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 24 namespace android { 25 namespace uirenderer { 26 27 DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer) 28 : mSurfaceTexture(0) 29 , mTransform(0) 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 43 DeferredLayerUpdater::~DeferredLayerUpdater() { 44 SkSafeUnref(mColorFilter); 45 setTransform(0); 46 mLayer->postDecStrong(); 47 mLayer = 0; 48 } 49 50 void DeferredLayerUpdater::setPaint(const SkPaint* paint) { 51 OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode); 52 SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : NULL; 53 SkRefCnt_SafeAssign(mColorFilter, colorFilter); 54 } 55 56 bool 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->getTexture()); 66 } 67 if (mUpdateTexImage) { 68 mUpdateTexImage = false; 69 doUpdateTexImage(); 70 } 71 if (mTransform) { 72 mLayer->getTransform().load(*mTransform); 73 setTransform(0); 74 } 75 } 76 return success; 77 } 78 79 void 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 != NULL) { 99 // force filtration if buffer size != layer size 100 forceFilter = mWidth != buffer->getWidth() 101 || mHeight != 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 LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, 113 !mBlend, forceFilter, renderTarget, transform); 114 } 115 } 116 117 void DeferredLayerUpdater::detachSurfaceTexture() { 118 if (mSurfaceTexture.get()) { 119 mRenderThread.eglManager().requireGlContext(); 120 status_t err = mSurfaceTexture->detachFromContext(); 121 if (err != 0) { 122 // TODO: Elevate to fatal exception 123 ALOGE("Failed to detach SurfaceTexture from context %d", err); 124 } 125 mSurfaceTexture = 0; 126 mLayer->clearTexture(); 127 } 128 } 129 130 } /* namespace uirenderer */ 131 } /* namespace android */ 132