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
DeferredLayerUpdater(renderthread::RenderThread & thread,Layer * layer)27 DeferredLayerUpdater::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
~DeferredLayerUpdater()43 DeferredLayerUpdater::~DeferredLayerUpdater() {
44 SkSafeUnref(mColorFilter);
45 setTransform(nullptr);
46 mLayer->postDecStrong();
47 mLayer = nullptr;
48 }
49
setPaint(const SkPaint * paint)50 void 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
apply()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->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
doUpdateTexImage()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 != 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
detachSurfaceTexture()120 void 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