• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
18 #include "GlLayer.h"
19 #include "VkLayer.h"
20 
21 #include "GrBackendSurface.h"
22 #include "SkColorFilter.h"
23 #include "SkSurface.h"
24 #include "gl/GrGLTypes.h"
25 
26 namespace android {
27 namespace uirenderer {
28 namespace skiapipeline {
29 
onDraw(SkCanvas * canvas)30 void LayerDrawable::onDraw(SkCanvas* canvas) {
31     Layer* layer = mLayerUpdater->backingLayer();
32     if (layer) {
33         DrawLayer(canvas->getGrContext(), canvas, layer);
34     }
35 }
36 
DrawLayer(GrContext * context,SkCanvas * canvas,Layer * layer,const SkRect * dstRect)37 bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
38                               const SkRect* dstRect) {
39     if (context == nullptr) {
40         SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
41         return false;
42     }
43     // transform the matrix based on the layer
44     SkMatrix layerTransform;
45     layer->getTransform().copyTo(layerTransform);
46     sk_sp<SkImage> layerImage;
47     const int layerWidth = layer->getWidth();
48     const int layerHeight = layer->getHeight();
49     if (layer->getApi() == Layer::Api::OpenGL) {
50         GlLayer* glLayer = static_cast<GlLayer*>(layer);
51         GrGLTextureInfo externalTexture;
52         externalTexture.fTarget = glLayer->getRenderTarget();
53         externalTexture.fID = glLayer->getTextureId();
54         // The format may not be GL_RGBA8, but given the DeferredLayerUpdater and GLConsumer don't
55         // expose that info we use it as our default.  Further, given that we only use this texture
56         // as a source this will not impact how Skia uses the texture.  The only potential affect
57         // this is anticipated to have is that for some format types if we are not bound as an OES
58         // texture we may get invalid results for SKP capture if we read back the texture.
59         externalTexture.fFormat = GL_RGBA8;
60         GrBackendTexture backendTexture(layerWidth, layerHeight, GrMipMapped::kNo, externalTexture);
61         layerImage = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
62                                               kPremul_SkAlphaType, nullptr);
63     } else {
64         SkASSERT(layer->getApi() == Layer::Api::Vulkan);
65         VkLayer* vkLayer = static_cast<VkLayer*>(layer);
66         canvas->clear(SK_ColorGREEN);
67         layerImage = vkLayer->getImage();
68     }
69 
70     if (layerImage) {
71         SkMatrix textureMatrixInv;
72         layer->getTexTransform().copyTo(textureMatrixInv);
73         // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
74         // use bottom left origin and remove flipV and invert transformations.
75         SkMatrix flipV;
76         flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
77         textureMatrixInv.preConcat(flipV);
78         textureMatrixInv.preScale(1.0f / layerWidth, 1.0f / layerHeight);
79         textureMatrixInv.postScale(layerWidth, layerHeight);
80         SkMatrix textureMatrix;
81         if (!textureMatrixInv.invert(&textureMatrix)) {
82             textureMatrix = textureMatrixInv;
83         }
84 
85         SkMatrix matrix = SkMatrix::Concat(layerTransform, textureMatrix);
86 
87         SkPaint paint;
88         paint.setAlpha(layer->getAlpha());
89         paint.setBlendMode(layer->getMode());
90         paint.setColorFilter(layer->getColorSpaceWithFilter());
91 
92         const bool nonIdentityMatrix = !matrix.isIdentity();
93         if (nonIdentityMatrix) {
94             canvas->save();
95             canvas->concat(matrix);
96         }
97         if (dstRect) {
98             SkMatrix matrixInv;
99             if (!matrix.invert(&matrixInv)) {
100                 matrixInv = matrix;
101             }
102             SkRect srcRect = SkRect::MakeIWH(layerWidth, layerHeight);
103             matrixInv.mapRect(&srcRect);
104             SkRect skiaDestRect = *dstRect;
105             matrixInv.mapRect(&skiaDestRect);
106             canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
107                                   SkCanvas::kFast_SrcRectConstraint);
108         } else {
109             canvas->drawImage(layerImage.get(), 0, 0, &paint);
110         }
111         // restore the original matrix
112         if (nonIdentityMatrix) {
113             canvas->restore();
114         }
115     }
116 
117     return layerImage;
118 }
119 
120 };  // namespace skiapipeline
121 };  // namespace uirenderer
122 };  // namespace android
123