blob: 75eff9f6d3db42a2770800a9a80360f2c9cf826f [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080022#include <math.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023
Mathias Agopiana67932f2011-04-20 14:20:59 -070024#include <cutils/compiler.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070025#include <cutils/native_handle.h>
Mathias Agopiana67932f2011-04-20 14:20:59 -070026#include <cutils/properties.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080027
28#include <utils/Errors.h>
29#include <utils/Log.h>
30#include <utils/StopWatch.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080031#include <utils/Trace.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032
Mathias Agopian3330b202009-10-05 17:07:12 -070033#include <ui/GraphicBuffer.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080034#include <ui/PixelFormat.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080035
Mathias Agopian90ac7992012-02-25 18:48:35 -080036#include <gui/Surface.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037
38#include "clz.h"
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -070039#include "DisplayDevice.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070040#include "GLExtensions.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include "SurfaceFlinger.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070043#include "SurfaceTextureLayer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044
Mathias Agopian1b031492012-06-20 17:51:20 -070045#include "DisplayHardware/HWComposer.h"
46
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#define DEBUG_RESIZE 0
48
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049namespace android {
50
51// ---------------------------------------------------------------------------
52
Mathias Agopian3ee454a2012-08-27 16:28:24 -070053Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
54 : LayerBaseClient(flinger, client),
Mathias Agopiana67932f2011-04-20 14:20:59 -070055 mTextureName(-1U),
56 mQueuedFrames(0),
57 mCurrentTransform(0),
Mathias Agopian933389f2011-07-18 16:15:08 -070058 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
Mathias Agopiana67932f2011-04-20 14:20:59 -070059 mCurrentOpacity(true),
Mathias Agopian4d143ee2012-02-23 20:05:39 -080060 mRefreshPending(false),
Mathias Agopian82d7ab62012-01-19 18:34:40 -080061 mFrameLatencyNeeded(false),
62 mFrameLatencyOffset(0),
Mathias Agopian5bf3abe2011-03-11 17:01:07 -080063 mFormat(PIXEL_FORMAT_NONE),
Mathias Agopian1f7bec62010-06-25 18:02:21 -070064 mGLExtensions(GLExtensions::getInstance()),
Mathias Agopiana67932f2011-04-20 14:20:59 -070065 mOpaqueLayer(true),
Mathias Agopianb7e930d2010-06-01 15:12:58 -070066 mSecure(false),
Mathias Agopian933389f2011-07-18 16:15:08 -070067 mProtectedByApp(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080068{
Mathias Agopiana67932f2011-04-20 14:20:59 -070069 mCurrentCrop.makeInvalid();
70 glGenTextures(1, &mTextureName);
Jamie Gennise8696a42012-01-15 18:54:57 -080071}
72
Mathias Agopian42977342012-08-05 00:40:46 -070073void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -070074 HWComposer::HWCLayerInterface* layer) {
Mathias Agopianc3973602012-08-31 17:51:25 -070075 LayerBaseClient::onLayerDisplayed(hw, layer);
Jesse Hallef194142012-06-14 14:45:17 -070076 if (layer) {
77 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
78 }
Mathias Agopiand606de62010-05-10 20:06:11 -070079}
80
Mathias Agopiana67932f2011-04-20 14:20:59 -070081void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070082{
Mathias Agopiana67932f2011-04-20 14:20:59 -070083 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070084
Mathias Agopiana67932f2011-04-20 14:20:59 -070085 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
86 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
87 private:
88 wp<Layer> mLayer;
89 virtual void onFrameAvailable() {
90 sp<Layer> that(mLayer.promote());
91 if (that != 0) {
92 that->onFrameQueued();
93 }
94 }
95 };
Daniel Lamb2675792012-02-23 14:35:13 -080096
97 // Creates a custom BufferQueue for SurfaceTexture to use
98 sp<BufferQueue> bq = new SurfaceTextureLayer();
99 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -0700100 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800101
Daniel Lamb2675792012-02-23 14:35:13 -0800102 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700103 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
104 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800105
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700106#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
107#warning "disabling triple buffering"
Jamie Gennis31a353d2012-08-24 17:25:13 -0700108 mSurfaceTexture->setDefaultMaxBufferCount(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700109#else
Jamie Gennis31a353d2012-08-24 17:25:13 -0700110 mSurfaceTexture->setDefaultMaxBufferCount(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800111#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700112}
113
Mathias Agopiana67932f2011-04-20 14:20:59 -0700114Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700115{
Mathias Agopian921e6ac2012-07-23 23:11:29 -0700116 mFlinger->deleteTextureAsync(mTextureName);
Mathias Agopian96f08192010-06-02 23:28:45 -0700117}
118
Mathias Agopiana67932f2011-04-20 14:20:59 -0700119void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700120 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800121 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700122}
123
Mathias Agopiand606de62010-05-10 20:06:11 -0700124// called with SurfaceFlinger::mStateLock as soon as the layer is entered
125// in the purgatory list
126void Layer::onRemoved()
127{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700128 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700129}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700130
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700131void Layer::setName(const String8& name) {
132 LayerBase::setName(name);
133 mSurfaceTexture->setName(name);
134}
135
Mathias Agopiana67932f2011-04-20 14:20:59 -0700136sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800137{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700138 class BSurface : public BnSurface, public LayerCleaner {
139 wp<const Layer> mOwner;
140 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
141 sp<ISurfaceTexture> res;
142 sp<const Layer> that( mOwner.promote() );
143 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800144 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700145 }
146 return res;
147 }
148 public:
149 BSurface(const sp<SurfaceFlinger>& flinger,
150 const sp<Layer>& layer)
151 : LayerCleaner(flinger, layer), mOwner(layer) { }
152 };
153 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800154 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800155}
156
Jamie Gennis582270d2011-08-17 18:19:00 -0700157wp<IBinder> Layer::getSurfaceTextureBinder() const
158{
Daniel Lamb2675792012-02-23 14:35:13 -0800159 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700160}
161
Mathias Agopianf9d93272009-06-19 17:00:27 -0700162status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800163 PixelFormat format, uint32_t flags)
164{
Mathias Agopian401c2572009-09-23 19:16:27 -0700165 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800166 PixelFormatInfo info;
167 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800168 if (err) {
169 ALOGE("unsupported pixelformat %d", format);
170 return err;
171 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800172
Mathias Agopianca99fb82010-04-14 16:43:44 -0700173 uint32_t const maxSurfaceDims = min(
Mathias Agopiana4912602012-07-12 14:25:33 -0700174 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700175
176 // never allow a surface larger than what our underlying GL implementation
177 // can handle.
178 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800179 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700180 return BAD_VALUE;
181 }
182
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700183 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700184
Mathias Agopian3165cc22012-08-08 19:42:09 -0700185 mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
186 mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
187 mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700188 mCurrentOpacity = getOpacityForFormat(format);
189
190 mSurfaceTexture->setDefaultBufferSize(w, h);
191 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800192 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700193
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800194 return NO_ERROR;
195}
196
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700197Rect Layer::computeBufferCrop() const {
198 // Start with the SurfaceTexture's buffer crop...
199 Rect crop;
200 if (!mCurrentCrop.isEmpty()) {
201 crop = mCurrentCrop;
202 } else if (mActiveBuffer != NULL){
203 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
204 } else {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700205 crop.makeInvalid();
206 return crop;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700207 }
208
209 // ... then reduce that in the same proportions as the window crop reduces
210 // the window size.
211 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700212 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700213 // Transform the window crop to match the buffer coordinate system,
214 // which means using the inverse of the current transform set on the
215 // SurfaceTexture.
216 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700217 int winWidth = s.active.w;
218 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700219 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
220 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
221 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700222 winWidth = s.active.h;
223 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700224 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700225 Rect winCrop = s.active.crop.transform(invTransform,
226 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700227
228 float xScale = float(crop.width()) / float(winWidth);
229 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700230 crop.left += int(ceilf(float(winCrop.left) * xScale));
231 crop.top += int(ceilf(float(winCrop.top) * yScale));
232 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
233 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700234 }
235
236 return crop;
237}
238
Mathias Agopian4fec8732012-06-29 14:12:52 -0700239void Layer::setGeometry(
Mathias Agopian42977342012-08-05 00:40:46 -0700240 const sp<const DisplayDevice>& hw,
Mathias Agopian4fec8732012-06-29 14:12:52 -0700241 HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700242{
Mathias Agopian4fec8732012-06-29 14:12:52 -0700243 LayerBaseClient::setGeometry(hw, layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700244
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700245 // enable this layer
246 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700247
248 // we can't do alpha-fade with the hwc HAL
249 const State& s(drawingState());
250 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700251 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700252 }
253
Mathias Agopian29a367b2011-07-12 14:51:45 -0700254 /*
255 * Transformations are applied in this order:
256 * 1) buffer orientation/flip/mirror
257 * 2) state transformation (window manager)
258 * 3) layer orientation (screen orientation)
259 * (NOTE: the matrices are multiplied in reverse order)
260 */
261
262 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopian42977342012-08-05 00:40:46 -0700263 const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700264
265 // this gives us only the "orientation" component of the transform
266 const uint32_t finalTransform = tr.getOrientation();
267
Mathias Agopiana350ff92010-08-10 17:14:02 -0700268 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700269 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700270 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700271 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700272 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700273 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700274 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700275}
276
Mathias Agopian42977342012-08-05 00:40:46 -0700277void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700278 HWComposer::HWCLayerInterface& layer) {
Mathias Agopian71e83e12012-09-04 20:25:39 -0700279 LayerBaseClient::setPerFrameData(hw, layer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700280 // NOTE: buffer can be NULL if the client never drew into this
281 // layer yet, or if we ran out of memory
Mathias Agopian71e83e12012-09-04 20:25:39 -0700282 layer.setBuffer(mActiveBuffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700283}
Jesse Halldc5b4852012-06-29 15:21:18 -0700284
Mathias Agopian42977342012-08-05 00:40:46 -0700285void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700286 HWComposer::HWCLayerInterface& layer) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700287 int fenceFd = -1;
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700288
289 // TODO: there is a possible optimization here: we only need to set the
290 // acquire fence the first time a new buffer is acquired on EACH display.
291
292 if (layer.getCompositionType() == HWC_OVERLAY) {
Jesse Halldc5b4852012-06-29 15:21:18 -0700293 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
294 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700295 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700296 if (fenceFd == -1) {
297 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
298 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700299 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700300 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700301 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700302}
303
Mathias Agopian42977342012-08-05 00:40:46 -0700304void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800305{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800306 ATRACE_CALL();
307
Mathias Agopiana67932f2011-04-20 14:20:59 -0700308 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800309 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700310 // in fact never been drawn into. This happens frequently with
311 // SurfaceView because the WindowManager can't know when the client
312 // has drawn the first time.
313
314 // If there is nothing under us, we paint the screen in black, otherwise
315 // we just skip this update.
316
317 // figure out if there is something below us
318 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700319 const SurfaceFlinger::LayerVector& drawingLayers(
320 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700321 const size_t count = drawingLayers.size();
322 for (size_t i=0 ; i<count ; ++i) {
323 const sp<LayerBase>& layer(drawingLayers[i]);
324 if (layer.get() == static_cast<LayerBase const*>(this))
325 break;
Mathias Agopian42977342012-08-05 00:40:46 -0700326 under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
Mathias Agopian179169e2010-05-06 20:21:45 -0700327 }
328 // if not everything below us is covered, we plug the holes!
329 Region holes(clip.subtract(under));
330 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700331 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700332 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333 return;
334 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700335
Jamie Gennis61e04b92012-09-09 17:48:42 -0700336 status_t err = mSurfaceTexture->doGLFenceWait();
337 if (err != OK) {
338 ALOGE("onDraw: failed waiting for fence: %d", err);
Jesse Halldc5b4852012-06-29 15:21:18 -0700339 // Go ahead and draw the buffer anyway; no matter what we do the screen
340 // is probably going to have something visibly wrong.
341 }
342
Jamie Gennis9575f602011-10-07 14:51:16 -0700343 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700344 // TODO: we could be more subtle with isFixedSize()
345 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
346
347 // Query the texture matrix given our current filtering mode.
348 float textureMatrix[16];
349 mSurfaceTexture->setFilteringEnabled(useFiltering);
350 mSurfaceTexture->getTransformMatrix(textureMatrix);
351
352 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700353 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
354 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700355 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700356 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700357 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700358 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
359 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700360 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700361 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700362 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700363 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700364 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700365 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700366 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700367 glMatrixMode(GL_TEXTURE);
368 glLoadIdentity();
369 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700370 glDisable(GL_TEXTURE_EXTERNAL_OES);
371 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700372 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700373
Mathias Agopian1b031492012-06-20 17:51:20 -0700374 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700375
Mathias Agopianc492e672011-10-18 14:49:27 -0700376 glDisable(GL_TEXTURE_EXTERNAL_OES);
377 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378}
379
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800380// As documented in libhardware header, formats in the range
381// 0x100 - 0x1FF are specific to the HAL implementation, and
382// are known to have no alpha channel
383// TODO: move definition for device-specific range into
384// hardware.h, instead of using hard-coded values here.
385#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
386
Mathias Agopiana67932f2011-04-20 14:20:59 -0700387bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800388{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700389 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
390 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800391 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700392 PixelFormatInfo info;
393 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
394 // in case of error (unknown format), we assume no blending
395 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800396}
397
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800398
Mathias Agopiana67932f2011-04-20 14:20:59 -0700399bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700400{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700401 // if we don't have a buffer yet, we're translucent regardless of the
402 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700403 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700404 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700405 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700406
407 // if the layer has the opaque flag, then we're always opaque,
408 // otherwise we use the current buffer's format.
409 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700410}
411
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800412bool Layer::isProtected() const
413{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700414 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800415 return (activeBuffer != 0) &&
416 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
417}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700418
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800419uint32_t Layer::doTransaction(uint32_t flags)
420{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800421 ATRACE_CALL();
422
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800423 const Layer::State& front(drawingState());
424 const Layer::State& temp(currentState());
425
Mathias Agopian4824d402012-06-04 18:16:30 -0700426 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
427 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700428
429 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700430 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000431 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700432 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
433 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
434 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
435 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
436 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
437 this, mCurrentScalingMode,
438 temp.active.w, temp.active.h,
439 temp.active.crop.left,
440 temp.active.crop.top,
441 temp.active.crop.right,
442 temp.active.crop.bottom,
443 temp.active.crop.getWidth(),
444 temp.active.crop.getHeight(),
445 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700446 temp.requested.crop.left,
447 temp.requested.crop.top,
448 temp.requested.crop.right,
449 temp.requested.crop.bottom,
450 temp.requested.crop.getWidth(),
451 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700452 front.active.w, front.active.h,
453 front.active.crop.left,
454 front.active.crop.top,
455 front.active.crop.right,
456 front.active.crop.bottom,
457 front.active.crop.getWidth(),
458 front.active.crop.getHeight(),
459 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700460 front.requested.crop.left,
461 front.requested.crop.top,
462 front.requested.crop.right,
463 front.requested.crop.bottom,
464 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700465 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800466
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700467 // record the new size, form this point on, when the client request
468 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700469 mSurfaceTexture->setDefaultBufferSize(
470 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800471 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700472
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700473 if (!isFixedSize()) {
474
475 const bool resizePending = (temp.requested.w != temp.active.w) ||
476 (temp.requested.h != temp.active.h);
477
478 if (resizePending) {
479 // don't let LayerBase::doTransaction update the drawing state
480 // if we have a pending resize, unless we are in fixed-size mode.
481 // the drawing state will be updated only once we receive a buffer
482 // with the correct size.
483 //
484 // in particular, we want to make sure the clip (which is part
485 // of the geometry state) is latched together with the size but is
486 // latched immediately when no resizing is involved.
487
488 flags |= eDontUpdateGeometryState;
489 }
490 }
491
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800492 return LayerBase::doTransaction(flags);
493}
494
Mathias Agopiana138f892010-05-21 17:24:35 -0700495bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700496 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700497}
498
499bool Layer::isCropped() const {
500 return !mCurrentCrop.isEmpty();
501}
502
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800503// ----------------------------------------------------------------------------
504// pageflip handling...
505// ----------------------------------------------------------------------------
506
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800507bool Layer::onPreComposition() {
508 mRefreshPending = false;
509 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800510}
511
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700512void Layer::onPostComposition() {
513 if (mFrameLatencyNeeded) {
514 const HWComposer& hwc = mFlinger->getHwComposer();
515 const size_t offset = mFrameLatencyOffset;
516 mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
517 mFrameStats[offset].set = systemTime();
Andy McFaddenb0d1dd32012-09-10 14:08:09 -0700518 mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700519 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
520 mFrameLatencyNeeded = false;
521 }
522}
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;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700653 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700654 // the first time we receive a buffer, we need to trigger a
655 // geometry invalidation.
656 mFlinger->invalidateHwcGeometry();
657 }
658
Mathias Agopian702634a2012-05-23 17:50:31 -0700659 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700660 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
661 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700662 if ((crop != mCurrentCrop) ||
663 (transform != mCurrentTransform) ||
664 (scalingMode != mCurrentScalingMode))
665 {
666 mCurrentCrop = crop;
667 mCurrentTransform = transform;
668 mCurrentScalingMode = scalingMode;
669 mFlinger->invalidateHwcGeometry();
670 }
671
672 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700673 uint32_t bufWidth = mActiveBuffer->getWidth();
674 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700675 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
676 bufHeight != uint32_t(oldActiveBuffer->height)) {
677 mFlinger->invalidateHwcGeometry();
678 }
679 }
680
681 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
682 if (oldOpacity != isOpaque()) {
683 recomputeVisibleRegions = true;
684 }
685
Mathias Agopian702634a2012-05-23 17:50:31 -0700686 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
687 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian4fec8732012-06-29 14:12:52 -0700688
689 // FIXME: postedRegion should be dirty & bounds
690 const Layer::State& front(drawingState());
691 Region dirtyRegion(Rect(front.active.w, front.active.h));
692
693 // transform the dirty region to window-manager space
694 outDirtyRegion = (front.transform.transform(dirtyRegion));
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700695 }
Mathias Agopian4fec8732012-06-29 14:12:52 -0700696 return outDirtyRegion;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800697}
698
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700699void Layer::dump(String8& result, char* buffer, size_t SIZE) const
700{
701 LayerBaseClient::dump(result, buffer, SIZE);
702
Mathias Agopiana67932f2011-04-20 14:20:59 -0700703 sp<const GraphicBuffer> buf0(mActiveBuffer);
704 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700705 if (buf0 != 0) {
706 w0 = buf0->getWidth();
707 h0 = buf0->getHeight();
708 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700709 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700710 }
711 snprintf(buffer, SIZE,
712 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700713 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800714 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700715 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800716 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700717
718 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700719
Mathias Agopiana67932f2011-04-20 14:20:59 -0700720 if (mSurfaceTexture != 0) {
721 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700722 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700723}
724
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800725void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
726{
727 LayerBaseClient::dumpStats(result, buffer, SIZE);
728 const size_t o = mFrameLatencyOffset;
Andy McFaddenb0d1dd32012-09-10 14:08:09 -0700729 const nsecs_t period =
730 mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800731 result.appendFormat("%lld\n", period);
732 for (size_t i=0 ; i<128 ; i++) {
733 const size_t index = (o+i) % 128;
734 const nsecs_t time_app = mFrameStats[index].timestamp;
735 const nsecs_t time_set = mFrameStats[index].set;
736 const nsecs_t time_vsync = mFrameStats[index].vsync;
737 result.appendFormat("%lld\t%lld\t%lld\n",
738 time_app,
739 time_vsync,
740 time_set);
741 }
742 result.append("\n");
743}
744
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800745void Layer::clearStats()
746{
747 LayerBaseClient::clearStats();
748 memset(mFrameStats, 0, sizeof(mFrameStats));
749}
750
Mathias Agopiana67932f2011-04-20 14:20:59 -0700751uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700752{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700753 // TODO: should we do something special if mSecure is set?
754 if (mProtectedByApp) {
755 // need a hardware-protected path to external video sink
756 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700757 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700758 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700759 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700760}
761
Mathias Agopiana4583642011-08-23 18:03:18 -0700762uint32_t Layer::getTransformHint() const {
763 uint32_t orientation = 0;
764 if (!mFlinger->mDebugDisableTransformHint) {
Mathias Agopian4fec8732012-06-29 14:12:52 -0700765 // The transform hint is used to improve performance on the main
766 // display -- we can only have a single transform hint, it cannot
767 // apply to all displays.
768 // This is why we use the default display here. This is not an
769 // oversight.
Mathias Agopian42977342012-08-05 00:40:46 -0700770 sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
771 const Transform& planeTransform(hw->getTransform());
Mathias Agopian4fec8732012-06-29 14:12:52 -0700772 orientation = planeTransform.getOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700773 if (orientation & Transform::ROT_INVALID) {
774 orientation = 0;
775 }
776 }
777 return orientation;
778}
779
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800780// ---------------------------------------------------------------------------
781
782
783}; // namespace android