104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck/*
204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * Copyright (C) 2014 The Android Open Source Project
304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck *
404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * Licensed under the Apache License, Version 2.0 (the "License");
504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * you may not use this file except in compliance with the License.
604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * You may obtain a copy of the License at
704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck *
804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck *      http://www.apache.org/licenses/LICENSE-2.0
904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck *
1004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * Unless required by applicable law or agreed to in writing, software
1104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * distributed under the License is distributed on an "AS IS" BASIS,
1204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * See the License for the specific language governing permissions and
1404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck * limitations under the License.
1504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck */
1604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck#include "DeferredLayerUpdater.h"
1704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
1804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck#include "OpenGLRenderer.h"
1904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
2004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck#include "LayerRenderer.h"
21749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck#include "renderthread/EglManager.h"
22749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck#include "renderthread/RenderTask.h"
2304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
2404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Recknamespace android {
2504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Recknamespace uirenderer {
2604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
27749906b468912dab7bf69a86e852deac3e80b0ccJohn ReckDeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer)
2825fbb3fa1138675379102a44405852555cefccbdJohn Reck        : mSurfaceTexture(0)
2904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        , mTransform(0)
3004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        , mNeedsGLContextAttach(false)
3104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        , mUpdateTexImage(false)
3204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        , mLayer(layer)
33d72e0a339b54af0c4e731513bbad120dff694723John Reck        , mCaches(Caches::getInstance())
34749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck        , mRenderThread(thread) {
3504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mWidth = mLayer->layer.getWidth();
3604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mHeight = mLayer->layer.getHeight();
3704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mBlend = mLayer->isBlend();
38674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    mColorFilter = SkSafeRef(mLayer->getColorFilter());
3904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mAlpha = mLayer->getAlpha();
4004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mMode = mLayer->getMode();
4104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
4204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
4304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John ReckDeferredLayerUpdater::~DeferredLayerUpdater() {
44674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    SkSafeUnref(mColorFilter);
458ca3eecc2b7fe507d3482745efc4cd2567ad15a1John Reck    setTransform(0);
460e89e2b7bcb2c035e8cee77f93120e7c5617f8d2John Reck    mLayer->postDecStrong();
47749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck    mLayer = 0;
4804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
4904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
50674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenbergervoid DeferredLayerUpdater::setPaint(const SkPaint* paint) {
51674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode);
52674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : NULL;
5304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    SkRefCnt_SafeAssign(mColorFilter, colorFilter);
5404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
5504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
5668bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckbool DeferredLayerUpdater::apply() {
5704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    bool success = true;
5804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    // These properties are applied the same to both layer types
5904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mLayer->setColorFilter(mColorFilter);
6004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mLayer->setAlpha(mAlpha, mMode);
6104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
6225fbb3fa1138675379102a44405852555cefccbdJohn Reck    if (mSurfaceTexture.get()) {
6304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        if (mNeedsGLContextAttach) {
6404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            mNeedsGLContextAttach = false;
6504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            mSurfaceTexture->attachToContext(mLayer->getTexture());
6604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
6704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        if (mUpdateTexImage) {
6804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            mUpdateTexImage = false;
6904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            doUpdateTexImage();
7004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
7104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        if (mTransform) {
7204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            mLayer->getTransform().load(*mTransform);
7304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            setTransform(0);
7404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
7504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    }
7604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    return success;
7704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
7804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
7904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reckvoid DeferredLayerUpdater::doUpdateTexImage() {
8004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
8104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        float transform[16];
8204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
8304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        int64_t frameNumber = mSurfaceTexture->getFrameNumber();
8404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // If the GLConsumer queue is in synchronous mode, need to discard all
8504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // but latest frame, using the frame number to tell when we no longer
8604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // have newer frames to target. Since we can't tell which mode it is in,
8704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // do this unconditionally.
8804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        int dropCounter = 0;
8904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
9004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
9104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            if (newFrameNumber == frameNumber) break;
9204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            frameNumber = newFrameNumber;
9304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            dropCounter++;
9404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
959757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik
969757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        bool forceFilter = false;
979757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
989757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        if (buffer != NULL) {
999757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik            // force filtration if buffer size != layer size
1009757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik            forceFilter = mWidth != buffer->getWidth()
1019757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik                    || mHeight != buffer->getHeight();
1029757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        }
1039757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik
10404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        #if DEBUG_RENDERER
10504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        if (dropCounter > 0) {
10604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
10704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
10804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        #endif
10904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        mSurfaceTexture->getTransformMatrix(transform);
11004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
11104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
1129757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight,
1139757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik                !mBlend, forceFilter, renderTarget, transform);
11404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    }
11504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
11604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
117918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reckvoid DeferredLayerUpdater::detachSurfaceTexture() {
118918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    if (mSurfaceTexture.get()) {
119749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck        mRenderThread.eglManager().requireGlContext();
120749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck        status_t err = mSurfaceTexture->detachFromContext();
121749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck        if (err != 0) {
122749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck            // TODO: Elevate to fatal exception
123749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck            ALOGE("Failed to detach SurfaceTexture from context %d", err);
124749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck        }
125918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck        mSurfaceTexture = 0;
126918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck        mLayer->clearTexture();
127918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    }
128918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck}
129918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck
13004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck} /* namespace uirenderer */
13104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck} /* namespace android */
132