blob: 4c82f91b175496fa320e36ae7fd28324e12d52e2 [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 Agopian0f2f5ff2012-07-31 23:09:07 -070039#include "DisplayDevice.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070040#include "GLExtensions.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include "SurfaceFlinger.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070043#include "SurfaceTextureLayer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044
Mathias Agopian1b031492012-06-20 17:51:20 -070045#include "DisplayHardware/HWComposer.h"
46
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#define DEBUG_RESIZE 0
48
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049namespace android {
50
51// ---------------------------------------------------------------------------
52
Mathias Agopian3ee454a2012-08-27 16:28:24 -070053Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
54 : LayerBaseClient(flinger, 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 Agopianb7e930d2010-06-01 15:12:58 -070066 mSecure(false),
Mathias Agopian933389f2011-07-18 16:15:08 -070067 mProtectedByApp(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080068{
Mathias Agopiana67932f2011-04-20 14:20:59 -070069 mCurrentCrop.makeInvalid();
70 glGenTextures(1, &mTextureName);
Jamie Gennise8696a42012-01-15 18:54:57 -080071}
72
Mathias Agopian42977342012-08-05 00:40:46 -070073void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -070074 HWComposer::HWCLayerInterface* layer) {
Jesse Hallef194142012-06-14 14:45:17 -070075 if (layer) {
76 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
77 }
Mathias Agopiand606de62010-05-10 20:06:11 -070078}
79
Mathias Agopiana67932f2011-04-20 14:20:59 -070080void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070081{
Mathias Agopiana67932f2011-04-20 14:20:59 -070082 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070083
Mathias Agopiana67932f2011-04-20 14:20:59 -070084 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
85 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
86 private:
87 wp<Layer> mLayer;
88 virtual void onFrameAvailable() {
89 sp<Layer> that(mLayer.promote());
90 if (that != 0) {
91 that->onFrameQueued();
92 }
93 }
94 };
Daniel Lamb2675792012-02-23 14:35:13 -080095
96 // Creates a custom BufferQueue for SurfaceTexture to use
97 sp<BufferQueue> bq = new SurfaceTextureLayer();
98 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -070099 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800100
Daniel Lamb2675792012-02-23 14:35:13 -0800101 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700102 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
103 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800104
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700105#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
106#warning "disabling triple buffering"
Mathias Agopiana67932f2011-04-20 14:20:59 -0700107 mSurfaceTexture->setBufferCountServer(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700108#else
109 mSurfaceTexture->setBufferCountServer(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800110#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700111}
112
Mathias Agopiana67932f2011-04-20 14:20:59 -0700113Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700114{
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700115 mFlinger->deleteTextureAsync(mTextureName);
Mathias Agopian96f08192010-06-02 23:28:45 -0700116}
117
Mathias Agopiana67932f2011-04-20 14:20:59 -0700118void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700119 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800120 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700121}
122
Mathias Agopiand606de62010-05-10 20:06:11 -0700123// called with SurfaceFlinger::mStateLock as soon as the layer is entered
124// in the purgatory list
125void Layer::onRemoved()
126{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700127 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700128}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700129
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700130void Layer::setName(const String8& name) {
131 LayerBase::setName(name);
132 mSurfaceTexture->setName(name);
133}
134
Mathias Agopiana67932f2011-04-20 14:20:59 -0700135sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800136{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700137 class BSurface : public BnSurface, public LayerCleaner {
138 wp<const Layer> mOwner;
139 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
140 sp<ISurfaceTexture> res;
141 sp<const Layer> that( mOwner.promote() );
142 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800143 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700144 }
145 return res;
146 }
147 public:
148 BSurface(const sp<SurfaceFlinger>& flinger,
149 const sp<Layer>& layer)
150 : LayerCleaner(flinger, layer), mOwner(layer) { }
151 };
152 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800153 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154}
155
Jamie Gennis582270d2011-08-17 18:19:00 -0700156wp<IBinder> Layer::getSurfaceTextureBinder() const
157{
Daniel Lamb2675792012-02-23 14:35:13 -0800158 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700159}
160
Mathias Agopianf9d93272009-06-19 17:00:27 -0700161status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800162 PixelFormat format, uint32_t flags)
163{
Mathias Agopian401c2572009-09-23 19:16:27 -0700164 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800165 PixelFormatInfo info;
166 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800167 if (err) {
168 ALOGE("unsupported pixelformat %d", format);
169 return err;
170 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800171
Mathias Agopianca99fb82010-04-14 16:43:44 -0700172 uint32_t const maxSurfaceDims = min(
Mathias Agopiana4912602012-07-12 14:25:33 -0700173 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700174
175 // never allow a surface larger than what our underlying GL implementation
176 // can handle.
177 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800178 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700179 return BAD_VALUE;
180 }
181
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700182 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700183
Mathias Agopian3165cc22012-08-08 19:42:09 -0700184 mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
185 mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
186 mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700187 mCurrentOpacity = getOpacityForFormat(format);
188
189 mSurfaceTexture->setDefaultBufferSize(w, h);
190 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800191 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700192
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800193 return NO_ERROR;
194}
195
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700196Rect Layer::computeBufferCrop() const {
197 // Start with the SurfaceTexture's buffer crop...
198 Rect crop;
199 if (!mCurrentCrop.isEmpty()) {
200 crop = mCurrentCrop;
201 } else if (mActiveBuffer != NULL){
202 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
203 } else {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700204 crop.makeInvalid();
205 return crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700206 }
207
208 // ... then reduce that in the same proportions as the window crop reduces
209 // the window size.
210 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700211 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700212 // Transform the window crop to match the buffer coordinate system,
213 // which means using the inverse of the current transform set on the
214 // SurfaceTexture.
215 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700216 int winWidth = s.active.w;
217 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700218 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
219 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
220 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700221 winWidth = s.active.h;
222 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700223 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700224 Rect winCrop = s.active.crop.transform(invTransform,
225 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700226
227 float xScale = float(crop.width()) / float(winWidth);
228 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700229 crop.left += int(ceilf(float(winCrop.left) * xScale));
230 crop.top += int(ceilf(float(winCrop.top) * yScale));
231 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
232 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700233 }
234
235 return crop;
236}
237
Mathias Agopian4fec8732012-06-29 14:12:52 -0700238void Layer::setGeometry(
Mathias Agopian42977342012-08-05 00:40:46 -0700239 const sp<const DisplayDevice>& hw,
Mathias Agopian4fec8732012-06-29 14:12:52 -0700240 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700241{
Mathias Agopian4fec8732012-06-29 14:12:52 -0700242 LayerBaseClient::setGeometry(hw, layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700243
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700244 // enable this layer
245 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700246
247 // we can't do alpha-fade with the hwc HAL
248 const State& s(drawingState());
249 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700250 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700251 }
252
Mathias Agopian29a367b2011-07-12 14:51:45 -0700253 /*
254 * Transformations are applied in this order:
255 * 1) buffer orientation/flip/mirror
256 * 2) state transformation (window manager)
257 * 3) layer orientation (screen orientation)
258 * (NOTE: the matrices are multiplied in reverse order)
259 */
260
261 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian42977342012-08-05 00:40:46 -0700262 const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700263
264 // this gives us only the "orientation" component of the transform
265 const uint32_t finalTransform = tr.getOrientation();
266
Mathias Agopiana350ff92010-08-10 17:14:02 -0700267 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700268 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700269 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700270 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700271 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700272 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700273 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700274}
275
Mathias Agopian42977342012-08-05 00:40:46 -0700276void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700277 HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700278 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700279 // NOTE: buffer can be NULL if the client never drew into this
280 // layer yet, or if we ran out of memory
281 layer.setBuffer(buffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700282}
Jesse Halldc5b4852012-06-29 15:21:18 -0700283
Mathias Agopian42977342012-08-05 00:40:46 -0700284void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700285 HWComposer::HWCLayerInterface& layer) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700286 int fenceFd = -1;
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700287
288 // TODO: there is a possible optimization here: we only need to set the
289 // acquire fence the first time a new buffer is acquired on EACH display.
290
291 if (layer.getCompositionType() == HWC_OVERLAY) {
Jesse Halldc5b4852012-06-29 15:21:18 -0700292 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
293 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700294 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700295 if (fenceFd == -1) {
296 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
297 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700298 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700299 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700300 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700301}
302
Mathias Agopian42977342012-08-05 00:40:46 -0700303void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800304{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800305 ATRACE_CALL();
306
Mathias Agopiana67932f2011-04-20 14:20:59 -0700307 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800308 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700309 // in fact never been drawn into. This happens frequently with
310 // SurfaceView because the WindowManager can't know when the client
311 // has drawn the first time.
312
313 // If there is nothing under us, we paint the screen in black, otherwise
314 // we just skip this update.
315
316 // figure out if there is something below us
317 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700318 const SurfaceFlinger::LayerVector& drawingLayers(
319 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700320 const size_t count = drawingLayers.size();
321 for (size_t i=0 ; i<count ; ++i) {
322 const sp<LayerBase>& layer(drawingLayers[i]);
323 if (layer.get() == static_cast<LayerBase const*>(this))
324 break;
Mathias Agopian42977342012-08-05 00:40:46 -0700325 under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700326 }
327 // if not everything below us is covered, we plug the holes!
328 Region holes(clip.subtract(under));
329 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700330 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700331 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800332 return;
333 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700334
Jesse Halldc5b4852012-06-29 15:21:18 -0700335 // TODO: replace this with a server-side wait
336 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
337 if (fence.get()) {
338 status_t err = fence->wait(Fence::TIMEOUT_NEVER);
339 ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
340 // Go ahead and draw the buffer anyway; no matter what we do the screen
341 // is probably going to have something visibly wrong.
342 }
343
Jamie Gennis9575f602011-10-07 14:51:16 -0700344 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700345 // TODO: we could be more subtle with isFixedSize()
346 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
347
348 // Query the texture matrix given our current filtering mode.
349 float textureMatrix[16];
350 mSurfaceTexture->setFilteringEnabled(useFiltering);
351 mSurfaceTexture->getTransformMatrix(textureMatrix);
352
353 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700354 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
355 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700356 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700357 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700358 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700359 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
360 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700361 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700362 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700363 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700364 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700365 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700366 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700367 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700368 glMatrixMode(GL_TEXTURE);
369 glLoadIdentity();
370 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700371 glDisable(GL_TEXTURE_EXTERNAL_OES);
372 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700373 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700374
Mathias Agopian1b031492012-06-20 17:51:20 -0700375 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700376
Mathias Agopianc492e672011-10-18 14:49:27 -0700377 glDisable(GL_TEXTURE_EXTERNAL_OES);
378 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800379}
380
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800381// As documented in libhardware header, formats in the range
382// 0x100 - 0x1FF are specific to the HAL implementation, and
383// are known to have no alpha channel
384// TODO: move definition for device-specific range into
385// hardware.h, instead of using hard-coded values here.
386#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
387
Mathias Agopiana67932f2011-04-20 14:20:59 -0700388bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800389{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700390 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
391 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800392 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700393 PixelFormatInfo info;
394 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
395 // in case of error (unknown format), we assume no blending
396 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800397}
398
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800399
Mathias Agopiana67932f2011-04-20 14:20:59 -0700400bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700401{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700402 // if we don't have a buffer yet, we're translucent regardless of the
403 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700404 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700405 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700406 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700407
408 // if the layer has the opaque flag, then we're always opaque,
409 // otherwise we use the current buffer's format.
410 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700411}
412
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800413bool Layer::isProtected() const
414{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700415 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800416 return (activeBuffer != 0) &&
417 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
418}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700419
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800420uint32_t Layer::doTransaction(uint32_t flags)
421{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800422 ATRACE_CALL();
423
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800424 const Layer::State& front(drawingState());
425 const Layer::State& temp(currentState());
426
Mathias Agopian4824d402012-06-04 18:16:30 -0700427 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
428 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700429
430 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700431 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000432 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700433 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
434 " current={ 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 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
437 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
438 this, mCurrentScalingMode,
439 temp.active.w, temp.active.h,
440 temp.active.crop.left,
441 temp.active.crop.top,
442 temp.active.crop.right,
443 temp.active.crop.bottom,
444 temp.active.crop.getWidth(),
445 temp.active.crop.getHeight(),
446 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700447 temp.requested.crop.left,
448 temp.requested.crop.top,
449 temp.requested.crop.right,
450 temp.requested.crop.bottom,
451 temp.requested.crop.getWidth(),
452 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700453 front.active.w, front.active.h,
454 front.active.crop.left,
455 front.active.crop.top,
456 front.active.crop.right,
457 front.active.crop.bottom,
458 front.active.crop.getWidth(),
459 front.active.crop.getHeight(),
460 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700461 front.requested.crop.left,
462 front.requested.crop.top,
463 front.requested.crop.right,
464 front.requested.crop.bottom,
465 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700466 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800467
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700468 // record the new size, form this point on, when the client request
469 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700470 mSurfaceTexture->setDefaultBufferSize(
471 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800472 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700473
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700474 if (!isFixedSize()) {
475
476 const bool resizePending = (temp.requested.w != temp.active.w) ||
477 (temp.requested.h != temp.active.h);
478
479 if (resizePending) {
480 // don't let LayerBase::doTransaction update the drawing state
481 // if we have a pending resize, unless we are in fixed-size mode.
482 // the drawing state will be updated only once we receive a buffer
483 // with the correct size.
484 //
485 // in particular, we want to make sure the clip (which is part
486 // of the geometry state) is latched together with the size but is
487 // latched immediately when no resizing is involved.
488
489 flags |= eDontUpdateGeometryState;
490 }
491 }
492
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 return LayerBase::doTransaction(flags);
494}
495
Mathias Agopiana138f892010-05-21 17:24:35 -0700496bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700497 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700498}
499
500bool Layer::isCropped() const {
501 return !mCurrentCrop.isEmpty();
502}
503
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800504// ----------------------------------------------------------------------------
505// pageflip handling...
506// ----------------------------------------------------------------------------
507
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800508bool Layer::onPreComposition() {
509 mRefreshPending = false;
510 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800511}
512
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700513void Layer::onPostComposition() {
514 if (mFrameLatencyNeeded) {
515 const HWComposer& hwc = mFlinger->getHwComposer();
516 const size_t offset = mFrameLatencyOffset;
517 mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
518 mFrameStats[offset].set = systemTime();
519 mFrameStats[offset].vsync = hwc.getRefreshTimestamp();
520 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
521 mFrameLatencyNeeded = false;
522 }
523}
524
Mathias Agopian4fec8732012-06-29 14:12:52 -0700525Region Layer::latchBuffer(bool& recomputeVisibleRegions)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800526{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800527 ATRACE_CALL();
528
Mathias Agopian4fec8732012-06-29 14:12:52 -0700529 Region outDirtyRegion;
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700530 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800531
532 // if we've already called updateTexImage() without going through
533 // a composition step, we have to skip this layer at this point
534 // because we cannot call updateTeximage() without a corresponding
535 // compositionComplete() call.
536 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800537 if (mRefreshPending) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700538 return outDirtyRegion;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800539 }
540
Jamie Gennis351a5132011-09-14 18:23:37 -0700541 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700542 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700543 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700544
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700545 // signal another event if we have more frames pending
546 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800547 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700548 }
549
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700550 struct Reject : public SurfaceTexture::BufferRejecter {
551 Layer::State& front;
552 Layer::State& current;
553 bool& recomputeVisibleRegions;
554 Reject(Layer::State& front, Layer::State& current,
555 bool& recomputeVisibleRegions)
556 : front(front), current(current),
557 recomputeVisibleRegions(recomputeVisibleRegions) {
558 }
559
560 virtual bool reject(const sp<GraphicBuffer>& buf,
561 const BufferQueue::BufferItem& item) {
562 if (buf == NULL) {
563 return false;
564 }
565
566 uint32_t bufWidth = buf->getWidth();
567 uint32_t bufHeight = buf->getHeight();
568
569 // check that we received a buffer of the right size
570 // (Take the buffer's orientation into account)
571 if (item.mTransform & Transform::ROT_90) {
572 swap(bufWidth, bufHeight);
573 }
574
575
576 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
577 if (front.active != front.requested) {
578
579 if (isFixedSize ||
580 (bufWidth == front.requested.w &&
581 bufHeight == front.requested.h))
582 {
583 // Here we pretend the transaction happened by updating the
584 // current and drawing states. Drawing state is only accessed
585 // in this thread, no need to have it locked
586 front.active = front.requested;
587
588 // We also need to update the current state so that
589 // we don't end-up overwriting the drawing state with
590 // this stale current state during the next transaction
591 //
592 // NOTE: We don't need to hold the transaction lock here
593 // because State::active is only accessed from this thread.
594 current.active = front.active;
595
596 // recompute visible region
597 recomputeVisibleRegions = true;
598 }
599
600 ALOGD_IF(DEBUG_RESIZE,
601 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
602 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
603 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
604 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
605 front.active.w, front.active.h,
606 front.active.crop.left,
607 front.active.crop.top,
608 front.active.crop.right,
609 front.active.crop.bottom,
610 front.active.crop.getWidth(),
611 front.active.crop.getHeight(),
612 front.requested.w, front.requested.h,
613 front.requested.crop.left,
614 front.requested.crop.top,
615 front.requested.crop.right,
616 front.requested.crop.bottom,
617 front.requested.crop.getWidth(),
618 front.requested.crop.getHeight());
619 }
620
621 if (!isFixedSize) {
622 if (front.active.w != bufWidth ||
623 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700624 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700625 return true;
626 }
627 }
628 return false;
629 }
630 };
631
632
633 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
634
Mathias Agopian4fec8732012-06-29 14:12:52 -0700635 // XXX: not sure if setTransformHint belongs here
636 // it should only be needed when the main screen orientation changes
637 mSurfaceTexture->setTransformHint(getTransformHint());
638
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700639 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700640 // something happened!
641 recomputeVisibleRegions = true;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700642 return outDirtyRegion;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700643 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700644
Jamie Gennis351a5132011-09-14 18:23:37 -0700645 // update the active buffer
646 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700647 if (mActiveBuffer == NULL) {
648 // this can only happen if the very first buffer was rejected.
Mathias Agopian4fec8732012-06-29 14:12:52 -0700649 return outDirtyRegion;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700650 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800651
Mathias Agopian4824d402012-06-04 18:16:30 -0700652 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700653 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700654 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700655 // the first time we receive a buffer, we need to trigger a
656 // geometry invalidation.
657 mFlinger->invalidateHwcGeometry();
658 }
659
Mathias Agopian702634a2012-05-23 17:50:31 -0700660 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700661 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
662 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700663 if ((crop != mCurrentCrop) ||
664 (transform != mCurrentTransform) ||
665 (scalingMode != mCurrentScalingMode))
666 {
667 mCurrentCrop = crop;
668 mCurrentTransform = transform;
669 mCurrentScalingMode = scalingMode;
670 mFlinger->invalidateHwcGeometry();
671 }
672
673 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700674 uint32_t bufWidth = mActiveBuffer->getWidth();
675 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700676 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
677 bufHeight != uint32_t(oldActiveBuffer->height)) {
678 mFlinger->invalidateHwcGeometry();
679 }
680 }
681
682 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
683 if (oldOpacity != isOpaque()) {
684 recomputeVisibleRegions = true;
685 }
686
Mathias Agopian702634a2012-05-23 17:50:31 -0700687 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
688 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700689
690 // FIXME: postedRegion should be dirty & bounds
691 const Layer::State& front(drawingState());
692 Region dirtyRegion(Rect(front.active.w, front.active.h));
693
694 // transform the dirty region to window-manager space
695 outDirtyRegion = (front.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700696 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700697 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800698}
699
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700700void Layer::dump(String8& result, char* buffer, size_t SIZE) const
701{
702 LayerBaseClient::dump(result, buffer, SIZE);
703
Mathias Agopiana67932f2011-04-20 14:20:59 -0700704 sp<const GraphicBuffer> buf0(mActiveBuffer);
705 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700706 if (buf0 != 0) {
707 w0 = buf0->getWidth();
708 h0 = buf0->getHeight();
709 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700710 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700711 }
712 snprintf(buffer, SIZE,
713 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700714 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800715 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700716 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800717 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700718
719 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700720
Mathias Agopiana67932f2011-04-20 14:20:59 -0700721 if (mSurfaceTexture != 0) {
722 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700723 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700724}
725
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800726void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
727{
728 LayerBaseClient::dumpStats(result, buffer, SIZE);
729 const size_t o = mFrameLatencyOffset;
Mathias Agopian888c8222012-08-04 21:10:38 -0700730 const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod();
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800731 result.appendFormat("%lld\n", period);
732 for (size_t i=0 ; i<128 ; i++) {
733 const size_t index = (o+i) % 128;
734 const nsecs_t time_app = mFrameStats[index].timestamp;
735 const nsecs_t time_set = mFrameStats[index].set;
736 const nsecs_t time_vsync = mFrameStats[index].vsync;
737 result.appendFormat("%lld\t%lld\t%lld\n",
738 time_app,
739 time_vsync,
740 time_set);
741 }
742 result.append("\n");
743}
744
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800745void Layer::clearStats()
746{
747 LayerBaseClient::clearStats();
748 memset(mFrameStats, 0, sizeof(mFrameStats));
749}
750
Mathias Agopiana67932f2011-04-20 14:20:59 -0700751uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700752{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700753 // TODO: should we do something special if mSecure is set?
754 if (mProtectedByApp) {
755 // need a hardware-protected path to external video sink
756 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700757 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700758 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700759 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700760}
761
Mathias Agopiana4583642011-08-23 18:03:18 -0700762uint32_t Layer::getTransformHint() const {
763 uint32_t orientation = 0;
764 if (!mFlinger->mDebugDisableTransformHint) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700765 // The transform hint is used to improve performance on the main
766 // display -- we can only have a single transform hint, it cannot
767 // apply to all displays.
768 // This is why we use the default display here. This is not an
769 // oversight.
Mathias Agopian42977342012-08-05 00:40:46 -0700770 sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
771 const Transform& planeTransform(hw->getTransform());
Mathias Agopian4fec8732012-06-29 14:12:52 -0700772 orientation = planeTransform.getOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700773 if (orientation & Transform::ROT_INVALID) {
774 orientation = 0;
775 }
776 }
777 return orientation;
778}
779
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800780// ---------------------------------------------------------------------------
781
782
783}; // namespace android