DeferredLayerUpdater.cpp revision 260ab726486317496bc12a57d599ea96dcde3284
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 "renderthread/EglManager.h"
19#include "renderthread/RenderTask.h"
20#include "utils/PaintUtils.h"
21
22namespace android {
23namespace uirenderer {
24
25DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer)
26        : mSurfaceTexture(nullptr)
27        , mTransform(nullptr)
28        , mNeedsGLContextAttach(false)
29        , mUpdateTexImage(false)
30        , mLayer(layer) {
31    mWidth = mLayer->getWidth();
32    mHeight = mLayer->getHeight();
33    mBlend = mLayer->isBlend();
34    mColorFilter = SkSafeRef(mLayer->getColorFilter());
35    mAlpha = mLayer->getAlpha();
36    mMode = mLayer->getMode();
37}
38
39DeferredLayerUpdater::~DeferredLayerUpdater() {
40    SkSafeUnref(mColorFilter);
41    setTransform(nullptr);
42    mLayer->postDecStrong();
43    mLayer = nullptr;
44}
45
46void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
47    mAlpha = PaintUtils::getAlphaDirect(paint);
48    mMode = PaintUtils::getBlendModeDirect(paint);
49    SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr;
50    SkRefCnt_SafeAssign(mColorFilter, colorFilter);
51}
52
53void DeferredLayerUpdater::apply() {
54    mLayer->setColorFilter(mColorFilter);
55    mLayer->setAlpha(mAlpha, mMode);
56
57    if (mSurfaceTexture.get()) {
58        if (mNeedsGLContextAttach) {
59            mNeedsGLContextAttach = false;
60            mSurfaceTexture->attachToContext(mLayer->getTextureId());
61        }
62        if (mUpdateTexImage) {
63            mUpdateTexImage = false;
64            doUpdateTexImage();
65        }
66        if (mTransform) {
67            mLayer->getTransform().load(*mTransform);
68            setTransform(nullptr);
69        }
70    }
71}
72
73void DeferredLayerUpdater::doUpdateTexImage() {
74    if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
75        float transform[16];
76
77        int64_t frameNumber = mSurfaceTexture->getFrameNumber();
78        // If the GLConsumer queue is in synchronous mode, need to discard all
79        // but latest frame, using the frame number to tell when we no longer
80        // have newer frames to target. Since we can't tell which mode it is in,
81        // do this unconditionally.
82        int dropCounter = 0;
83        while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
84            int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
85            if (newFrameNumber == frameNumber) break;
86            frameNumber = newFrameNumber;
87            dropCounter++;
88        }
89
90        bool forceFilter = false;
91        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
92        if (buffer != nullptr) {
93            // force filtration if buffer size != layer size
94            forceFilter = mWidth != static_cast<int>(buffer->getWidth())
95                    || mHeight != static_cast<int>(buffer->getHeight());
96        }
97
98        #if DEBUG_RENDERER
99        if (dropCounter > 0) {
100            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
101        }
102        #endif
103        mSurfaceTexture->getTransformMatrix(transform);
104        GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
105
106        LOG_ALWAYS_FATAL_IF(renderTarget != GL_TEXTURE_2D && renderTarget != GL_TEXTURE_EXTERNAL_OES,
107                "doUpdateTexImage target %x, 2d %x, EXT %x",
108                renderTarget, GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL_OES);
109        updateLayer(forceFilter, renderTarget, transform);
110    }
111}
112
113void DeferredLayerUpdater::updateLayer(bool forceFilter, GLenum renderTarget,
114        const float* textureTransform) {
115    mLayer->setBlend(mBlend);
116    mLayer->setForceFilter(forceFilter);
117    mLayer->setSize(mWidth, mHeight);
118    mLayer->getTexTransform().load(textureTransform);
119
120    if (renderTarget != mLayer->getRenderTarget()) {
121        mLayer->setRenderTarget(renderTarget);
122        mLayer->bindTexture();
123        mLayer->setFilter(GL_NEAREST, false, true);
124        mLayer->setWrap(GL_CLAMP_TO_EDGE, false, true);
125    }
126}
127
128void DeferredLayerUpdater::detachSurfaceTexture() {
129    if (mSurfaceTexture.get()) {
130        status_t err = mSurfaceTexture->detachFromContext();
131        if (err != 0) {
132            // TODO: Elevate to fatal exception
133            ALOGE("Failed to detach SurfaceTexture from context %d", err);
134        }
135        mSurfaceTexture = nullptr;
136        mLayer->clearTexture();
137    }
138}
139
140} /* namespace uirenderer */
141} /* namespace android */
142