DeferredLayerUpdater.cpp revision 749906b468912dab7bf69a86e852deac3e80b0cc
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 "OpenGLRenderer.h"
19
20#include "LayerRenderer.h"
21#include "renderthread/EglManager.h"
22#include "renderthread/RenderTask.h"
23
24namespace android {
25namespace uirenderer {
26
27class DeleteLayerTask : public renderthread::RenderTask {
28public:
29    DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer)
30        : mEglManager(eglManager)
31        , mLayer(layer)
32    {}
33
34    virtual void run() {
35        mEglManager.requireGlContext();
36        LayerRenderer::destroyLayer(mLayer);
37        mLayer = 0;
38        delete this;
39    }
40
41private:
42    renderthread::EglManager& mEglManager;
43    Layer* mLayer;
44};
45
46DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer)
47        : mSurfaceTexture(0)
48        , mTransform(0)
49        , mNeedsGLContextAttach(false)
50        , mUpdateTexImage(false)
51        , mLayer(layer)
52        , mCaches(Caches::getInstance())
53        , mRenderThread(thread) {
54    mWidth = mLayer->layer.getWidth();
55    mHeight = mLayer->layer.getHeight();
56    mBlend = mLayer->isBlend();
57    mColorFilter = SkSafeRef(mLayer->getColorFilter());
58    mAlpha = mLayer->getAlpha();
59    mMode = mLayer->getMode();
60}
61
62DeferredLayerUpdater::~DeferredLayerUpdater() {
63    SkSafeUnref(mColorFilter);
64    setTransform(0);
65    mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer));
66    mLayer = 0;
67}
68
69void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
70    OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode);
71    SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : NULL;
72    SkRefCnt_SafeAssign(mColorFilter, colorFilter);
73}
74
75bool DeferredLayerUpdater::apply() {
76    bool success = true;
77    // These properties are applied the same to both layer types
78    mLayer->setColorFilter(mColorFilter);
79    mLayer->setAlpha(mAlpha, mMode);
80
81    if (mSurfaceTexture.get()) {
82        if (mNeedsGLContextAttach) {
83            mNeedsGLContextAttach = false;
84            mSurfaceTexture->attachToContext(mLayer->getTexture());
85        }
86        if (mUpdateTexImage) {
87            mUpdateTexImage = false;
88            doUpdateTexImage();
89        }
90        if (mTransform) {
91            mLayer->getTransform().load(*mTransform);
92            setTransform(0);
93        }
94    }
95    return success;
96}
97
98void DeferredLayerUpdater::doUpdateTexImage() {
99    if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
100        float transform[16];
101
102        int64_t frameNumber = mSurfaceTexture->getFrameNumber();
103        // If the GLConsumer queue is in synchronous mode, need to discard all
104        // but latest frame, using the frame number to tell when we no longer
105        // have newer frames to target. Since we can't tell which mode it is in,
106        // do this unconditionally.
107        int dropCounter = 0;
108        while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
109            int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
110            if (newFrameNumber == frameNumber) break;
111            frameNumber = newFrameNumber;
112            dropCounter++;
113        }
114
115        bool forceFilter = false;
116        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
117        if (buffer != NULL) {
118            // force filtration if buffer size != layer size
119            forceFilter = mWidth != buffer->getWidth()
120                    || mHeight != buffer->getHeight();
121        }
122
123        #if DEBUG_RENDERER
124        if (dropCounter > 0) {
125            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
126        }
127        #endif
128        mSurfaceTexture->getTransformMatrix(transform);
129        GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
130
131        LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight,
132                !mBlend, forceFilter, renderTarget, transform);
133    }
134}
135
136void DeferredLayerUpdater::detachSurfaceTexture() {
137    if (mSurfaceTexture.get()) {
138        mRenderThread.eglManager().requireGlContext();
139        status_t err = mSurfaceTexture->detachFromContext();
140        if (err != 0) {
141            // TODO: Elevate to fatal exception
142            ALOGE("Failed to detach SurfaceTexture from context %d", err);
143        }
144        mSurfaceTexture = 0;
145        mLayer->clearTexture();
146    }
147}
148
149} /* namespace uirenderer */
150} /* namespace android */
151