blob: b2f26831bf72f181e13abde8c47edda8dc04e201 [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 Agopian118d0242011-10-13 16:02:48 -0700127 mFlinger->postMessageAsync(
128 new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
Mathias Agopian96f08192010-06-02 23:28:45 -0700129}
130
Mathias Agopiana67932f2011-04-20 14:20:59 -0700131void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700132 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800133 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700134}
135
Mathias Agopiand606de62010-05-10 20:06:11 -0700136// called with SurfaceFlinger::mStateLock as soon as the layer is entered
137// in the purgatory list
138void Layer::onRemoved()
139{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700140 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700141}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700142
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700143void Layer::setName(const String8& name) {
144 LayerBase::setName(name);
145 mSurfaceTexture->setName(name);
146}
147
Mathias Agopiana67932f2011-04-20 14:20:59 -0700148sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800149{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700150 class BSurface : public BnSurface, public LayerCleaner {
151 wp<const Layer> mOwner;
152 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
153 sp<ISurfaceTexture> res;
154 sp<const Layer> that( mOwner.promote() );
155 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800156 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700157 }
158 return res;
159 }
160 public:
161 BSurface(const sp<SurfaceFlinger>& flinger,
162 const sp<Layer>& layer)
163 : LayerCleaner(flinger, layer), mOwner(layer) { }
164 };
165 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800166 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800167}
168
Jamie Gennis582270d2011-08-17 18:19:00 -0700169wp<IBinder> Layer::getSurfaceTextureBinder() const
170{
Daniel Lamb2675792012-02-23 14:35:13 -0800171 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700172}
173
Mathias Agopianf9d93272009-06-19 17:00:27 -0700174status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800175 PixelFormat format, uint32_t flags)
176{
Mathias Agopian401c2572009-09-23 19:16:27 -0700177 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800178 PixelFormatInfo info;
179 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800180 if (err) {
181 ALOGE("unsupported pixelformat %d", format);
182 return err;
183 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800184
Mathias Agopianca99fb82010-04-14 16:43:44 -0700185 uint32_t const maxSurfaceDims = min(
Mathias Agopiana4912602012-07-12 14:25:33 -0700186 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700187
188 // never allow a surface larger than what our underlying GL implementation
189 // can handle.
190 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800191 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700192 return BAD_VALUE;
193 }
194
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700195 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700196
Mathias Agopian3330b202009-10-05 17:07:12 -0700197 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800198 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700199 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
200 mCurrentOpacity = getOpacityForFormat(format);
201
202 mSurfaceTexture->setDefaultBufferSize(w, h);
203 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800204 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700205
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800206 return NO_ERROR;
207}
208
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700209Rect Layer::computeBufferCrop() const {
210 // Start with the SurfaceTexture's buffer crop...
211 Rect crop;
212 if (!mCurrentCrop.isEmpty()) {
213 crop = mCurrentCrop;
214 } else if (mActiveBuffer != NULL){
215 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
216 } else {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700217 crop.makeInvalid();
218 return crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700219 }
220
221 // ... then reduce that in the same proportions as the window crop reduces
222 // the window size.
223 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700224 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700225 // Transform the window crop to match the buffer coordinate system,
226 // which means using the inverse of the current transform set on the
227 // SurfaceTexture.
228 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700229 int winWidth = s.active.w;
230 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700231 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
232 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
233 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700234 winWidth = s.active.h;
235 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700236 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700237 Rect winCrop = s.active.crop.transform(invTransform,
238 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700239
240 float xScale = float(crop.width()) / float(winWidth);
241 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700242 crop.left += int(ceilf(float(winCrop.left) * xScale));
243 crop.top += int(ceilf(float(winCrop.top) * yScale));
244 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
245 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700246 }
247
248 return crop;
249}
250
Mathias Agopian4fec8732012-06-29 14:12:52 -0700251void Layer::setGeometry(
252 const DisplayHardware& hw,
253 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700254{
Mathias Agopian4fec8732012-06-29 14:12:52 -0700255 LayerBaseClient::setGeometry(hw, layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700256
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700257 // enable this layer
258 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700259
260 // we can't do alpha-fade with the hwc HAL
261 const State& s(drawingState());
262 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700263 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700264 }
265
Mathias Agopian29a367b2011-07-12 14:51:45 -0700266 /*
267 * Transformations are applied in this order:
268 * 1) buffer orientation/flip/mirror
269 * 2) state transformation (window manager)
270 * 3) layer orientation (screen orientation)
271 * (NOTE: the matrices are multiplied in reverse order)
272 */
273
274 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700275 const Transform tr(hw.getTransform() * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700276
277 // this gives us only the "orientation" component of the transform
278 const uint32_t finalTransform = tr.getOrientation();
279
Mathias Agopiana350ff92010-08-10 17:14:02 -0700280 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700281 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700282 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700283 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700284 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700285 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700286 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700287}
288
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700289void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700290 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700291 // NOTE: buffer can be NULL if the client never drew into this
292 // layer yet, or if we ran out of memory
293 layer.setBuffer(buffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700294}
Jesse Halldc5b4852012-06-29 15:21:18 -0700295
Jesse Hallc5c5a142012-07-02 16:49:28 -0700296void Layer::setAcquireFence(HWComposer::HWCLayerInterface& layer) {
297 int fenceFd = -1;
Jesse Halldc5b4852012-06-29 15:21:18 -0700298 if (mNeedHwcFence) {
299 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
300 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700301 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700302 if (fenceFd == -1) {
303 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
304 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700305 }
306 mNeedHwcFence = false;
Jesse Halldc5b4852012-06-29 15:21:18 -0700307 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700308 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700309}
310
Mathias Agopian1b031492012-06-20 17:51:20 -0700311void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800312{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800313 ATRACE_CALL();
314
Mathias Agopiana67932f2011-04-20 14:20:59 -0700315 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800316 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700317 // in fact never been drawn into. This happens frequently with
318 // SurfaceView because the WindowManager can't know when the client
319 // has drawn the first time.
320
321 // If there is nothing under us, we paint the screen in black, otherwise
322 // we just skip this update.
323
324 // figure out if there is something below us
325 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700326 const SurfaceFlinger::LayerVector& drawingLayers(
327 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700328 const size_t count = drawingLayers.size();
329 for (size_t i=0 ; i<count ; ++i) {
330 const sp<LayerBase>& layer(drawingLayers[i]);
331 if (layer.get() == static_cast<LayerBase const*>(this))
332 break;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700333 under.orSelf( hw.getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700334 }
335 // if not everything below us is covered, we plug the holes!
336 Region holes(clip.subtract(under));
337 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700338 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700339 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800340 return;
341 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700342
Jesse Halldc5b4852012-06-29 15:21:18 -0700343 // TODO: replace this with a server-side wait
344 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
345 if (fence.get()) {
346 status_t err = fence->wait(Fence::TIMEOUT_NEVER);
347 ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
348 // Go ahead and draw the buffer anyway; no matter what we do the screen
349 // is probably going to have something visibly wrong.
350 }
351
Jamie Gennis9575f602011-10-07 14:51:16 -0700352 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700353 // TODO: we could be more subtle with isFixedSize()
354 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
355
356 // Query the texture matrix given our current filtering mode.
357 float textureMatrix[16];
358 mSurfaceTexture->setFilteringEnabled(useFiltering);
359 mSurfaceTexture->getTransformMatrix(textureMatrix);
360
361 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700362 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
363 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700364 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700365 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700366 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700367 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
368 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700369 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700370 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700371 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700372 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700373 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700374 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700375 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700376 glMatrixMode(GL_TEXTURE);
377 glLoadIdentity();
378 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700379 glDisable(GL_TEXTURE_EXTERNAL_OES);
380 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700381 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700382
Mathias Agopian1b031492012-06-20 17:51:20 -0700383 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700384
Mathias Agopianc492e672011-10-18 14:49:27 -0700385 glDisable(GL_TEXTURE_EXTERNAL_OES);
386 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800387}
388
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800389// As documented in libhardware header, formats in the range
390// 0x100 - 0x1FF are specific to the HAL implementation, and
391// are known to have no alpha channel
392// TODO: move definition for device-specific range into
393// hardware.h, instead of using hard-coded values here.
394#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
395
Mathias Agopiana67932f2011-04-20 14:20:59 -0700396bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800397{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700398 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
399 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800400 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700401 PixelFormatInfo info;
402 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
403 // in case of error (unknown format), we assume no blending
404 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800405}
406
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800407
Mathias Agopiana67932f2011-04-20 14:20:59 -0700408bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700409{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700410 // if we don't have a buffer yet, we're translucent regardless of the
411 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700412 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700413 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700414 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700415
416 // if the layer has the opaque flag, then we're always opaque,
417 // otherwise we use the current buffer's format.
418 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700419}
420
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800421bool Layer::isProtected() const
422{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700423 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800424 return (activeBuffer != 0) &&
425 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
426}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700427
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800428uint32_t Layer::doTransaction(uint32_t flags)
429{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800430 ATRACE_CALL();
431
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800432 const Layer::State& front(drawingState());
433 const Layer::State& temp(currentState());
434
Mathias Agopian4824d402012-06-04 18:16:30 -0700435 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
436 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700437
438 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700439 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000440 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700441 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
442 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
443 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
444 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
445 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
446 this, mCurrentScalingMode,
447 temp.active.w, temp.active.h,
448 temp.active.crop.left,
449 temp.active.crop.top,
450 temp.active.crop.right,
451 temp.active.crop.bottom,
452 temp.active.crop.getWidth(),
453 temp.active.crop.getHeight(),
454 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700455 temp.requested.crop.left,
456 temp.requested.crop.top,
457 temp.requested.crop.right,
458 temp.requested.crop.bottom,
459 temp.requested.crop.getWidth(),
460 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700461 front.active.w, front.active.h,
462 front.active.crop.left,
463 front.active.crop.top,
464 front.active.crop.right,
465 front.active.crop.bottom,
466 front.active.crop.getWidth(),
467 front.active.crop.getHeight(),
468 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700469 front.requested.crop.left,
470 front.requested.crop.top,
471 front.requested.crop.right,
472 front.requested.crop.bottom,
473 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700474 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800475
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700476 // record the new size, form this point on, when the client request
477 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700478 mSurfaceTexture->setDefaultBufferSize(
479 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800480 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700481
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700482 if (!isFixedSize()) {
483
484 const bool resizePending = (temp.requested.w != temp.active.w) ||
485 (temp.requested.h != temp.active.h);
486
487 if (resizePending) {
488 // don't let LayerBase::doTransaction update the drawing state
489 // if we have a pending resize, unless we are in fixed-size mode.
490 // the drawing state will be updated only once we receive a buffer
491 // with the correct size.
492 //
493 // in particular, we want to make sure the clip (which is part
494 // of the geometry state) is latched together with the size but is
495 // latched immediately when no resizing is involved.
496
497 flags |= eDontUpdateGeometryState;
498 }
499 }
500
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800501 return LayerBase::doTransaction(flags);
502}
503
Mathias Agopiana138f892010-05-21 17:24:35 -0700504bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700505 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700506}
507
508bool Layer::isCropped() const {
509 return !mCurrentCrop.isEmpty();
510}
511
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800512// ----------------------------------------------------------------------------
513// pageflip handling...
514// ----------------------------------------------------------------------------
515
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800516bool Layer::onPreComposition() {
517 mRefreshPending = false;
518 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800519}
520
Mathias Agopian4fec8732012-06-29 14:12:52 -0700521Region Layer::latchBuffer(bool& recomputeVisibleRegions)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800522{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800523 ATRACE_CALL();
524
Mathias Agopian4fec8732012-06-29 14:12:52 -0700525 Region outDirtyRegion;
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700526 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800527
528 // if we've already called updateTexImage() without going through
529 // a composition step, we have to skip this layer at this point
530 // because we cannot call updateTeximage() without a corresponding
531 // compositionComplete() call.
532 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800533 if (mRefreshPending) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700534 return outDirtyRegion;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800535 }
536
Jamie Gennis351a5132011-09-14 18:23:37 -0700537 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700538 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700539 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700540
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700541 // signal another event if we have more frames pending
542 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800543 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700544 }
545
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700546 struct Reject : public SurfaceTexture::BufferRejecter {
547 Layer::State& front;
548 Layer::State& current;
549 bool& recomputeVisibleRegions;
550 Reject(Layer::State& front, Layer::State& current,
551 bool& recomputeVisibleRegions)
552 : front(front), current(current),
553 recomputeVisibleRegions(recomputeVisibleRegions) {
554 }
555
556 virtual bool reject(const sp<GraphicBuffer>& buf,
557 const BufferQueue::BufferItem& item) {
558 if (buf == NULL) {
559 return false;
560 }
561
562 uint32_t bufWidth = buf->getWidth();
563 uint32_t bufHeight = buf->getHeight();
564
565 // check that we received a buffer of the right size
566 // (Take the buffer's orientation into account)
567 if (item.mTransform & Transform::ROT_90) {
568 swap(bufWidth, bufHeight);
569 }
570
571
572 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
573 if (front.active != front.requested) {
574
575 if (isFixedSize ||
576 (bufWidth == front.requested.w &&
577 bufHeight == front.requested.h))
578 {
579 // Here we pretend the transaction happened by updating the
580 // current and drawing states. Drawing state is only accessed
581 // in this thread, no need to have it locked
582 front.active = front.requested;
583
584 // We also need to update the current state so that
585 // we don't end-up overwriting the drawing state with
586 // this stale current state during the next transaction
587 //
588 // NOTE: We don't need to hold the transaction lock here
589 // because State::active is only accessed from this thread.
590 current.active = front.active;
591
592 // recompute visible region
593 recomputeVisibleRegions = true;
594 }
595
596 ALOGD_IF(DEBUG_RESIZE,
597 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
598 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
599 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
600 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
601 front.active.w, front.active.h,
602 front.active.crop.left,
603 front.active.crop.top,
604 front.active.crop.right,
605 front.active.crop.bottom,
606 front.active.crop.getWidth(),
607 front.active.crop.getHeight(),
608 front.requested.w, front.requested.h,
609 front.requested.crop.left,
610 front.requested.crop.top,
611 front.requested.crop.right,
612 front.requested.crop.bottom,
613 front.requested.crop.getWidth(),
614 front.requested.crop.getHeight());
615 }
616
617 if (!isFixedSize) {
618 if (front.active.w != bufWidth ||
619 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700620 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700621 return true;
622 }
623 }
624 return false;
625 }
626 };
627
628
629 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
630
Mathias Agopian4fec8732012-06-29 14:12:52 -0700631 // XXX: not sure if setTransformHint belongs here
632 // it should only be needed when the main screen orientation changes
633 mSurfaceTexture->setTransformHint(getTransformHint());
634
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700635 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700636 // something happened!
637 recomputeVisibleRegions = true;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700638 return outDirtyRegion;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700639 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700640
Jamie Gennis351a5132011-09-14 18:23:37 -0700641 // update the active buffer
642 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700643 if (mActiveBuffer == NULL) {
644 // this can only happen if the very first buffer was rejected.
Mathias Agopian4fec8732012-06-29 14:12:52 -0700645 return outDirtyRegion;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700646 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800647
Mathias Agopian4824d402012-06-04 18:16:30 -0700648 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700649 mFrameLatencyNeeded = true;
Jesse Halldc5b4852012-06-29 15:21:18 -0700650 mNeedHwcFence = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700651 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700652 // the first time we receive a buffer, we need to trigger a
653 // geometry invalidation.
654 mFlinger->invalidateHwcGeometry();
655 }
656
Mathias Agopian702634a2012-05-23 17:50:31 -0700657 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700658 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
659 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700660 if ((crop != mCurrentCrop) ||
661 (transform != mCurrentTransform) ||
662 (scalingMode != mCurrentScalingMode))
663 {
664 mCurrentCrop = crop;
665 mCurrentTransform = transform;
666 mCurrentScalingMode = scalingMode;
667 mFlinger->invalidateHwcGeometry();
668 }
669
670 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700671 uint32_t bufWidth = mActiveBuffer->getWidth();
672 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700673 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
674 bufHeight != uint32_t(oldActiveBuffer->height)) {
675 mFlinger->invalidateHwcGeometry();
676 }
677 }
678
679 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
680 if (oldOpacity != isOpaque()) {
681 recomputeVisibleRegions = true;
682 }
683
Mathias Agopian702634a2012-05-23 17:50:31 -0700684 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
685 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700686
687 // FIXME: postedRegion should be dirty & bounds
688 const Layer::State& front(drawingState());
689 Region dirtyRegion(Rect(front.active.w, front.active.h));
690
691 // transform the dirty region to window-manager space
692 outDirtyRegion = (front.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700693 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700694 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800695}
696
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700697void Layer::dump(String8& result, char* buffer, size_t SIZE) const
698{
699 LayerBaseClient::dump(result, buffer, SIZE);
700
Mathias Agopiana67932f2011-04-20 14:20:59 -0700701 sp<const GraphicBuffer> buf0(mActiveBuffer);
702 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700703 if (buf0 != 0) {
704 w0 = buf0->getWidth();
705 h0 = buf0->getHeight();
706 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700707 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700708 }
709 snprintf(buffer, SIZE,
710 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700711 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800712 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700713 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800714 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700715
716 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700717
Mathias Agopiana67932f2011-04-20 14:20:59 -0700718 if (mSurfaceTexture != 0) {
719 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700720 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700721}
722
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800723void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
724{
725 LayerBaseClient::dumpStats(result, buffer, SIZE);
726 const size_t o = mFrameLatencyOffset;
Mathias Agopian1b031492012-06-20 17:51:20 -0700727 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800728 const nsecs_t period = hw.getRefreshPeriod();
729 result.appendFormat("%lld\n", period);
730 for (size_t i=0 ; i<128 ; i++) {
731 const size_t index = (o+i) % 128;
732 const nsecs_t time_app = mFrameStats[index].timestamp;
733 const nsecs_t time_set = mFrameStats[index].set;
734 const nsecs_t time_vsync = mFrameStats[index].vsync;
735 result.appendFormat("%lld\t%lld\t%lld\n",
736 time_app,
737 time_vsync,
738 time_set);
739 }
740 result.append("\n");
741}
742
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800743void Layer::clearStats()
744{
745 LayerBaseClient::clearStats();
746 memset(mFrameStats, 0, sizeof(mFrameStats));
747}
748
Mathias Agopiana67932f2011-04-20 14:20:59 -0700749uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700750{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700751 // TODO: should we do something special if mSecure is set?
752 if (mProtectedByApp) {
753 // need a hardware-protected path to external video sink
754 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700755 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700756 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700757 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700758}
759
Mathias Agopiana4583642011-08-23 18:03:18 -0700760uint32_t Layer::getTransformHint() const {
761 uint32_t orientation = 0;
762 if (!mFlinger->mDebugDisableTransformHint) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700763 // The transform hint is used to improve performance on the main
764 // display -- we can only have a single transform hint, it cannot
765 // apply to all displays.
766 // This is why we use the default display here. This is not an
767 // oversight.
768 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
769 const Transform& planeTransform(hw.getTransform());
770 orientation = planeTransform.getOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700771 if (orientation & Transform::ROT_INVALID) {
772 orientation = 0;
773 }
774 }
775 return orientation;
776}
777
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800778// ---------------------------------------------------------------------------
779
780
781}; // namespace android