blob: 815a6f94a9489f93e3af6a1089c8c1322073c9e5 [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 Agopian1b031492012-06-20 17:51:20 -070039#include "DisplayHardware.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),
Jesse Halldc5b4852012-06-29 15:21:18 -070063 mNeedHwcFence(false),
Mathias Agopian82d7ab62012-01-19 18:34:40 -080064 mFrameLatencyOffset(0),
Mathias Agopian5bf3abe2011-03-11 17:01:07 -080065 mFormat(PIXEL_FORMAT_NONE),
Mathias Agopian1f7bec62010-06-25 18:02:21 -070066 mGLExtensions(GLExtensions::getInstance()),
Mathias Agopiana67932f2011-04-20 14:20:59 -070067 mOpaqueLayer(true),
Mathias Agopianb7e930d2010-06-01 15:12:58 -070068 mSecure(false),
Mathias Agopian933389f2011-07-18 16:15:08 -070069 mProtectedByApp(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080070{
Mathias Agopiana67932f2011-04-20 14:20:59 -070071 mCurrentCrop.makeInvalid();
72 glGenTextures(1, &mTextureName);
Jamie Gennise8696a42012-01-15 18:54:57 -080073}
74
Jesse Hallef194142012-06-14 14:45:17 -070075void Layer::onLayerDisplayed(HWComposer::HWCLayerInterface* layer) {
76 if (layer) {
77 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
78 }
79
Jamie Gennise8696a42012-01-15 18:54:57 -080080 if (mFrameLatencyNeeded) {
Mathias Agopian1b031492012-06-20 17:51:20 -070081 // we need a DisplayHardware for debugging only right now
82 // XXX: should this be called per DisplayHardware?
83 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -080084 mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
85 mFrameStats[mFrameLatencyOffset].set = systemTime();
86 mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
Jamie Gennise8696a42012-01-15 18:54:57 -080087 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
88 mFrameLatencyNeeded = false;
89 }
Mathias Agopiand606de62010-05-10 20:06:11 -070090}
91
Mathias Agopiana67932f2011-04-20 14:20:59 -070092void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070093{
Mathias Agopiana67932f2011-04-20 14:20:59 -070094 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070095
Mathias Agopiana67932f2011-04-20 14:20:59 -070096 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
97 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
98 private:
99 wp<Layer> mLayer;
100 virtual void onFrameAvailable() {
101 sp<Layer> that(mLayer.promote());
102 if (that != 0) {
103 that->onFrameQueued();
104 }
105 }
106 };
Daniel Lamb2675792012-02-23 14:35:13 -0800107
108 // Creates a custom BufferQueue for SurfaceTexture to use
109 sp<BufferQueue> bq = new SurfaceTextureLayer();
110 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -0700111 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800112
Daniel Lamb2675792012-02-23 14:35:13 -0800113 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700114 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
115 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800116
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700117#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
118#warning "disabling triple buffering"
Mathias Agopiana67932f2011-04-20 14:20:59 -0700119 mSurfaceTexture->setBufferCountServer(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700120#else
121 mSurfaceTexture->setBufferCountServer(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800122#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700123}
124
Mathias Agopiana67932f2011-04-20 14:20:59 -0700125Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700126{
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700127 mFlinger->deleteTextureAsync(mTextureName);
Mathias Agopian96f08192010-06-02 23:28:45 -0700128}
129
Mathias Agopiana67932f2011-04-20 14:20:59 -0700130void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700131 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800132 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700133}
134
Mathias Agopiand606de62010-05-10 20:06:11 -0700135// called with SurfaceFlinger::mStateLock as soon as the layer is entered
136// in the purgatory list
137void Layer::onRemoved()
138{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700139 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700140}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700141
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700142void Layer::setName(const String8& name) {
143 LayerBase::setName(name);
144 mSurfaceTexture->setName(name);
145}
146
Mathias Agopiana67932f2011-04-20 14:20:59 -0700147sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800148{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700149 class BSurface : public BnSurface, public LayerCleaner {
150 wp<const Layer> mOwner;
151 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
152 sp<ISurfaceTexture> res;
153 sp<const Layer> that( mOwner.promote() );
154 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800155 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700156 }
157 return res;
158 }
159 public:
160 BSurface(const sp<SurfaceFlinger>& flinger,
161 const sp<Layer>& layer)
162 : LayerCleaner(flinger, layer), mOwner(layer) { }
163 };
164 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800165 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800166}
167
Jamie Gennis582270d2011-08-17 18:19:00 -0700168wp<IBinder> Layer::getSurfaceTextureBinder() const
169{
Daniel Lamb2675792012-02-23 14:35:13 -0800170 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700171}
172
Mathias Agopianf9d93272009-06-19 17:00:27 -0700173status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800174 PixelFormat format, uint32_t flags)
175{
Mathias Agopian401c2572009-09-23 19:16:27 -0700176 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800177 PixelFormatInfo info;
178 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800179 if (err) {
180 ALOGE("unsupported pixelformat %d", format);
181 return err;
182 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183
Mathias Agopianca99fb82010-04-14 16:43:44 -0700184 uint32_t const maxSurfaceDims = min(
Mathias Agopiana4912602012-07-12 14:25:33 -0700185 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700186
187 // never allow a surface larger than what our underlying GL implementation
188 // can handle.
189 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800190 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700191 return BAD_VALUE;
192 }
193
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700194 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700195
Mathias Agopian3330b202009-10-05 17:07:12 -0700196 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800197 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700198 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
199 mCurrentOpacity = getOpacityForFormat(format);
200
201 mSurfaceTexture->setDefaultBufferSize(w, h);
202 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800203 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700204
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800205 return NO_ERROR;
206}
207
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700208Rect Layer::computeBufferCrop() const {
209 // Start with the SurfaceTexture's buffer crop...
210 Rect crop;
211 if (!mCurrentCrop.isEmpty()) {
212 crop = mCurrentCrop;
213 } else if (mActiveBuffer != NULL){
214 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
215 } else {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700216 crop.makeInvalid();
217 return crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700218 }
219
220 // ... then reduce that in the same proportions as the window crop reduces
221 // the window size.
222 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700223 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700224 // Transform the window crop to match the buffer coordinate system,
225 // which means using the inverse of the current transform set on the
226 // SurfaceTexture.
227 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700228 int winWidth = s.active.w;
229 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700230 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
231 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
232 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700233 winWidth = s.active.h;
234 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700235 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700236 Rect winCrop = s.active.crop.transform(invTransform,
237 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700238
239 float xScale = float(crop.width()) / float(winWidth);
240 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700241 crop.left += int(ceilf(float(winCrop.left) * xScale));
242 crop.top += int(ceilf(float(winCrop.top) * yScale));
243 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
244 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700245 }
246
247 return crop;
248}
249
Mathias Agopian4fec8732012-06-29 14:12:52 -0700250void Layer::setGeometry(
251 const DisplayHardware& hw,
252 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700253{
Mathias Agopian4fec8732012-06-29 14:12:52 -0700254 LayerBaseClient::setGeometry(hw, layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700255
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700256 // enable this layer
257 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700258
259 // we can't do alpha-fade with the hwc HAL
260 const State& s(drawingState());
261 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700262 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700263 }
264
Mathias Agopian29a367b2011-07-12 14:51:45 -0700265 /*
266 * Transformations are applied in this order:
267 * 1) buffer orientation/flip/mirror
268 * 2) state transformation (window manager)
269 * 3) layer orientation (screen orientation)
270 * (NOTE: the matrices are multiplied in reverse order)
271 */
272
273 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700274 const Transform tr(hw.getTransform() * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700275
276 // this gives us only the "orientation" component of the transform
277 const uint32_t finalTransform = tr.getOrientation();
278
Mathias Agopiana350ff92010-08-10 17:14:02 -0700279 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700280 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700281 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700282 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700283 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700284 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700285 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700286}
287
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700288void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700289 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700290 // NOTE: buffer can be NULL if the client never drew into this
291 // layer yet, or if we ran out of memory
292 layer.setBuffer(buffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700293}
Jesse Halldc5b4852012-06-29 15:21:18 -0700294
Jesse Hallc5c5a142012-07-02 16:49:28 -0700295void Layer::setAcquireFence(HWComposer::HWCLayerInterface& layer) {
296 int fenceFd = -1;
Mathias Agopian52bbb1a2012-07-31 19:01:53 -0700297 if (mNeedHwcFence && (layer.getCompositionType() == HWC_OVERLAY)) {
Jesse Halldc5b4852012-06-29 15:21:18 -0700298 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
299 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700300 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700301 if (fenceFd == -1) {
302 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
303 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700304 }
305 mNeedHwcFence = false;
Jesse Halldc5b4852012-06-29 15:21:18 -0700306 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700307 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700308}
309
Mathias Agopian1b031492012-06-20 17:51:20 -0700310void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800311{
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;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700332 under.orSelf( hw.getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700333 }
334 // if not everything below us is covered, we plug the holes!
335 Region holes(clip.subtract(under));
336 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700337 clearWithOpenGL(hw, 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
Jesse Halldc5b4852012-06-29 15:21:18 -0700342 // TODO: replace this with a server-side wait
343 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
344 if (fence.get()) {
345 status_t err = fence->wait(Fence::TIMEOUT_NEVER);
346 ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
347 // Go ahead and draw the buffer anyway; no matter what we do the screen
348 // is probably going to have something visibly wrong.
349 }
350
Jamie Gennis9575f602011-10-07 14:51:16 -0700351 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700352 // TODO: we could be more subtle with isFixedSize()
353 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
354
355 // Query the texture matrix given our current filtering mode.
356 float textureMatrix[16];
357 mSurfaceTexture->setFilteringEnabled(useFiltering);
358 mSurfaceTexture->getTransformMatrix(textureMatrix);
359
360 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700361 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
362 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700363 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700364 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700365 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700366 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
367 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700368 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700369 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700370 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700371 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700372 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700373 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700374 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700375 glMatrixMode(GL_TEXTURE);
376 glLoadIdentity();
377 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700378 glDisable(GL_TEXTURE_EXTERNAL_OES);
379 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700380 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700381
Mathias Agopian1b031492012-06-20 17:51:20 -0700382 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700383
Mathias Agopianc492e672011-10-18 14:49:27 -0700384 glDisable(GL_TEXTURE_EXTERNAL_OES);
385 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800386}
387
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800388// As documented in libhardware header, formats in the range
389// 0x100 - 0x1FF are specific to the HAL implementation, and
390// are known to have no alpha channel
391// TODO: move definition for device-specific range into
392// hardware.h, instead of using hard-coded values here.
393#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
394
Mathias Agopiana67932f2011-04-20 14:20:59 -0700395bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800396{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700397 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
398 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800399 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700400 PixelFormatInfo info;
401 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
402 // in case of error (unknown format), we assume no blending
403 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800404}
405
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800406
Mathias Agopiana67932f2011-04-20 14:20:59 -0700407bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700408{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700409 // if we don't have a buffer yet, we're translucent regardless of the
410 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700411 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700412 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700413 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700414
415 // if the layer has the opaque flag, then we're always opaque,
416 // otherwise we use the current buffer's format.
417 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700418}
419
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800420bool Layer::isProtected() const
421{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700422 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800423 return (activeBuffer != 0) &&
424 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
425}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700426
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800427uint32_t Layer::doTransaction(uint32_t flags)
428{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800429 ATRACE_CALL();
430
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800431 const Layer::State& front(drawingState());
432 const Layer::State& temp(currentState());
433
Mathias Agopian4824d402012-06-04 18:16:30 -0700434 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
435 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700436
437 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700438 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000439 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700440 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
441 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
442 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
443 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
444 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
445 this, mCurrentScalingMode,
446 temp.active.w, temp.active.h,
447 temp.active.crop.left,
448 temp.active.crop.top,
449 temp.active.crop.right,
450 temp.active.crop.bottom,
451 temp.active.crop.getWidth(),
452 temp.active.crop.getHeight(),
453 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700454 temp.requested.crop.left,
455 temp.requested.crop.top,
456 temp.requested.crop.right,
457 temp.requested.crop.bottom,
458 temp.requested.crop.getWidth(),
459 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700460 front.active.w, front.active.h,
461 front.active.crop.left,
462 front.active.crop.top,
463 front.active.crop.right,
464 front.active.crop.bottom,
465 front.active.crop.getWidth(),
466 front.active.crop.getHeight(),
467 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700468 front.requested.crop.left,
469 front.requested.crop.top,
470 front.requested.crop.right,
471 front.requested.crop.bottom,
472 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700473 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800474
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700475 // record the new size, form this point on, when the client request
476 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700477 mSurfaceTexture->setDefaultBufferSize(
478 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800479 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700480
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700481 if (!isFixedSize()) {
482
483 const bool resizePending = (temp.requested.w != temp.active.w) ||
484 (temp.requested.h != temp.active.h);
485
486 if (resizePending) {
487 // don't let LayerBase::doTransaction update the drawing state
488 // if we have a pending resize, unless we are in fixed-size mode.
489 // the drawing state will be updated only once we receive a buffer
490 // with the correct size.
491 //
492 // in particular, we want to make sure the clip (which is part
493 // of the geometry state) is latched together with the size but is
494 // latched immediately when no resizing is involved.
495
496 flags |= eDontUpdateGeometryState;
497 }
498 }
499
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800500 return LayerBase::doTransaction(flags);
501}
502
Mathias Agopiana138f892010-05-21 17:24:35 -0700503bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700504 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700505}
506
507bool Layer::isCropped() const {
508 return !mCurrentCrop.isEmpty();
509}
510
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800511// ----------------------------------------------------------------------------
512// pageflip handling...
513// ----------------------------------------------------------------------------
514
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800515bool Layer::onPreComposition() {
516 mRefreshPending = false;
517 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800518}
519
Mathias Agopian4fec8732012-06-29 14:12:52 -0700520Region Layer::latchBuffer(bool& recomputeVisibleRegions)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800521{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800522 ATRACE_CALL();
523
Mathias Agopian4fec8732012-06-29 14:12:52 -0700524 Region outDirtyRegion;
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700525 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800526
527 // if we've already called updateTexImage() without going through
528 // a composition step, we have to skip this layer at this point
529 // because we cannot call updateTeximage() without a corresponding
530 // compositionComplete() call.
531 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800532 if (mRefreshPending) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700533 return outDirtyRegion;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800534 }
535
Jamie Gennis351a5132011-09-14 18:23:37 -0700536 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700537 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700538 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700539
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700540 // signal another event if we have more frames pending
541 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800542 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700543 }
544
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700545 struct Reject : public SurfaceTexture::BufferRejecter {
546 Layer::State& front;
547 Layer::State& current;
548 bool& recomputeVisibleRegions;
549 Reject(Layer::State& front, Layer::State& current,
550 bool& recomputeVisibleRegions)
551 : front(front), current(current),
552 recomputeVisibleRegions(recomputeVisibleRegions) {
553 }
554
555 virtual bool reject(const sp<GraphicBuffer>& buf,
556 const BufferQueue::BufferItem& item) {
557 if (buf == NULL) {
558 return false;
559 }
560
561 uint32_t bufWidth = buf->getWidth();
562 uint32_t bufHeight = buf->getHeight();
563
564 // check that we received a buffer of the right size
565 // (Take the buffer's orientation into account)
566 if (item.mTransform & Transform::ROT_90) {
567 swap(bufWidth, bufHeight);
568 }
569
570
571 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
572 if (front.active != front.requested) {
573
574 if (isFixedSize ||
575 (bufWidth == front.requested.w &&
576 bufHeight == front.requested.h))
577 {
578 // Here we pretend the transaction happened by updating the
579 // current and drawing states. Drawing state is only accessed
580 // in this thread, no need to have it locked
581 front.active = front.requested;
582
583 // We also need to update the current state so that
584 // we don't end-up overwriting the drawing state with
585 // this stale current state during the next transaction
586 //
587 // NOTE: We don't need to hold the transaction lock here
588 // because State::active is only accessed from this thread.
589 current.active = front.active;
590
591 // recompute visible region
592 recomputeVisibleRegions = true;
593 }
594
595 ALOGD_IF(DEBUG_RESIZE,
596 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
597 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
598 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
599 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
600 front.active.w, front.active.h,
601 front.active.crop.left,
602 front.active.crop.top,
603 front.active.crop.right,
604 front.active.crop.bottom,
605 front.active.crop.getWidth(),
606 front.active.crop.getHeight(),
607 front.requested.w, front.requested.h,
608 front.requested.crop.left,
609 front.requested.crop.top,
610 front.requested.crop.right,
611 front.requested.crop.bottom,
612 front.requested.crop.getWidth(),
613 front.requested.crop.getHeight());
614 }
615
616 if (!isFixedSize) {
617 if (front.active.w != bufWidth ||
618 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700619 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700620 return true;
621 }
622 }
623 return false;
624 }
625 };
626
627
628 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
629
Mathias Agopian4fec8732012-06-29 14:12:52 -0700630 // XXX: not sure if setTransformHint belongs here
631 // it should only be needed when the main screen orientation changes
632 mSurfaceTexture->setTransformHint(getTransformHint());
633
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700634 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700635 // something happened!
636 recomputeVisibleRegions = true;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700637 return outDirtyRegion;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700638 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700639
Jamie Gennis351a5132011-09-14 18:23:37 -0700640 // update the active buffer
641 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700642 if (mActiveBuffer == NULL) {
643 // this can only happen if the very first buffer was rejected.
Mathias Agopian4fec8732012-06-29 14:12:52 -0700644 return outDirtyRegion;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700645 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800646
Mathias Agopian4824d402012-06-04 18:16:30 -0700647 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700648 mFrameLatencyNeeded = true;
Jesse Halldc5b4852012-06-29 15:21:18 -0700649 mNeedHwcFence = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700650 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700651 // the first time we receive a buffer, we need to trigger a
652 // geometry invalidation.
653 mFlinger->invalidateHwcGeometry();
654 }
655
Mathias Agopian702634a2012-05-23 17:50:31 -0700656 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700657 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
658 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700659 if ((crop != mCurrentCrop) ||
660 (transform != mCurrentTransform) ||
661 (scalingMode != mCurrentScalingMode))
662 {
663 mCurrentCrop = crop;
664 mCurrentTransform = transform;
665 mCurrentScalingMode = scalingMode;
666 mFlinger->invalidateHwcGeometry();
667 }
668
669 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700670 uint32_t bufWidth = mActiveBuffer->getWidth();
671 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700672 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
673 bufHeight != uint32_t(oldActiveBuffer->height)) {
674 mFlinger->invalidateHwcGeometry();
675 }
676 }
677
678 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
679 if (oldOpacity != isOpaque()) {
680 recomputeVisibleRegions = true;
681 }
682
Mathias Agopian702634a2012-05-23 17:50:31 -0700683 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
684 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700685
686 // FIXME: postedRegion should be dirty & bounds
687 const Layer::State& front(drawingState());
688 Region dirtyRegion(Rect(front.active.w, front.active.h));
689
690 // transform the dirty region to window-manager space
691 outDirtyRegion = (front.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700692 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700693 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694}
695
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700696void Layer::dump(String8& result, char* buffer, size_t SIZE) const
697{
698 LayerBaseClient::dump(result, buffer, SIZE);
699
Mathias Agopiana67932f2011-04-20 14:20:59 -0700700 sp<const GraphicBuffer> buf0(mActiveBuffer);
701 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700702 if (buf0 != 0) {
703 w0 = buf0->getWidth();
704 h0 = buf0->getHeight();
705 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700706 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700707 }
708 snprintf(buffer, SIZE,
709 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700710 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800711 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700712 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800713 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700714
715 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700716
Mathias Agopiana67932f2011-04-20 14:20:59 -0700717 if (mSurfaceTexture != 0) {
718 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700719 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700720}
721
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800722void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
723{
724 LayerBaseClient::dumpStats(result, buffer, SIZE);
725 const size_t o = mFrameLatencyOffset;
Mathias Agopian1b031492012-06-20 17:51:20 -0700726 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800727 const nsecs_t period = hw.getRefreshPeriod();
728 result.appendFormat("%lld\n", period);
729 for (size_t i=0 ; i<128 ; i++) {
730 const size_t index = (o+i) % 128;
731 const nsecs_t time_app = mFrameStats[index].timestamp;
732 const nsecs_t time_set = mFrameStats[index].set;
733 const nsecs_t time_vsync = mFrameStats[index].vsync;
734 result.appendFormat("%lld\t%lld\t%lld\n",
735 time_app,
736 time_vsync,
737 time_set);
738 }
739 result.append("\n");
740}
741
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800742void Layer::clearStats()
743{
744 LayerBaseClient::clearStats();
745 memset(mFrameStats, 0, sizeof(mFrameStats));
746}
747
Mathias Agopiana67932f2011-04-20 14:20:59 -0700748uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700749{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700750 // TODO: should we do something special if mSecure is set?
751 if (mProtectedByApp) {
752 // need a hardware-protected path to external video sink
753 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700754 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700755 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700756 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700757}
758
Mathias Agopiana4583642011-08-23 18:03:18 -0700759uint32_t Layer::getTransformHint() const {
760 uint32_t orientation = 0;
761 if (!mFlinger->mDebugDisableTransformHint) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700762 // The transform hint is used to improve performance on the main
763 // display -- we can only have a single transform hint, it cannot
764 // apply to all displays.
765 // This is why we use the default display here. This is not an
766 // oversight.
767 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
768 const Transform& planeTransform(hw.getTransform());
769 orientation = planeTransform.getOrientation();
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