Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2014 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 #include "DeferredLayerUpdater.h"
     17 
     18 #include "renderstate/RenderState.h"
     19 #include "utils/PaintUtils.h"
     20 
     21 namespace android {
     22 namespace uirenderer {
     23 
     24 DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
     25         : mRenderState(renderState)
     26         , mBlend(false)
     27         , mSurfaceTexture(nullptr)
     28         , mTransform(nullptr)
     29         , mGLContextAttached(false)
     30         , mUpdateTexImage(false)
     31         , mLayer(nullptr) {
     32     renderState.registerContextCallback(this);
     33 }
     34 
     35 DeferredLayerUpdater::~DeferredLayerUpdater() {
     36     setTransform(nullptr);
     37     mRenderState.removeContextCallback(this);
     38     destroyLayer();
     39 }
     40 
     41 void DeferredLayerUpdater::onContextDestroyed() {
     42     destroyLayer();
     43 }
     44 
     45 void DeferredLayerUpdater::destroyLayer() {
     46     if (!mLayer) {
     47         return;
     48     }
     49 
     50     if (mSurfaceTexture.get() && mGLContextAttached) {
     51         mSurfaceTexture->detachFromView();
     52         mGLContextAttached = false;
     53     }
     54 
     55     mLayer->postDecStrong();
     56 
     57     mLayer = nullptr;
     58 }
     59 
     60 void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
     61     mAlpha = PaintUtils::getAlphaDirect(paint);
     62     mMode = PaintUtils::getBlendModeDirect(paint);
     63     if (paint) {
     64         mColorFilter = paint->refColorFilter();
     65     } else {
     66         mColorFilter.reset();
     67     }
     68 }
     69 
     70 void DeferredLayerUpdater::apply() {
     71     if (!mLayer) {
     72         mLayer = new Layer(mRenderState, mColorFilter, mAlpha, mMode);
     73     }
     74 
     75     mLayer->setColorFilter(mColorFilter);
     76     mLayer->setAlpha(mAlpha, mMode);
     77 
     78     if (mSurfaceTexture.get()) {
     79         if (!mGLContextAttached) {
     80             mGLContextAttached = true;
     81             mUpdateTexImage = true;
     82             mSurfaceTexture->attachToView();
     83         }
     84         if (mUpdateTexImage) {
     85             mUpdateTexImage = false;
     86             sk_sp<SkImage> layerImage;
     87             SkMatrix textureTransform;
     88             bool queueEmpty = true;
     89             // If the SurfaceTexture queue is in synchronous mode, need to discard all
     90             // but latest frame. Since we can't tell which mode it is in,
     91             // do this unconditionally.
     92             do {
     93                 layerImage = mSurfaceTexture->dequeueImage(textureTransform, &queueEmpty,
     94                         mRenderState);
     95             } while (layerImage.get() && (!queueEmpty));
     96             if (layerImage.get()) {
     97                 // force filtration if buffer size != layer size
     98                 bool forceFilter = mWidth != layerImage->width() || mHeight != layerImage->height();
     99                 updateLayer(forceFilter, textureTransform, layerImage);
    100             }
    101         }
    102 
    103         if (mTransform) {
    104             mLayer->getTransform() = *mTransform;
    105             setTransform(nullptr);
    106         }
    107     }
    108 }
    109 
    110 void DeferredLayerUpdater::updateLayer(bool forceFilter, const SkMatrix& textureTransform,
    111         const sk_sp<SkImage>& layerImage) {
    112     mLayer->setBlend(mBlend);
    113     mLayer->setForceFilter(forceFilter);
    114     mLayer->setSize(mWidth, mHeight);
    115     mLayer->getTexTransform() = textureTransform;
    116     mLayer->setImage(layerImage);
    117 }
    118 
    119 void DeferredLayerUpdater::detachSurfaceTexture() {
    120     if (mSurfaceTexture.get()) {
    121         destroyLayer();
    122         mSurfaceTexture = nullptr;
    123     }
    124 }
    125 
    126 } /* namespace uirenderer */
    127 } /* namespace android */
    128