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