blob: 64e4b5f4463cd79925a7a80d55974cdc23f10f9e [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080022#include <math.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023
Mathias Agopiana67932f2011-04-20 14:20:59 -070024#include <cutils/compiler.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070025#include <cutils/native_handle.h>
Mathias Agopiana67932f2011-04-20 14:20:59 -070026#include <cutils/properties.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
28#include <utils/Errors.h>
29#include <utils/Log.h>
30#include <utils/StopWatch.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080031#include <utils/Trace.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032
Mathias Agopian3330b202009-10-05 17:07:12 -070033#include <ui/GraphicBuffer.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034#include <ui/PixelFormat.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080035
Mathias Agopian90ac7992012-02-25 18:48:35 -080036#include <gui/Surface.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037
38#include "clz.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070039#include "DisplayHardware/DisplayHardware.h"
40#include "DisplayHardware/HWComposer.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070041#include "GLExtensions.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080043#include "SurfaceFlinger.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070044#include "SurfaceTextureLayer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080045
46#define DEBUG_RESIZE 0
47
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048namespace android {
49
50// ---------------------------------------------------------------------------
51
Mathias Agopian96f08192010-06-02 23:28:45 -070052Layer::Layer(SurfaceFlinger* flinger,
53 DisplayID display, const sp<Client>& client)
54 : LayerBaseClient(flinger, display, client),
Mathias Agopiana67932f2011-04-20 14:20:59 -070055 mTextureName(-1U),
56 mQueuedFrames(0),
57 mCurrentTransform(0),
Mathias Agopian933389f2011-07-18 16:15:08 -070058 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
Mathias Agopiana67932f2011-04-20 14:20:59 -070059 mCurrentOpacity(true),
Mathias Agopian4d143ee2012-02-23 20:05:39 -080060 mRefreshPending(false),
Mathias Agopian82d7ab62012-01-19 18:34:40 -080061 mFrameLatencyNeeded(false),
62 mFrameLatencyOffset(0),
Mathias Agopian5bf3abe2011-03-11 17:01:07 -080063 mFormat(PIXEL_FORMAT_NONE),
Mathias Agopian1f7bec62010-06-25 18:02:21 -070064 mGLExtensions(GLExtensions::getInstance()),
Mathias Agopiana67932f2011-04-20 14:20:59 -070065 mOpaqueLayer(true),
Mathias Agopiand606de62010-05-10 20:06:11 -070066 mNeedsDithering(false),
Mathias Agopianb7e930d2010-06-01 15:12:58 -070067 mSecure(false),
Mathias Agopian933389f2011-07-18 16:15:08 -070068 mProtectedByApp(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080069{
Mathias Agopiana67932f2011-04-20 14:20:59 -070070 mCurrentCrop.makeInvalid();
71 glGenTextures(1, &mTextureName);
Jamie Gennise8696a42012-01-15 18:54:57 -080072}
73
Jesse Hallef194142012-06-14 14:45:17 -070074void Layer::onLayerDisplayed(HWComposer::HWCLayerInterface* layer) {
75 if (layer) {
76 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
77 }
78
Jamie Gennise8696a42012-01-15 18:54:57 -080079 if (mFrameLatencyNeeded) {
Mathias Agopian82d7ab62012-01-19 18:34:40 -080080 const DisplayHardware& hw(graphicPlane(0).displayHardware());
81 mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
82 mFrameStats[mFrameLatencyOffset].set = systemTime();
83 mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
Jamie Gennise8696a42012-01-15 18:54:57 -080084 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
85 mFrameLatencyNeeded = false;
86 }
Mathias Agopiand606de62010-05-10 20:06:11 -070087}
88
Mathias Agopiana67932f2011-04-20 14:20:59 -070089void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070090{
Mathias Agopiana67932f2011-04-20 14:20:59 -070091 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070092
Mathias Agopiana67932f2011-04-20 14:20:59 -070093 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
94 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
95 private:
96 wp<Layer> mLayer;
97 virtual void onFrameAvailable() {
98 sp<Layer> that(mLayer.promote());
99 if (that != 0) {
100 that->onFrameQueued();
101 }
102 }
103 };
Daniel Lamb2675792012-02-23 14:35:13 -0800104
105 // Creates a custom BufferQueue for SurfaceTexture to use
106 sp<BufferQueue> bq = new SurfaceTextureLayer();
107 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -0700108 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800109
Daniel Lamb2675792012-02-23 14:35:13 -0800110 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700111 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
112 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800113
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700114#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
115#warning "disabling triple buffering"
Mathias Agopiana67932f2011-04-20 14:20:59 -0700116 mSurfaceTexture->setBufferCountServer(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700117#else
118 mSurfaceTexture->setBufferCountServer(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800119#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700120}
121
Mathias Agopiana67932f2011-04-20 14:20:59 -0700122Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700123{
Mathias Agopian118d0242011-10-13 16:02:48 -0700124 mFlinger->postMessageAsync(
125 new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
Mathias Agopian96f08192010-06-02 23:28:45 -0700126}
127
Mathias Agopiana67932f2011-04-20 14:20:59 -0700128void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700129 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800130 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700131}
132
Mathias Agopiand606de62010-05-10 20:06:11 -0700133// called with SurfaceFlinger::mStateLock as soon as the layer is entered
134// in the purgatory list
135void Layer::onRemoved()
136{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700137 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700138}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700139
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700140void Layer::setName(const String8& name) {
141 LayerBase::setName(name);
142 mSurfaceTexture->setName(name);
143}
144
Daniel Lamb2675792012-02-23 14:35:13 -0800145void Layer::validateVisibility(const Transform& globalTransform) {
146 LayerBase::validateVisibility(globalTransform);
147
148 // This optimization allows the SurfaceTexture to bake in
149 // the rotation so hardware overlays can be used
150 mSurfaceTexture->setTransformHint(getTransformHint());
151}
152
Mathias Agopiana67932f2011-04-20 14:20:59 -0700153sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700155 class BSurface : public BnSurface, public LayerCleaner {
156 wp<const Layer> mOwner;
157 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
158 sp<ISurfaceTexture> res;
159 sp<const Layer> that( mOwner.promote() );
160 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800161 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700162 }
163 return res;
164 }
165 public:
166 BSurface(const sp<SurfaceFlinger>& flinger,
167 const sp<Layer>& layer)
168 : LayerCleaner(flinger, layer), mOwner(layer) { }
169 };
170 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800171 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800172}
173
Jamie Gennis582270d2011-08-17 18:19:00 -0700174wp<IBinder> Layer::getSurfaceTextureBinder() const
175{
Daniel Lamb2675792012-02-23 14:35:13 -0800176 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700177}
178
Mathias Agopianf9d93272009-06-19 17:00:27 -0700179status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180 PixelFormat format, uint32_t flags)
181{
Mathias Agopian401c2572009-09-23 19:16:27 -0700182 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183 PixelFormatInfo info;
184 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800185 if (err) {
186 ALOGE("unsupported pixelformat %d", format);
187 return err;
188 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800189
Mathias Agopian401c2572009-09-23 19:16:27 -0700190 // the display's pixel format
191 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700192 uint32_t const maxSurfaceDims = min(
193 hw.getMaxTextureSize(), hw.getMaxViewportDims());
194
195 // never allow a surface larger than what our underlying GL implementation
196 // can handle.
197 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800198 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700199 return BAD_VALUE;
200 }
201
Mathias Agopian401c2572009-09-23 19:16:27 -0700202 PixelFormatInfo displayInfo;
203 getPixelFormatInfo(hw.getFormat(), &displayInfo);
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700204 const uint32_t hwFlags = hw.getFlags();
205
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700206 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700207
Mathias Agopian3330b202009-10-05 17:07:12 -0700208 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800209 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700210 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
211 mCurrentOpacity = getOpacityForFormat(format);
212
213 mSurfaceTexture->setDefaultBufferSize(w, h);
214 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800215 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700216
Mathias Agopian401c2572009-09-23 19:16:27 -0700217 // we use the red index
218 int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
219 int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
220 mNeedsDithering = layerRedsize > displayRedSize;
221
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800222 return NO_ERROR;
223}
224
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700225Rect Layer::computeBufferCrop() const {
226 // Start with the SurfaceTexture's buffer crop...
227 Rect crop;
228 if (!mCurrentCrop.isEmpty()) {
229 crop = mCurrentCrop;
230 } else if (mActiveBuffer != NULL){
231 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
232 } else {
233 crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
234 }
235
236 // ... then reduce that in the same proportions as the window crop reduces
237 // the window size.
238 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700239 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700240 // Transform the window crop to match the buffer coordinate system,
241 // which means using the inverse of the current transform set on the
242 // SurfaceTexture.
243 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700244 int winWidth = s.active.w;
245 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700246 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
247 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
248 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700249 winWidth = s.active.h;
250 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700251 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700252 Rect winCrop = s.active.crop.transform(invTransform,
253 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700254
255 float xScale = float(crop.width()) / float(winWidth);
256 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700257 crop.left += int(ceilf(float(winCrop.left) * xScale));
258 crop.top += int(ceilf(float(winCrop.top) * yScale));
259 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
260 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700261 }
262
263 return crop;
264}
265
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700266void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700267{
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700268 LayerBaseClient::setGeometry(layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700269
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700270 // enable this layer
271 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700272
273 // we can't do alpha-fade with the hwc HAL
274 const State& s(drawingState());
275 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700276 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700277 }
278
Mathias Agopian29a367b2011-07-12 14:51:45 -0700279 /*
280 * Transformations are applied in this order:
281 * 1) buffer orientation/flip/mirror
282 * 2) state transformation (window manager)
283 * 3) layer orientation (screen orientation)
Mathias Agopiand992db32011-08-18 18:31:00 -0700284 * mTransform is already the composition of (2) and (3)
Mathias Agopian29a367b2011-07-12 14:51:45 -0700285 * (NOTE: the matrices are multiplied in reverse order)
286 */
287
288 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopiand992db32011-08-18 18:31:00 -0700289 const Transform tr(mTransform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700290
291 // this gives us only the "orientation" component of the transform
292 const uint32_t finalTransform = tr.getOrientation();
293
Mathias Agopiana350ff92010-08-10 17:14:02 -0700294 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700295 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700296 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700297 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700298 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700299 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700300 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700301}
302
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700303void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700304 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700305 // NOTE: buffer can be NULL if the client never drew into this
306 // layer yet, or if we ran out of memory
307 layer.setBuffer(buffer);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700308}
309
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800310void Layer::onDraw(const Region& clip) const
311{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800312 ATRACE_CALL();
313
Mathias Agopiana67932f2011-04-20 14:20:59 -0700314 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800315 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700316 // in fact never been drawn into. This happens frequently with
317 // SurfaceView because the WindowManager can't know when the client
318 // has drawn the first time.
319
320 // If there is nothing under us, we paint the screen in black, otherwise
321 // we just skip this update.
322
323 // figure out if there is something below us
324 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700325 const SurfaceFlinger::LayerVector& drawingLayers(
326 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700327 const size_t count = drawingLayers.size();
328 for (size_t i=0 ; i<count ; ++i) {
329 const sp<LayerBase>& layer(drawingLayers[i]);
330 if (layer.get() == static_cast<LayerBase const*>(this))
331 break;
332 under.orSelf(layer->visibleRegionScreen);
333 }
334 // if not everything below us is covered, we plug the holes!
335 Region holes(clip.subtract(under));
336 if (!holes.isEmpty()) {
Mathias Agopian0a917752010-06-14 21:20:00 -0700337 clearWithOpenGL(holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700338 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339 return;
340 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700341
Jamie Gennis9575f602011-10-07 14:51:16 -0700342 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700343 // TODO: we could be more subtle with isFixedSize()
344 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
345
346 // Query the texture matrix given our current filtering mode.
347 float textureMatrix[16];
348 mSurfaceTexture->setFilteringEnabled(useFiltering);
349 mSurfaceTexture->getTransformMatrix(textureMatrix);
350
351 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700352 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
353 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700354 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700355 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700356 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700357 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
358 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700359 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700360 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700361 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700362 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700363 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700364 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700365 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700366 glMatrixMode(GL_TEXTURE);
367 glLoadIdentity();
368 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700369 glDisable(GL_TEXTURE_EXTERNAL_OES);
370 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700371 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700372
373 drawWithOpenGL(clip);
374
Mathias Agopianc492e672011-10-18 14:49:27 -0700375 glDisable(GL_TEXTURE_EXTERNAL_OES);
376 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800377}
378
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800379// As documented in libhardware header, formats in the range
380// 0x100 - 0x1FF are specific to the HAL implementation, and
381// are known to have no alpha channel
382// TODO: move definition for device-specific range into
383// hardware.h, instead of using hard-coded values here.
384#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
385
Mathias Agopiana67932f2011-04-20 14:20:59 -0700386bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800387{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700388 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
389 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800390 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700391 PixelFormatInfo info;
392 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
393 // in case of error (unknown format), we assume no blending
394 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800395}
396
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800397
Mathias Agopiana67932f2011-04-20 14:20:59 -0700398bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700399{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700400 // if we don't have a buffer yet, we're translucent regardless of the
401 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700402 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700403 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700404 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700405
406 // if the layer has the opaque flag, then we're always opaque,
407 // otherwise we use the current buffer's format.
408 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700409}
410
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800411bool Layer::isProtected() const
412{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700413 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800414 return (activeBuffer != 0) &&
415 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
416}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700417
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800418uint32_t Layer::doTransaction(uint32_t flags)
419{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800420 ATRACE_CALL();
421
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800422 const Layer::State& front(drawingState());
423 const Layer::State& temp(currentState());
424
Mathias Agopian4824d402012-06-04 18:16:30 -0700425 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
426 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700427
428 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700429 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000430 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700431 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
432 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
433 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
434 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
435 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
436 this, mCurrentScalingMode,
437 temp.active.w, temp.active.h,
438 temp.active.crop.left,
439 temp.active.crop.top,
440 temp.active.crop.right,
441 temp.active.crop.bottom,
442 temp.active.crop.getWidth(),
443 temp.active.crop.getHeight(),
444 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700445 temp.requested.crop.left,
446 temp.requested.crop.top,
447 temp.requested.crop.right,
448 temp.requested.crop.bottom,
449 temp.requested.crop.getWidth(),
450 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700451 front.active.w, front.active.h,
452 front.active.crop.left,
453 front.active.crop.top,
454 front.active.crop.right,
455 front.active.crop.bottom,
456 front.active.crop.getWidth(),
457 front.active.crop.getHeight(),
458 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700459 front.requested.crop.left,
460 front.requested.crop.top,
461 front.requested.crop.right,
462 front.requested.crop.bottom,
463 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700464 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800465
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700466 // record the new size, form this point on, when the client request
467 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700468 mSurfaceTexture->setDefaultBufferSize(
469 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800470 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700471
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700472 if (!isFixedSize()) {
473
474 const bool resizePending = (temp.requested.w != temp.active.w) ||
475 (temp.requested.h != temp.active.h);
476
477 if (resizePending) {
478 // don't let LayerBase::doTransaction update the drawing state
479 // if we have a pending resize, unless we are in fixed-size mode.
480 // the drawing state will be updated only once we receive a buffer
481 // with the correct size.
482 //
483 // in particular, we want to make sure the clip (which is part
484 // of the geometry state) is latched together with the size but is
485 // latched immediately when no resizing is involved.
486
487 flags |= eDontUpdateGeometryState;
488 }
489 }
490
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800491 return LayerBase::doTransaction(flags);
492}
493
Mathias Agopiana138f892010-05-21 17:24:35 -0700494bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700495 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700496}
497
498bool Layer::isCropped() const {
499 return !mCurrentCrop.isEmpty();
500}
501
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800502// ----------------------------------------------------------------------------
503// pageflip handling...
504// ----------------------------------------------------------------------------
505
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800506bool Layer::onPreComposition() {
507 mRefreshPending = false;
508 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800509}
510
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800511void Layer::lockPageFlip(bool& recomputeVisibleRegions)
512{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800513 ATRACE_CALL();
514
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700515 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800516
517 // if we've already called updateTexImage() without going through
518 // a composition step, we have to skip this layer at this point
519 // because we cannot call updateTeximage() without a corresponding
520 // compositionComplete() call.
521 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800522 if (mRefreshPending) {
523 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800524 return;
525 }
526
Jamie Gennis351a5132011-09-14 18:23:37 -0700527 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700528 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700529 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700530
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700531 // signal another event if we have more frames pending
532 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800533 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700534 }
535
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700536 struct Reject : public SurfaceTexture::BufferRejecter {
537 Layer::State& front;
538 Layer::State& current;
539 bool& recomputeVisibleRegions;
540 Reject(Layer::State& front, Layer::State& current,
541 bool& recomputeVisibleRegions)
542 : front(front), current(current),
543 recomputeVisibleRegions(recomputeVisibleRegions) {
544 }
545
546 virtual bool reject(const sp<GraphicBuffer>& buf,
547 const BufferQueue::BufferItem& item) {
548 if (buf == NULL) {
549 return false;
550 }
551
552 uint32_t bufWidth = buf->getWidth();
553 uint32_t bufHeight = buf->getHeight();
554
555 // check that we received a buffer of the right size
556 // (Take the buffer's orientation into account)
557 if (item.mTransform & Transform::ROT_90) {
558 swap(bufWidth, bufHeight);
559 }
560
561
562 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
563 if (front.active != front.requested) {
564
565 if (isFixedSize ||
566 (bufWidth == front.requested.w &&
567 bufHeight == front.requested.h))
568 {
569 // Here we pretend the transaction happened by updating the
570 // current and drawing states. Drawing state is only accessed
571 // in this thread, no need to have it locked
572 front.active = front.requested;
573
574 // We also need to update the current state so that
575 // we don't end-up overwriting the drawing state with
576 // this stale current state during the next transaction
577 //
578 // NOTE: We don't need to hold the transaction lock here
579 // because State::active is only accessed from this thread.
580 current.active = front.active;
581
582 // recompute visible region
583 recomputeVisibleRegions = true;
584 }
585
586 ALOGD_IF(DEBUG_RESIZE,
587 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
588 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
589 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
590 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
591 front.active.w, front.active.h,
592 front.active.crop.left,
593 front.active.crop.top,
594 front.active.crop.right,
595 front.active.crop.bottom,
596 front.active.crop.getWidth(),
597 front.active.crop.getHeight(),
598 front.requested.w, front.requested.h,
599 front.requested.crop.left,
600 front.requested.crop.top,
601 front.requested.crop.right,
602 front.requested.crop.bottom,
603 front.requested.crop.getWidth(),
604 front.requested.crop.getHeight());
605 }
606
607 if (!isFixedSize) {
608 if (front.active.w != bufWidth ||
609 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700610 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700611 return true;
612 }
613 }
614 return false;
615 }
616 };
617
618
619 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
620
621 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700622 // something happened!
623 recomputeVisibleRegions = true;
624 return;
625 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700626
Jamie Gennis351a5132011-09-14 18:23:37 -0700627 // update the active buffer
628 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700629 if (mActiveBuffer == NULL) {
630 // this can only happen if the very first buffer was rejected.
631 return;
632 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800633
Mathias Agopian4824d402012-06-04 18:16:30 -0700634 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700635 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700636 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700637 // the first time we receive a buffer, we need to trigger a
638 // geometry invalidation.
639 mFlinger->invalidateHwcGeometry();
640 }
641
Mathias Agopian702634a2012-05-23 17:50:31 -0700642 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700643 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
644 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700645 if ((crop != mCurrentCrop) ||
646 (transform != mCurrentTransform) ||
647 (scalingMode != mCurrentScalingMode))
648 {
649 mCurrentCrop = crop;
650 mCurrentTransform = transform;
651 mCurrentScalingMode = scalingMode;
652 mFlinger->invalidateHwcGeometry();
653 }
654
655 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700656 uint32_t bufWidth = mActiveBuffer->getWidth();
657 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700658 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
659 bufHeight != uint32_t(oldActiveBuffer->height)) {
660 mFlinger->invalidateHwcGeometry();
661 }
662 }
663
664 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
665 if (oldOpacity != isOpaque()) {
666 recomputeVisibleRegions = true;
667 }
668
669 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700670 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700671 mPostedDirtyRegion.set(front.active.w, front.active.h);
672
673 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
674 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700675 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800676}
677
678void Layer::unlockPageFlip(
679 const Transform& planeTransform, Region& outDirtyRegion)
680{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800681 ATRACE_CALL();
682
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800683 Region postedRegion(mPostedDirtyRegion);
684 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800685 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800686 if (!visibleRegionScreen.isEmpty()) {
687 // The dirty region is given in the layer's coordinate space
688 // transform the dirty region by the surface's transformation
689 // and the global transformation.
690 const Layer::State& s(drawingState());
691 const Transform tr(planeTransform * s.transform);
692 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800693
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800694 // At this point, the dirty region is in screen space.
695 // Make sure it's constrained by the visible region (which
696 // is in screen space as well).
697 postedRegion.andSelf(visibleRegionScreen);
698 outDirtyRegion.orSelf(postedRegion);
699 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800700 }
701}
702
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700703void Layer::dump(String8& result, char* buffer, size_t SIZE) const
704{
705 LayerBaseClient::dump(result, buffer, SIZE);
706
Mathias Agopiana67932f2011-04-20 14:20:59 -0700707 sp<const GraphicBuffer> buf0(mActiveBuffer);
708 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700709 if (buf0 != 0) {
710 w0 = buf0->getWidth();
711 h0 = buf0->getHeight();
712 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700713 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700714 }
715 snprintf(buffer, SIZE,
716 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700717 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800718 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700719 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800720 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700721
722 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700723
Mathias Agopiana67932f2011-04-20 14:20:59 -0700724 if (mSurfaceTexture != 0) {
725 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700726 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700727}
728
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800729void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
730{
731 LayerBaseClient::dumpStats(result, buffer, SIZE);
732 const size_t o = mFrameLatencyOffset;
733 const DisplayHardware& hw(graphicPlane(0).displayHardware());
734 const nsecs_t period = hw.getRefreshPeriod();
735 result.appendFormat("%lld\n", period);
736 for (size_t i=0 ; i<128 ; i++) {
737 const size_t index = (o+i) % 128;
738 const nsecs_t time_app = mFrameStats[index].timestamp;
739 const nsecs_t time_set = mFrameStats[index].set;
740 const nsecs_t time_vsync = mFrameStats[index].vsync;
741 result.appendFormat("%lld\t%lld\t%lld\n",
742 time_app,
743 time_vsync,
744 time_set);
745 }
746 result.append("\n");
747}
748
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800749void Layer::clearStats()
750{
751 LayerBaseClient::clearStats();
752 memset(mFrameStats, 0, sizeof(mFrameStats));
753}
754
Mathias Agopiana67932f2011-04-20 14:20:59 -0700755uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700756{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700757 // TODO: should we do something special if mSecure is set?
758 if (mProtectedByApp) {
759 // need a hardware-protected path to external video sink
760 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700761 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700762 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700763 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700764}
765
Mathias Agopiana4583642011-08-23 18:03:18 -0700766uint32_t Layer::getTransformHint() const {
767 uint32_t orientation = 0;
768 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700769 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700770 if (orientation & Transform::ROT_INVALID) {
771 orientation = 0;
772 }
773 }
774 return orientation;
775}
776
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800777// ---------------------------------------------------------------------------
778
779
780}; // namespace android