blob: 0825ec6f623a337a8555ddff342e234fb6bd3d01 [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 Agopian96f08192010-06-02 23:28:45 -070053Layer::Layer(SurfaceFlinger* flinger,
54 DisplayID display, const sp<Client>& client)
55 : LayerBaseClient(flinger, display, client),
Mathias Agopiana67932f2011-04-20 14:20:59 -070056 mTextureName(-1U),
57 mQueuedFrames(0),
58 mCurrentTransform(0),
Mathias Agopian933389f2011-07-18 16:15:08 -070059 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
Mathias Agopiana67932f2011-04-20 14:20:59 -070060 mCurrentOpacity(true),
Mathias Agopian4d143ee2012-02-23 20:05:39 -080061 mRefreshPending(false),
Mathias Agopian82d7ab62012-01-19 18:34:40 -080062 mFrameLatencyNeeded(false),
63 mFrameLatencyOffset(0),
Mathias Agopian5bf3abe2011-03-11 17:01:07 -080064 mFormat(PIXEL_FORMAT_NONE),
Mathias Agopian1f7bec62010-06-25 18:02:21 -070065 mGLExtensions(GLExtensions::getInstance()),
Mathias Agopiana67932f2011-04-20 14:20:59 -070066 mOpaqueLayer(true),
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
Mathias Agopian42977342012-08-05 00:40:46 -070074void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -070075 HWComposer::HWCLayerInterface* layer) {
Jesse Hallef194142012-06-14 14:45:17 -070076 if (layer) {
77 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
78 }
Mathias Agopiand606de62010-05-10 20:06:11 -070079}
80
Mathias Agopiana67932f2011-04-20 14:20:59 -070081void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070082{
Mathias Agopiana67932f2011-04-20 14:20:59 -070083 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070084
Mathias Agopiana67932f2011-04-20 14:20:59 -070085 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
86 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
87 private:
88 wp<Layer> mLayer;
89 virtual void onFrameAvailable() {
90 sp<Layer> that(mLayer.promote());
91 if (that != 0) {
92 that->onFrameQueued();
93 }
94 }
95 };
Daniel Lamb2675792012-02-23 14:35:13 -080096
97 // Creates a custom BufferQueue for SurfaceTexture to use
98 sp<BufferQueue> bq = new SurfaceTextureLayer();
99 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -0700100 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800101
Daniel Lamb2675792012-02-23 14:35:13 -0800102 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700103 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
104 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800105
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700106#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
107#warning "disabling triple buffering"
Mathias Agopiana67932f2011-04-20 14:20:59 -0700108 mSurfaceTexture->setBufferCountServer(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700109#else
110 mSurfaceTexture->setBufferCountServer(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800111#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700112}
113
Mathias Agopiana67932f2011-04-20 14:20:59 -0700114Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700115{
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700116 mFlinger->deleteTextureAsync(mTextureName);
Mathias Agopian96f08192010-06-02 23:28:45 -0700117}
118
Mathias Agopiana67932f2011-04-20 14:20:59 -0700119void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700120 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800121 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700122}
123
Mathias Agopiand606de62010-05-10 20:06:11 -0700124// called with SurfaceFlinger::mStateLock as soon as the layer is entered
125// in the purgatory list
126void Layer::onRemoved()
127{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700128 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700129}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700130
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700131void Layer::setName(const String8& name) {
132 LayerBase::setName(name);
133 mSurfaceTexture->setName(name);
134}
135
Mathias Agopiana67932f2011-04-20 14:20:59 -0700136sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700138 class BSurface : public BnSurface, public LayerCleaner {
139 wp<const Layer> mOwner;
140 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
141 sp<ISurfaceTexture> res;
142 sp<const Layer> that( mOwner.promote() );
143 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800144 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700145 }
146 return res;
147 }
148 public:
149 BSurface(const sp<SurfaceFlinger>& flinger,
150 const sp<Layer>& layer)
151 : LayerCleaner(flinger, layer), mOwner(layer) { }
152 };
153 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800154 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800155}
156
Jamie Gennis582270d2011-08-17 18:19:00 -0700157wp<IBinder> Layer::getSurfaceTextureBinder() const
158{
Daniel Lamb2675792012-02-23 14:35:13 -0800159 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700160}
161
Mathias Agopianf9d93272009-06-19 17:00:27 -0700162status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800163 PixelFormat format, uint32_t flags)
164{
Mathias Agopian401c2572009-09-23 19:16:27 -0700165 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800166 PixelFormatInfo info;
167 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800168 if (err) {
169 ALOGE("unsupported pixelformat %d", format);
170 return err;
171 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800172
Mathias Agopianca99fb82010-04-14 16:43:44 -0700173 uint32_t const maxSurfaceDims = min(
Mathias Agopiana4912602012-07-12 14:25:33 -0700174 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700175
176 // never allow a surface larger than what our underlying GL implementation
177 // can handle.
178 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800179 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700180 return BAD_VALUE;
181 }
182
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700183 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700184
Mathias Agopian3165cc22012-08-08 19:42:09 -0700185 mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
186 mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
187 mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700188 mCurrentOpacity = getOpacityForFormat(format);
189
190 mSurfaceTexture->setDefaultBufferSize(w, h);
191 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800192 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700193
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194 return NO_ERROR;
195}
196
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700197Rect Layer::computeBufferCrop() const {
198 // Start with the SurfaceTexture's buffer crop...
199 Rect crop;
200 if (!mCurrentCrop.isEmpty()) {
201 crop = mCurrentCrop;
202 } else if (mActiveBuffer != NULL){
203 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
204 } else {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700205 crop.makeInvalid();
206 return crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700207 }
208
209 // ... then reduce that in the same proportions as the window crop reduces
210 // the window size.
211 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700212 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700213 // Transform the window crop to match the buffer coordinate system,
214 // which means using the inverse of the current transform set on the
215 // SurfaceTexture.
216 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700217 int winWidth = s.active.w;
218 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700219 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
220 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
221 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700222 winWidth = s.active.h;
223 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700224 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700225 Rect winCrop = s.active.crop.transform(invTransform,
226 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700227
228 float xScale = float(crop.width()) / float(winWidth);
229 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700230 crop.left += int(ceilf(float(winCrop.left) * xScale));
231 crop.top += int(ceilf(float(winCrop.top) * yScale));
232 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
233 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700234 }
235
236 return crop;
237}
238
Mathias Agopian4fec8732012-06-29 14:12:52 -0700239void Layer::setGeometry(
Mathias Agopian42977342012-08-05 00:40:46 -0700240 const sp<const DisplayDevice>& hw,
Mathias Agopian4fec8732012-06-29 14:12:52 -0700241 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700242{
Mathias Agopian4fec8732012-06-29 14:12:52 -0700243 LayerBaseClient::setGeometry(hw, layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700244
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700245 // enable this layer
246 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700247
248 // we can't do alpha-fade with the hwc HAL
249 const State& s(drawingState());
250 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700251 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700252 }
253
Mathias Agopian29a367b2011-07-12 14:51:45 -0700254 /*
255 * Transformations are applied in this order:
256 * 1) buffer orientation/flip/mirror
257 * 2) state transformation (window manager)
258 * 3) layer orientation (screen orientation)
259 * (NOTE: the matrices are multiplied in reverse order)
260 */
261
262 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian42977342012-08-05 00:40:46 -0700263 const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700264
265 // this gives us only the "orientation" component of the transform
266 const uint32_t finalTransform = tr.getOrientation();
267
Mathias Agopiana350ff92010-08-10 17:14:02 -0700268 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700269 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700270 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700271 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700272 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700273 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700274 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700275}
276
Mathias Agopian42977342012-08-05 00:40:46 -0700277void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700278 HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700279 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700280 // NOTE: buffer can be NULL if the client never drew into this
281 // layer yet, or if we ran out of memory
282 layer.setBuffer(buffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700283}
Jesse Halldc5b4852012-06-29 15:21:18 -0700284
Mathias Agopian42977342012-08-05 00:40:46 -0700285void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700286 HWComposer::HWCLayerInterface& layer) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700287 int fenceFd = -1;
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700288
289 // TODO: there is a possible optimization here: we only need to set the
290 // acquire fence the first time a new buffer is acquired on EACH display.
291
292 if (layer.getCompositionType() == HWC_OVERLAY) {
Jesse Halldc5b4852012-06-29 15:21:18 -0700293 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
294 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700295 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700296 if (fenceFd == -1) {
297 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
298 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700299 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700300 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700301 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700302}
303
Mathias Agopian42977342012-08-05 00:40:46 -0700304void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800305{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800306 ATRACE_CALL();
307
Mathias Agopiana67932f2011-04-20 14:20:59 -0700308 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800309 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700310 // in fact never been drawn into. This happens frequently with
311 // SurfaceView because the WindowManager can't know when the client
312 // has drawn the first time.
313
314 // If there is nothing under us, we paint the screen in black, otherwise
315 // we just skip this update.
316
317 // figure out if there is something below us
318 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700319 const SurfaceFlinger::LayerVector& drawingLayers(
320 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700321 const size_t count = drawingLayers.size();
322 for (size_t i=0 ; i<count ; ++i) {
323 const sp<LayerBase>& layer(drawingLayers[i]);
324 if (layer.get() == static_cast<LayerBase const*>(this))
325 break;
Mathias Agopian42977342012-08-05 00:40:46 -0700326 under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700327 }
328 // if not everything below us is covered, we plug the holes!
329 Region holes(clip.subtract(under));
330 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700331 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700332 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333 return;
334 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700335
Jesse Halldc5b4852012-06-29 15:21:18 -0700336 // TODO: replace this with a server-side wait
337 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
338 if (fence.get()) {
339 status_t err = fence->wait(Fence::TIMEOUT_NEVER);
340 ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
341 // Go ahead and draw the buffer anyway; no matter what we do the screen
342 // is probably going to have something visibly wrong.
343 }
344
Jamie Gennis9575f602011-10-07 14:51:16 -0700345 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700346 // TODO: we could be more subtle with isFixedSize()
347 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
348
349 // Query the texture matrix given our current filtering mode.
350 float textureMatrix[16];
351 mSurfaceTexture->setFilteringEnabled(useFiltering);
352 mSurfaceTexture->getTransformMatrix(textureMatrix);
353
354 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700355 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
356 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700357 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700358 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700359 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700360 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
361 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700362 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700363 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700364 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700365 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700366 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700367 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700368 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700369 glMatrixMode(GL_TEXTURE);
370 glLoadIdentity();
371 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700372 glDisable(GL_TEXTURE_EXTERNAL_OES);
373 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700374 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700375
Mathias Agopian1b031492012-06-20 17:51:20 -0700376 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700377
Mathias Agopianc492e672011-10-18 14:49:27 -0700378 glDisable(GL_TEXTURE_EXTERNAL_OES);
379 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800380}
381
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800382// As documented in libhardware header, formats in the range
383// 0x100 - 0x1FF are specific to the HAL implementation, and
384// are known to have no alpha channel
385// TODO: move definition for device-specific range into
386// hardware.h, instead of using hard-coded values here.
387#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
388
Mathias Agopiana67932f2011-04-20 14:20:59 -0700389bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800390{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700391 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
392 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800393 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700394 PixelFormatInfo info;
395 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
396 // in case of error (unknown format), we assume no blending
397 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800398}
399
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800400
Mathias Agopiana67932f2011-04-20 14:20:59 -0700401bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700402{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700403 // if we don't have a buffer yet, we're translucent regardless of the
404 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700405 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700406 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700407 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700408
409 // if the layer has the opaque flag, then we're always opaque,
410 // otherwise we use the current buffer's format.
411 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700412}
413
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800414bool Layer::isProtected() const
415{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700416 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800417 return (activeBuffer != 0) &&
418 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
419}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700420
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800421uint32_t Layer::doTransaction(uint32_t flags)
422{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800423 ATRACE_CALL();
424
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800425 const Layer::State& front(drawingState());
426 const Layer::State& temp(currentState());
427
Mathias Agopian4824d402012-06-04 18:16:30 -0700428 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
429 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700430
431 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700432 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000433 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700434 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
435 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
436 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
437 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
438 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
439 this, mCurrentScalingMode,
440 temp.active.w, temp.active.h,
441 temp.active.crop.left,
442 temp.active.crop.top,
443 temp.active.crop.right,
444 temp.active.crop.bottom,
445 temp.active.crop.getWidth(),
446 temp.active.crop.getHeight(),
447 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700448 temp.requested.crop.left,
449 temp.requested.crop.top,
450 temp.requested.crop.right,
451 temp.requested.crop.bottom,
452 temp.requested.crop.getWidth(),
453 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700454 front.active.w, front.active.h,
455 front.active.crop.left,
456 front.active.crop.top,
457 front.active.crop.right,
458 front.active.crop.bottom,
459 front.active.crop.getWidth(),
460 front.active.crop.getHeight(),
461 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700462 front.requested.crop.left,
463 front.requested.crop.top,
464 front.requested.crop.right,
465 front.requested.crop.bottom,
466 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700467 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800468
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700469 // record the new size, form this point on, when the client request
470 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700471 mSurfaceTexture->setDefaultBufferSize(
472 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800473 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700474
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700475 if (!isFixedSize()) {
476
477 const bool resizePending = (temp.requested.w != temp.active.w) ||
478 (temp.requested.h != temp.active.h);
479
480 if (resizePending) {
481 // don't let LayerBase::doTransaction update the drawing state
482 // if we have a pending resize, unless we are in fixed-size mode.
483 // the drawing state will be updated only once we receive a buffer
484 // with the correct size.
485 //
486 // in particular, we want to make sure the clip (which is part
487 // of the geometry state) is latched together with the size but is
488 // latched immediately when no resizing is involved.
489
490 flags |= eDontUpdateGeometryState;
491 }
492 }
493
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800494 return LayerBase::doTransaction(flags);
495}
496
Mathias Agopiana138f892010-05-21 17:24:35 -0700497bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700498 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700499}
500
501bool Layer::isCropped() const {
502 return !mCurrentCrop.isEmpty();
503}
504
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505// ----------------------------------------------------------------------------
506// pageflip handling...
507// ----------------------------------------------------------------------------
508
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800509bool Layer::onPreComposition() {
510 mRefreshPending = false;
511 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800512}
513
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700514void Layer::onPostComposition() {
515 if (mFrameLatencyNeeded) {
516 const HWComposer& hwc = mFlinger->getHwComposer();
517 const size_t offset = mFrameLatencyOffset;
518 mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
519 mFrameStats[offset].set = systemTime();
520 mFrameStats[offset].vsync = hwc.getRefreshTimestamp();
521 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
522 mFrameLatencyNeeded = false;
523 }
524}
525
Mathias Agopian4fec8732012-06-29 14:12:52 -0700526Region Layer::latchBuffer(bool& recomputeVisibleRegions)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800527{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800528 ATRACE_CALL();
529
Mathias Agopian4fec8732012-06-29 14:12:52 -0700530 Region outDirtyRegion;
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700531 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800532
533 // if we've already called updateTexImage() without going through
534 // a composition step, we have to skip this layer at this point
535 // because we cannot call updateTeximage() without a corresponding
536 // compositionComplete() call.
537 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800538 if (mRefreshPending) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700539 return outDirtyRegion;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800540 }
541
Jamie Gennis351a5132011-09-14 18:23:37 -0700542 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700543 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700544 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700545
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700546 // signal another event if we have more frames pending
547 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800548 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700549 }
550
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700551 struct Reject : public SurfaceTexture::BufferRejecter {
552 Layer::State& front;
553 Layer::State& current;
554 bool& recomputeVisibleRegions;
555 Reject(Layer::State& front, Layer::State& current,
556 bool& recomputeVisibleRegions)
557 : front(front), current(current),
558 recomputeVisibleRegions(recomputeVisibleRegions) {
559 }
560
561 virtual bool reject(const sp<GraphicBuffer>& buf,
562 const BufferQueue::BufferItem& item) {
563 if (buf == NULL) {
564 return false;
565 }
566
567 uint32_t bufWidth = buf->getWidth();
568 uint32_t bufHeight = buf->getHeight();
569
570 // check that we received a buffer of the right size
571 // (Take the buffer's orientation into account)
572 if (item.mTransform & Transform::ROT_90) {
573 swap(bufWidth, bufHeight);
574 }
575
576
577 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
578 if (front.active != front.requested) {
579
580 if (isFixedSize ||
581 (bufWidth == front.requested.w &&
582 bufHeight == front.requested.h))
583 {
584 // Here we pretend the transaction happened by updating the
585 // current and drawing states. Drawing state is only accessed
586 // in this thread, no need to have it locked
587 front.active = front.requested;
588
589 // We also need to update the current state so that
590 // we don't end-up overwriting the drawing state with
591 // this stale current state during the next transaction
592 //
593 // NOTE: We don't need to hold the transaction lock here
594 // because State::active is only accessed from this thread.
595 current.active = front.active;
596
597 // recompute visible region
598 recomputeVisibleRegions = true;
599 }
600
601 ALOGD_IF(DEBUG_RESIZE,
602 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
603 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
604 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
605 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
606 front.active.w, front.active.h,
607 front.active.crop.left,
608 front.active.crop.top,
609 front.active.crop.right,
610 front.active.crop.bottom,
611 front.active.crop.getWidth(),
612 front.active.crop.getHeight(),
613 front.requested.w, front.requested.h,
614 front.requested.crop.left,
615 front.requested.crop.top,
616 front.requested.crop.right,
617 front.requested.crop.bottom,
618 front.requested.crop.getWidth(),
619 front.requested.crop.getHeight());
620 }
621
622 if (!isFixedSize) {
623 if (front.active.w != bufWidth ||
624 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700625 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700626 return true;
627 }
628 }
629 return false;
630 }
631 };
632
633
634 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
635
Mathias Agopian4fec8732012-06-29 14:12:52 -0700636 // XXX: not sure if setTransformHint belongs here
637 // it should only be needed when the main screen orientation changes
638 mSurfaceTexture->setTransformHint(getTransformHint());
639
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700640 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700641 // something happened!
642 recomputeVisibleRegions = true;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700643 return outDirtyRegion;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700644 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700645
Jamie Gennis351a5132011-09-14 18:23:37 -0700646 // update the active buffer
647 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700648 if (mActiveBuffer == NULL) {
649 // this can only happen if the very first buffer was rejected.
Mathias Agopian4fec8732012-06-29 14:12:52 -0700650 return outDirtyRegion;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700651 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800652
Mathias Agopian4824d402012-06-04 18:16:30 -0700653 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700654 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700655 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700656 // the first time we receive a buffer, we need to trigger a
657 // geometry invalidation.
658 mFlinger->invalidateHwcGeometry();
659 }
660
Mathias Agopian702634a2012-05-23 17:50:31 -0700661 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700662 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
663 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700664 if ((crop != mCurrentCrop) ||
665 (transform != mCurrentTransform) ||
666 (scalingMode != mCurrentScalingMode))
667 {
668 mCurrentCrop = crop;
669 mCurrentTransform = transform;
670 mCurrentScalingMode = scalingMode;
671 mFlinger->invalidateHwcGeometry();
672 }
673
674 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700675 uint32_t bufWidth = mActiveBuffer->getWidth();
676 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700677 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
678 bufHeight != uint32_t(oldActiveBuffer->height)) {
679 mFlinger->invalidateHwcGeometry();
680 }
681 }
682
683 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
684 if (oldOpacity != isOpaque()) {
685 recomputeVisibleRegions = true;
686 }
687
Mathias Agopian702634a2012-05-23 17:50:31 -0700688 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
689 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700690
691 // FIXME: postedRegion should be dirty & bounds
692 const Layer::State& front(drawingState());
693 Region dirtyRegion(Rect(front.active.w, front.active.h));
694
695 // transform the dirty region to window-manager space
696 outDirtyRegion = (front.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700697 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700698 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800699}
700
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700701void Layer::dump(String8& result, char* buffer, size_t SIZE) const
702{
703 LayerBaseClient::dump(result, buffer, SIZE);
704
Mathias Agopiana67932f2011-04-20 14:20:59 -0700705 sp<const GraphicBuffer> buf0(mActiveBuffer);
706 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700707 if (buf0 != 0) {
708 w0 = buf0->getWidth();
709 h0 = buf0->getHeight();
710 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700711 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700712 }
713 snprintf(buffer, SIZE,
714 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700715 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800716 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700717 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800718 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700719
720 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700721
Mathias Agopiana67932f2011-04-20 14:20:59 -0700722 if (mSurfaceTexture != 0) {
723 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700724 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700725}
726
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800727void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
728{
729 LayerBaseClient::dumpStats(result, buffer, SIZE);
730 const size_t o = mFrameLatencyOffset;
Mathias Agopian888c8222012-08-04 21:10:38 -0700731 const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod();
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800732 result.appendFormat("%lld\n", period);
733 for (size_t i=0 ; i<128 ; i++) {
734 const size_t index = (o+i) % 128;
735 const nsecs_t time_app = mFrameStats[index].timestamp;
736 const nsecs_t time_set = mFrameStats[index].set;
737 const nsecs_t time_vsync = mFrameStats[index].vsync;
738 result.appendFormat("%lld\t%lld\t%lld\n",
739 time_app,
740 time_vsync,
741 time_set);
742 }
743 result.append("\n");
744}
745
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800746void Layer::clearStats()
747{
748 LayerBaseClient::clearStats();
749 memset(mFrameStats, 0, sizeof(mFrameStats));
750}
751
Mathias Agopiana67932f2011-04-20 14:20:59 -0700752uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700753{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700754 // TODO: should we do something special if mSecure is set?
755 if (mProtectedByApp) {
756 // need a hardware-protected path to external video sink
757 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700758 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700759 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700760 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700761}
762
Mathias Agopiana4583642011-08-23 18:03:18 -0700763uint32_t Layer::getTransformHint() const {
764 uint32_t orientation = 0;
765 if (!mFlinger->mDebugDisableTransformHint) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700766 // The transform hint is used to improve performance on the main
767 // display -- we can only have a single transform hint, it cannot
768 // apply to all displays.
769 // This is why we use the default display here. This is not an
770 // oversight.
Mathias Agopian42977342012-08-05 00:40:46 -0700771 sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
772 const Transform& planeTransform(hw->getTransform());
Mathias Agopian4fec8732012-06-29 14:12:52 -0700773 orientation = planeTransform.getOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700774 if (orientation & Transform::ROT_INVALID) {
775 orientation = 0;
776 }
777 }
778 return orientation;
779}
780
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800781// ---------------------------------------------------------------------------
782
783
784}; // namespace android