blob: a09b5c7bf03681713eb571851a4e373da21ccab1 [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 Agopian401c2572009-09-23 19:16:27 -0700185 // the display's pixel format
Mathias Agopian1b031492012-06-20 17:51:20 -0700186 // XXX: we shouldn't rely on the DisplayHardware to do this
187 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700188 uint32_t const maxSurfaceDims = min(
189 hw.getMaxTextureSize(), hw.getMaxViewportDims());
190
191 // never allow a surface larger than what our underlying GL implementation
192 // can handle.
193 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800194 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700195 return BAD_VALUE;
196 }
197
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700198 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700199
Mathias Agopian3330b202009-10-05 17:07:12 -0700200 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800201 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700202 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
203 mCurrentOpacity = getOpacityForFormat(format);
204
205 mSurfaceTexture->setDefaultBufferSize(w, h);
206 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800207 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700208
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209 return NO_ERROR;
210}
211
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700212Rect Layer::computeBufferCrop() const {
213 // Start with the SurfaceTexture's buffer crop...
214 Rect crop;
215 if (!mCurrentCrop.isEmpty()) {
216 crop = mCurrentCrop;
217 } else if (mActiveBuffer != NULL){
218 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
219 } else {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700220 crop.makeInvalid();
221 return crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700222 }
223
224 // ... then reduce that in the same proportions as the window crop reduces
225 // the window size.
226 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700227 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700228 // Transform the window crop to match the buffer coordinate system,
229 // which means using the inverse of the current transform set on the
230 // SurfaceTexture.
231 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700232 int winWidth = s.active.w;
233 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700234 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
235 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
236 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700237 winWidth = s.active.h;
238 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700239 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700240 Rect winCrop = s.active.crop.transform(invTransform,
241 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700242
243 float xScale = float(crop.width()) / float(winWidth);
244 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700245 crop.left += int(ceilf(float(winCrop.left) * xScale));
246 crop.top += int(ceilf(float(winCrop.top) * yScale));
247 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
248 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700249 }
250
251 return crop;
252}
253
Mathias Agopian4fec8732012-06-29 14:12:52 -0700254void Layer::setGeometry(
255 const DisplayHardware& hw,
256 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700257{
Mathias Agopian4fec8732012-06-29 14:12:52 -0700258 LayerBaseClient::setGeometry(hw, layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700259
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700260 // enable this layer
261 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700262
263 // we can't do alpha-fade with the hwc HAL
264 const State& s(drawingState());
265 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700266 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700267 }
268
Mathias Agopian29a367b2011-07-12 14:51:45 -0700269 /*
270 * Transformations are applied in this order:
271 * 1) buffer orientation/flip/mirror
272 * 2) state transformation (window manager)
273 * 3) layer orientation (screen orientation)
274 * (NOTE: the matrices are multiplied in reverse order)
275 */
276
277 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700278 const Transform tr(hw.getTransform() * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700279
280 // this gives us only the "orientation" component of the transform
281 const uint32_t finalTransform = tr.getOrientation();
282
Mathias Agopiana350ff92010-08-10 17:14:02 -0700283 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700284 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700285 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700286 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700287 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700288 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700289 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700290}
291
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700292void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700293 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700294 // NOTE: buffer can be NULL if the client never drew into this
295 // layer yet, or if we ran out of memory
296 layer.setBuffer(buffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700297}
Jesse Halldc5b4852012-06-29 15:21:18 -0700298
Jesse Hallc5c5a142012-07-02 16:49:28 -0700299void Layer::setAcquireFence(HWComposer::HWCLayerInterface& layer) {
300 int fenceFd = -1;
Jesse Halldc5b4852012-06-29 15:21:18 -0700301 if (mNeedHwcFence) {
302 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
303 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700304 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700305 if (fenceFd == -1) {
306 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
307 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700308 }
309 mNeedHwcFence = false;
Jesse Halldc5b4852012-06-29 15:21:18 -0700310 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700311 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700312}
313
Mathias Agopian1b031492012-06-20 17:51:20 -0700314void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800315{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800316 ATRACE_CALL();
317
Mathias Agopiana67932f2011-04-20 14:20:59 -0700318 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800319 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700320 // in fact never been drawn into. This happens frequently with
321 // SurfaceView because the WindowManager can't know when the client
322 // has drawn the first time.
323
324 // If there is nothing under us, we paint the screen in black, otherwise
325 // we just skip this update.
326
327 // figure out if there is something below us
328 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700329 const SurfaceFlinger::LayerVector& drawingLayers(
330 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700331 const size_t count = drawingLayers.size();
332 for (size_t i=0 ; i<count ; ++i) {
333 const sp<LayerBase>& layer(drawingLayers[i]);
334 if (layer.get() == static_cast<LayerBase const*>(this))
335 break;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700336 under.orSelf( hw.getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700337 }
338 // if not everything below us is covered, we plug the holes!
339 Region holes(clip.subtract(under));
340 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700341 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700342 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800343 return;
344 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700345
Jesse Halldc5b4852012-06-29 15:21:18 -0700346 // TODO: replace this with a server-side wait
347 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
348 if (fence.get()) {
349 status_t err = fence->wait(Fence::TIMEOUT_NEVER);
350 ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
351 // Go ahead and draw the buffer anyway; no matter what we do the screen
352 // is probably going to have something visibly wrong.
353 }
354
Jamie Gennis9575f602011-10-07 14:51:16 -0700355 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700356 // TODO: we could be more subtle with isFixedSize()
357 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
358
359 // Query the texture matrix given our current filtering mode.
360 float textureMatrix[16];
361 mSurfaceTexture->setFilteringEnabled(useFiltering);
362 mSurfaceTexture->getTransformMatrix(textureMatrix);
363
364 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700365 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
366 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700367 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700368 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700369 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700370 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
371 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700372 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700373 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700374 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700375 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700376 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700377 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700378 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700379 glMatrixMode(GL_TEXTURE);
380 glLoadIdentity();
381 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700382 glDisable(GL_TEXTURE_EXTERNAL_OES);
383 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700384 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700385
Mathias Agopian1b031492012-06-20 17:51:20 -0700386 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700387
Mathias Agopianc492e672011-10-18 14:49:27 -0700388 glDisable(GL_TEXTURE_EXTERNAL_OES);
389 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800390}
391
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800392// As documented in libhardware header, formats in the range
393// 0x100 - 0x1FF are specific to the HAL implementation, and
394// are known to have no alpha channel
395// TODO: move definition for device-specific range into
396// hardware.h, instead of using hard-coded values here.
397#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
398
Mathias Agopiana67932f2011-04-20 14:20:59 -0700399bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800400{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700401 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
402 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800403 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700404 PixelFormatInfo info;
405 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
406 // in case of error (unknown format), we assume no blending
407 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800408}
409
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800410
Mathias Agopiana67932f2011-04-20 14:20:59 -0700411bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700412{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700413 // if we don't have a buffer yet, we're translucent regardless of the
414 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700415 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700416 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700417 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700418
419 // if the layer has the opaque flag, then we're always opaque,
420 // otherwise we use the current buffer's format.
421 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700422}
423
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800424bool Layer::isProtected() const
425{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700426 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800427 return (activeBuffer != 0) &&
428 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
429}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700430
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800431uint32_t Layer::doTransaction(uint32_t flags)
432{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800433 ATRACE_CALL();
434
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800435 const Layer::State& front(drawingState());
436 const Layer::State& temp(currentState());
437
Mathias Agopian4824d402012-06-04 18:16:30 -0700438 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
439 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700440
441 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700442 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000443 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700444 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
445 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
446 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
447 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
448 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
449 this, mCurrentScalingMode,
450 temp.active.w, temp.active.h,
451 temp.active.crop.left,
452 temp.active.crop.top,
453 temp.active.crop.right,
454 temp.active.crop.bottom,
455 temp.active.crop.getWidth(),
456 temp.active.crop.getHeight(),
457 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700458 temp.requested.crop.left,
459 temp.requested.crop.top,
460 temp.requested.crop.right,
461 temp.requested.crop.bottom,
462 temp.requested.crop.getWidth(),
463 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700464 front.active.w, front.active.h,
465 front.active.crop.left,
466 front.active.crop.top,
467 front.active.crop.right,
468 front.active.crop.bottom,
469 front.active.crop.getWidth(),
470 front.active.crop.getHeight(),
471 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700472 front.requested.crop.left,
473 front.requested.crop.top,
474 front.requested.crop.right,
475 front.requested.crop.bottom,
476 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700477 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800478
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700479 // record the new size, form this point on, when the client request
480 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700481 mSurfaceTexture->setDefaultBufferSize(
482 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800483 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700484
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700485 if (!isFixedSize()) {
486
487 const bool resizePending = (temp.requested.w != temp.active.w) ||
488 (temp.requested.h != temp.active.h);
489
490 if (resizePending) {
491 // don't let LayerBase::doTransaction update the drawing state
492 // if we have a pending resize, unless we are in fixed-size mode.
493 // the drawing state will be updated only once we receive a buffer
494 // with the correct size.
495 //
496 // in particular, we want to make sure the clip (which is part
497 // of the geometry state) is latched together with the size but is
498 // latched immediately when no resizing is involved.
499
500 flags |= eDontUpdateGeometryState;
501 }
502 }
503
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800504 return LayerBase::doTransaction(flags);
505}
506
Mathias Agopiana138f892010-05-21 17:24:35 -0700507bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700508 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700509}
510
511bool Layer::isCropped() const {
512 return !mCurrentCrop.isEmpty();
513}
514
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800515// ----------------------------------------------------------------------------
516// pageflip handling...
517// ----------------------------------------------------------------------------
518
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800519bool Layer::onPreComposition() {
520 mRefreshPending = false;
521 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800522}
523
Mathias Agopian4fec8732012-06-29 14:12:52 -0700524Region Layer::latchBuffer(bool& recomputeVisibleRegions)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800525{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800526 ATRACE_CALL();
527
Mathias Agopian4fec8732012-06-29 14:12:52 -0700528 Region outDirtyRegion;
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700529 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800530
531 // if we've already called updateTexImage() without going through
532 // a composition step, we have to skip this layer at this point
533 // because we cannot call updateTeximage() without a corresponding
534 // compositionComplete() call.
535 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800536 if (mRefreshPending) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700537 return outDirtyRegion;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800538 }
539
Jamie Gennis351a5132011-09-14 18:23:37 -0700540 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700541 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700542 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700543
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700544 // signal another event if we have more frames pending
545 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800546 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700547 }
548
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700549 struct Reject : public SurfaceTexture::BufferRejecter {
550 Layer::State& front;
551 Layer::State& current;
552 bool& recomputeVisibleRegions;
553 Reject(Layer::State& front, Layer::State& current,
554 bool& recomputeVisibleRegions)
555 : front(front), current(current),
556 recomputeVisibleRegions(recomputeVisibleRegions) {
557 }
558
559 virtual bool reject(const sp<GraphicBuffer>& buf,
560 const BufferQueue::BufferItem& item) {
561 if (buf == NULL) {
562 return false;
563 }
564
565 uint32_t bufWidth = buf->getWidth();
566 uint32_t bufHeight = buf->getHeight();
567
568 // check that we received a buffer of the right size
569 // (Take the buffer's orientation into account)
570 if (item.mTransform & Transform::ROT_90) {
571 swap(bufWidth, bufHeight);
572 }
573
574
575 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
576 if (front.active != front.requested) {
577
578 if (isFixedSize ||
579 (bufWidth == front.requested.w &&
580 bufHeight == front.requested.h))
581 {
582 // Here we pretend the transaction happened by updating the
583 // current and drawing states. Drawing state is only accessed
584 // in this thread, no need to have it locked
585 front.active = front.requested;
586
587 // We also need to update the current state so that
588 // we don't end-up overwriting the drawing state with
589 // this stale current state during the next transaction
590 //
591 // NOTE: We don't need to hold the transaction lock here
592 // because State::active is only accessed from this thread.
593 current.active = front.active;
594
595 // recompute visible region
596 recomputeVisibleRegions = true;
597 }
598
599 ALOGD_IF(DEBUG_RESIZE,
600 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
601 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
602 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
603 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
604 front.active.w, front.active.h,
605 front.active.crop.left,
606 front.active.crop.top,
607 front.active.crop.right,
608 front.active.crop.bottom,
609 front.active.crop.getWidth(),
610 front.active.crop.getHeight(),
611 front.requested.w, front.requested.h,
612 front.requested.crop.left,
613 front.requested.crop.top,
614 front.requested.crop.right,
615 front.requested.crop.bottom,
616 front.requested.crop.getWidth(),
617 front.requested.crop.getHeight());
618 }
619
620 if (!isFixedSize) {
621 if (front.active.w != bufWidth ||
622 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700623 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700624 return true;
625 }
626 }
627 return false;
628 }
629 };
630
631
632 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
633
Mathias Agopian4fec8732012-06-29 14:12:52 -0700634 // XXX: not sure if setTransformHint belongs here
635 // it should only be needed when the main screen orientation changes
636 mSurfaceTexture->setTransformHint(getTransformHint());
637
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700638 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700639 // something happened!
640 recomputeVisibleRegions = true;
Mathias Agopian4fec8732012-06-29 14:12:52 -0700641 return outDirtyRegion;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700642 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700643
Jamie Gennis351a5132011-09-14 18:23:37 -0700644 // update the active buffer
645 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700646 if (mActiveBuffer == NULL) {
647 // this can only happen if the very first buffer was rejected.
Mathias Agopian4fec8732012-06-29 14:12:52 -0700648 return outDirtyRegion;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700649 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800650
Mathias Agopian4824d402012-06-04 18:16:30 -0700651 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700652 mFrameLatencyNeeded = true;
Jesse Halldc5b4852012-06-29 15:21:18 -0700653 mNeedHwcFence = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700654 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700655 // the first time we receive a buffer, we need to trigger a
656 // geometry invalidation.
657 mFlinger->invalidateHwcGeometry();
658 }
659
Mathias Agopian702634a2012-05-23 17:50:31 -0700660 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700661 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
662 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700663 if ((crop != mCurrentCrop) ||
664 (transform != mCurrentTransform) ||
665 (scalingMode != mCurrentScalingMode))
666 {
667 mCurrentCrop = crop;
668 mCurrentTransform = transform;
669 mCurrentScalingMode = scalingMode;
670 mFlinger->invalidateHwcGeometry();
671 }
672
673 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700674 uint32_t bufWidth = mActiveBuffer->getWidth();
675 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700676 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
677 bufHeight != uint32_t(oldActiveBuffer->height)) {
678 mFlinger->invalidateHwcGeometry();
679 }
680 }
681
682 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
683 if (oldOpacity != isOpaque()) {
684 recomputeVisibleRegions = true;
685 }
686
Mathias Agopian702634a2012-05-23 17:50:31 -0700687 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
688 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700689
690 // FIXME: postedRegion should be dirty & bounds
691 const Layer::State& front(drawingState());
692 Region dirtyRegion(Rect(front.active.w, front.active.h));
693
694 // transform the dirty region to window-manager space
695 outDirtyRegion = (front.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700696 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700697 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800698}
699
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700700void Layer::dump(String8& result, char* buffer, size_t SIZE) const
701{
702 LayerBaseClient::dump(result, buffer, SIZE);
703
Mathias Agopiana67932f2011-04-20 14:20:59 -0700704 sp<const GraphicBuffer> buf0(mActiveBuffer);
705 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700706 if (buf0 != 0) {
707 w0 = buf0->getWidth();
708 h0 = buf0->getHeight();
709 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700710 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700711 }
712 snprintf(buffer, SIZE,
713 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700714 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800715 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700716 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800717 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700718
719 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700720
Mathias Agopiana67932f2011-04-20 14:20:59 -0700721 if (mSurfaceTexture != 0) {
722 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700723 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700724}
725
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800726void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
727{
728 LayerBaseClient::dumpStats(result, buffer, SIZE);
729 const size_t o = mFrameLatencyOffset;
Mathias Agopian1b031492012-06-20 17:51:20 -0700730 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800731 const nsecs_t period = hw.getRefreshPeriod();
732 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.
771 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
772 const Transform& planeTransform(hw.getTransform());
773 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