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
188cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel#include "GlLayer.h"
1945ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel#include "VkLayer.h"
203e9999bd866fac71c72e6b484a9836c87c328a08sergeyv#include "renderstate/RenderState.h"
21749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck#include "renderthread/EglManager.h"
22749906b468912dab7bf69a86e852deac3e80b0ccJohn Reck#include "renderthread/RenderTask.h"
235e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik#include "utils/PaintUtils.h"
2404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
2504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Recknamespace android {
2604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Recknamespace uirenderer {
2704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
283e9999bd866fac71c72e6b484a9836c87c328a08sergeyvDeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState, CreateLayerFn createLayerFn,
293e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        Layer::Api layerApi)
303e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        : mRenderState(renderState)
313e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        , mBlend(false)
323e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        , mSurfaceTexture(nullptr)
33d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , mTransform(nullptr)
3400eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        , mGLContextAttached(false)
3504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        , mUpdateTexImage(false)
363e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        , mLayer(nullptr)
373e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        , mLayerApi(layerApi)
383e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        , mCreateLayerFn(createLayerFn) {
393e9999bd866fac71c72e6b484a9836c87c328a08sergeyv    renderState.registerDeferredLayerUpdater(this);
4004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
4104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
4204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John ReckDeferredLayerUpdater::~DeferredLayerUpdater() {
43674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenberger    SkSafeUnref(mColorFilter);
44d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    setTransform(nullptr);
453e9999bd866fac71c72e6b484a9836c87c328a08sergeyv    mRenderState.unregisterDeferredLayerUpdater(this);
463e9999bd866fac71c72e6b484a9836c87c328a08sergeyv    destroyLayer();
473e9999bd866fac71c72e6b484a9836c87c328a08sergeyv}
483e9999bd866fac71c72e6b484a9836c87c328a08sergeyv
493e9999bd866fac71c72e6b484a9836c87c328a08sergeyvvoid DeferredLayerUpdater::destroyLayer() {
5000eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv    if (!mLayer) {
5100eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        return;
5200eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv    }
5300eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv
5400eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv    if (mSurfaceTexture.get() && mLayerApi == Layer::Api::OpenGL && mGLContextAttached) {
5500eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        status_t err = mSurfaceTexture->detachFromContext();
5600eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        mGLContextAttached = false;
5700eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        if (err != 0) {
5800eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv            // TODO: Elevate to fatal exception
5900eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv            ALOGE("Failed to detach SurfaceTexture from context %d", err);
6000eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        }
613e9999bd866fac71c72e6b484a9836c87c328a08sergeyv    }
6200eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv
6300eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv    mLayer->postDecStrong();
6400eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv    mLayer = nullptr;
6504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
6604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
67674554fc36932ca50b15bba41ac6f650254d4e72Derek Sollenbergervoid DeferredLayerUpdater::setPaint(const SkPaint* paint) {
68bf6f0f260886a04a1680c7f9917124a751322ca4Chris Craik    mAlpha = PaintUtils::getAlphaDirect(paint);
69260ab726486317496bc12a57d599ea96dcde3284Mike Reed    mMode = PaintUtils::getBlendModeDirect(paint);
70d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr;
7104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    SkRefCnt_SafeAssign(mColorFilter, colorFilter);
7204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
7304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
74d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craikvoid DeferredLayerUpdater::apply() {
753e9999bd866fac71c72e6b484a9836c87c328a08sergeyv    if (!mLayer) {
763e9999bd866fac71c72e6b484a9836c87c328a08sergeyv        mLayer = mCreateLayerFn(mRenderState, mWidth, mHeight, mColorFilter, mAlpha, mMode, mBlend);
773e9999bd866fac71c72e6b484a9836c87c328a08sergeyv    }
783e9999bd866fac71c72e6b484a9836c87c328a08sergeyv
7904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mLayer->setColorFilter(mColorFilter);
8004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    mLayer->setAlpha(mAlpha, mMode);
8104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
8225fbb3fa1138675379102a44405852555cefccbdJohn Reck    if (mSurfaceTexture.get()) {
8345ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel        if (mLayer->getApi() == Layer::Api::Vulkan) {
8445ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel            if (mUpdateTexImage) {
8545ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                mUpdateTexImage = false;
8645ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                doUpdateVkTexImage();
8745ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel            }
8845ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel        } else {
8945ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel            LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
9045ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                                "apply surfaceTexture with non GL backend %x, GL %x, VK %x",
9145ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                                mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
9200eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv            if (!mGLContextAttached) {
9300eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv                mGLContextAttached = true;
9400eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv                mUpdateTexImage = true;
9545ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                mSurfaceTexture->attachToContext(static_cast<GlLayer*>(mLayer)->getTextureId());
9645ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel            }
9745ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel            if (mUpdateTexImage) {
9845ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                mUpdateTexImage = false;
9945ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                doUpdateTexImage();
10045ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel            }
10109df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik            GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
10209df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik            static_cast<GlLayer*>(mLayer)->setRenderTarget(renderTarget);
10304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
10404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        if (mTransform) {
10504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            mLayer->getTransform().load(*mTransform);
106d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik            setTransform(nullptr);
10704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
10804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    }
10904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck}
11004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
11104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reckvoid DeferredLayerUpdater::doUpdateTexImage() {
1128cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::OpenGL,
1138cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel                        "doUpdateTexImage non GL backend %x, GL %x, VK %x",
1148cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel                        mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
11504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck    if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
11604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        float transform[16];
11704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
11804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        int64_t frameNumber = mSurfaceTexture->getFrameNumber();
11904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // If the GLConsumer queue is in synchronous mode, need to discard all
12004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // but latest frame, using the frame number to tell when we no longer
12104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // have newer frames to target. Since we can't tell which mode it is in,
12204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        // do this unconditionally.
12304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        int dropCounter = 0;
12404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
12504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
12604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            if (newFrameNumber == frameNumber) break;
12704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            frameNumber = newFrameNumber;
12804fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            dropCounter++;
12904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
1309757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik
1319757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        bool forceFilter = false;
1329757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
133d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        if (buffer != nullptr) {
1349757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik            // force filtration if buffer size != layer size
13532d2e769ea6052aca2232c571a82ed7a7f8c996aDan Stoza            forceFilter = mWidth != static_cast<int>(buffer->getWidth())
13632d2e769ea6052aca2232c571a82ed7a7f8c996aDan Stoza                    || mHeight != static_cast<int>(buffer->getHeight());
1379757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik        }
1389757ac0b9d62f6aea5e47cfb375f445c78bb7897Chris Craik
13904fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        #if DEBUG_RENDERER
14004fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        if (dropCounter > 0) {
14104fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck            RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
14204fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        }
14304fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        #endif
14404fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck        mSurfaceTexture->getTransformMatrix(transform);
14504fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck
14609df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik        updateLayer(forceFilter, transform);
14756ad6ec42f814e9e61030ff819cac4e5d31def8bDerek Sollenberger    }
14856ad6ec42f814e9e61030ff819cac4e5d31def8bDerek Sollenberger}
14956ad6ec42f814e9e61030ff819cac4e5d31def8bDerek Sollenberger
15045ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Danielvoid DeferredLayerUpdater::doUpdateVkTexImage() {
15145ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    LOG_ALWAYS_FATAL_IF(mLayer->getApi() != Layer::Api::Vulkan,
15245ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                        "updateLayer non Vulkan backend %x, GL %x, VK %x",
15345ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel                        mLayer->getApi(), Layer::Api::OpenGL, Layer::Api::Vulkan);
15445ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel
15545ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    static const mat4 identityMatrix;
15609df887c9078a34f2bda32c83734b7f75c0a60ffChris Craik    updateLayer(false, identityMatrix.data);
15745ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel
15845ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    VkLayer* vkLayer = static_cast<VkLayer*>(mLayer);
15945ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    vkLayer->updateTexture();
16045ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel}
16145ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel
16209df887c9078a34f2bda32c83734b7f75c0a60ffChris Craikvoid DeferredLayerUpdater::updateLayer(bool forceFilter, const float* textureTransform) {
16345ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    mLayer->setBlend(mBlend);
16445ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    mLayer->setForceFilter(forceFilter);
16545ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    mLayer->setSize(mWidth, mHeight);
16645ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel    mLayer->getTexTransform().load(textureTransform);
16745ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel}
16845ec62ba72c5017fae7d8baab20bfb0d4c99c627Greg Daniel
169918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reckvoid DeferredLayerUpdater::detachSurfaceTexture() {
170918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    if (mSurfaceTexture.get()) {
17100eb43dbc04083eab85fbb1a9589e2548f2004edsergeyv        destroyLayer();
172d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        mSurfaceTexture = nullptr;
173918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck    }
174918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck}
175918ad523b2780e0c893f3d2a32d4ec13f2a7e921John Reck
17604fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck} /* namespace uirenderer */
17704fc583c3dd3144bc6b718fcac4b3e1afdfdb067John Reck} /* namespace android */
178