blob: 0d1cb45bb3fb4cdb21e6ee97dc35d997dd9bfced [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 Agopian1b031492012-06-20 17:51:20 -0700148void Layer::validateVisibility(const Transform& globalTransform, const DisplayHardware& hw) {
149 LayerBase::validateVisibility(globalTransform, hw);
Daniel Lamb2675792012-02-23 14:35:13 -0800150
151 // This optimization allows the SurfaceTexture to bake in
152 // the rotation so hardware overlays can be used
153 mSurfaceTexture->setTransformHint(getTransformHint());
154}
155
Mathias Agopiana67932f2011-04-20 14:20:59 -0700156sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800157{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700158 class BSurface : public BnSurface, public LayerCleaner {
159 wp<const Layer> mOwner;
160 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
161 sp<ISurfaceTexture> res;
162 sp<const Layer> that( mOwner.promote() );
163 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800164 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700165 }
166 return res;
167 }
168 public:
169 BSurface(const sp<SurfaceFlinger>& flinger,
170 const sp<Layer>& layer)
171 : LayerCleaner(flinger, layer), mOwner(layer) { }
172 };
173 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800174 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800175}
176
Jamie Gennis582270d2011-08-17 18:19:00 -0700177wp<IBinder> Layer::getSurfaceTextureBinder() const
178{
Daniel Lamb2675792012-02-23 14:35:13 -0800179 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700180}
181
Mathias Agopianf9d93272009-06-19 17:00:27 -0700182status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183 PixelFormat format, uint32_t flags)
184{
Mathias Agopian401c2572009-09-23 19:16:27 -0700185 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186 PixelFormatInfo info;
187 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800188 if (err) {
189 ALOGE("unsupported pixelformat %d", format);
190 return err;
191 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800192
Mathias Agopian401c2572009-09-23 19:16:27 -0700193 // the display's pixel format
Mathias Agopian1b031492012-06-20 17:51:20 -0700194 // XXX: we shouldn't rely on the DisplayHardware to do this
195 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700196 uint32_t const maxSurfaceDims = min(
197 hw.getMaxTextureSize(), hw.getMaxViewportDims());
198
199 // never allow a surface larger than what our underlying GL implementation
200 // can handle.
201 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800202 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700203 return BAD_VALUE;
204 }
205
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700206 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700207
Mathias Agopian3330b202009-10-05 17:07:12 -0700208 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800209 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700210 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
211 mCurrentOpacity = getOpacityForFormat(format);
212
213 mSurfaceTexture->setDefaultBufferSize(w, h);
214 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800215 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700216
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800217 return NO_ERROR;
218}
219
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700220Rect Layer::computeBufferCrop() const {
221 // Start with the SurfaceTexture's buffer crop...
222 Rect crop;
223 if (!mCurrentCrop.isEmpty()) {
224 crop = mCurrentCrop;
225 } else if (mActiveBuffer != NULL){
226 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
227 } else {
228 crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
229 }
230
231 // ... then reduce that in the same proportions as the window crop reduces
232 // the window size.
233 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700234 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700235 // Transform the window crop to match the buffer coordinate system,
236 // which means using the inverse of the current transform set on the
237 // SurfaceTexture.
238 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700239 int winWidth = s.active.w;
240 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700241 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
242 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
243 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700244 winWidth = s.active.h;
245 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700246 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700247 Rect winCrop = s.active.crop.transform(invTransform,
248 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700249
250 float xScale = float(crop.width()) / float(winWidth);
251 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700252 crop.left += int(ceilf(float(winCrop.left) * xScale));
253 crop.top += int(ceilf(float(winCrop.top) * yScale));
254 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
255 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700256 }
257
258 return crop;
259}
260
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700261void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700262{
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700263 LayerBaseClient::setGeometry(layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700264
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700265 // enable this layer
266 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700267
268 // we can't do alpha-fade with the hwc HAL
269 const State& s(drawingState());
270 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700271 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700272 }
273
Mathias Agopian29a367b2011-07-12 14:51:45 -0700274 /*
275 * Transformations are applied in this order:
276 * 1) buffer orientation/flip/mirror
277 * 2) state transformation (window manager)
278 * 3) layer orientation (screen orientation)
Mathias Agopiand992db32011-08-18 18:31:00 -0700279 * mTransform is already the composition of (2) and (3)
Mathias Agopian29a367b2011-07-12 14:51:45 -0700280 * (NOTE: the matrices are multiplied in reverse order)
281 */
282
283 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopiand992db32011-08-18 18:31:00 -0700284 const Transform tr(mTransform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700285
286 // this gives us only the "orientation" component of the transform
287 const uint32_t finalTransform = tr.getOrientation();
288
Mathias Agopiana350ff92010-08-10 17:14:02 -0700289 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700290 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700291 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700292 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700293 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700294 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700295 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700296}
297
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700298void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700299 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700300 // NOTE: buffer can be NULL if the client never drew into this
301 // layer yet, or if we ran out of memory
302 layer.setBuffer(buffer);
Jesse Hallc5c5a142012-07-02 16:49:28 -0700303}
Jesse Halldc5b4852012-06-29 15:21:18 -0700304
Jesse Hallc5c5a142012-07-02 16:49:28 -0700305void Layer::setAcquireFence(HWComposer::HWCLayerInterface& layer) {
306 int fenceFd = -1;
Jesse Halldc5b4852012-06-29 15:21:18 -0700307 if (mNeedHwcFence) {
308 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
309 if (fence.get()) {
Jesse Hallc5c5a142012-07-02 16:49:28 -0700310 fenceFd = fence->dup();
Jesse Halldc5b4852012-06-29 15:21:18 -0700311 if (fenceFd == -1) {
312 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
313 }
Jesse Halldc5b4852012-06-29 15:21:18 -0700314 }
315 mNeedHwcFence = false;
Jesse Halldc5b4852012-06-29 15:21:18 -0700316 }
Jesse Hallc5c5a142012-07-02 16:49:28 -0700317 layer.setAcquireFenceFd(fenceFd);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700318}
319
Mathias Agopian1b031492012-06-20 17:51:20 -0700320void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800321{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800322 ATRACE_CALL();
323
Mathias Agopiana67932f2011-04-20 14:20:59 -0700324 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800325 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700326 // in fact never been drawn into. This happens frequently with
327 // SurfaceView because the WindowManager can't know when the client
328 // has drawn the first time.
329
330 // If there is nothing under us, we paint the screen in black, otherwise
331 // we just skip this update.
332
333 // figure out if there is something below us
334 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700335 const SurfaceFlinger::LayerVector& drawingLayers(
336 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700337 const size_t count = drawingLayers.size();
338 for (size_t i=0 ; i<count ; ++i) {
339 const sp<LayerBase>& layer(drawingLayers[i]);
340 if (layer.get() == static_cast<LayerBase const*>(this))
341 break;
342 under.orSelf(layer->visibleRegionScreen);
343 }
344 // if not everything below us is covered, we plug the holes!
345 Region holes(clip.subtract(under));
346 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700347 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700348 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800349 return;
350 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700351
Jesse Halldc5b4852012-06-29 15:21:18 -0700352 // TODO: replace this with a server-side wait
353 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
354 if (fence.get()) {
355 status_t err = fence->wait(Fence::TIMEOUT_NEVER);
356 ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
357 // Go ahead and draw the buffer anyway; no matter what we do the screen
358 // is probably going to have something visibly wrong.
359 }
360
Jamie Gennis9575f602011-10-07 14:51:16 -0700361 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700362 // TODO: we could be more subtle with isFixedSize()
363 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
364
365 // Query the texture matrix given our current filtering mode.
366 float textureMatrix[16];
367 mSurfaceTexture->setFilteringEnabled(useFiltering);
368 mSurfaceTexture->getTransformMatrix(textureMatrix);
369
370 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700371 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
372 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700373 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700374 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700375 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700376 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
377 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700378 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700379 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700380 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700381 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700382 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700383 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700384 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700385 glMatrixMode(GL_TEXTURE);
386 glLoadIdentity();
387 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700388 glDisable(GL_TEXTURE_EXTERNAL_OES);
389 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700390 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700391
Mathias Agopian1b031492012-06-20 17:51:20 -0700392 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700393
Mathias Agopianc492e672011-10-18 14:49:27 -0700394 glDisable(GL_TEXTURE_EXTERNAL_OES);
395 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800396}
397
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800398// As documented in libhardware header, formats in the range
399// 0x100 - 0x1FF are specific to the HAL implementation, and
400// are known to have no alpha channel
401// TODO: move definition for device-specific range into
402// hardware.h, instead of using hard-coded values here.
403#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
404
Mathias Agopiana67932f2011-04-20 14:20:59 -0700405bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800406{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700407 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
408 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800409 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700410 PixelFormatInfo info;
411 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
412 // in case of error (unknown format), we assume no blending
413 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800414}
415
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800416
Mathias Agopiana67932f2011-04-20 14:20:59 -0700417bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700418{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700419 // if we don't have a buffer yet, we're translucent regardless of the
420 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700421 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700422 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700423 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700424
425 // if the layer has the opaque flag, then we're always opaque,
426 // otherwise we use the current buffer's format.
427 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700428}
429
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800430bool Layer::isProtected() const
431{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700432 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800433 return (activeBuffer != 0) &&
434 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
435}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700436
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437uint32_t Layer::doTransaction(uint32_t flags)
438{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800439 ATRACE_CALL();
440
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800441 const Layer::State& front(drawingState());
442 const Layer::State& temp(currentState());
443
Mathias Agopian4824d402012-06-04 18:16:30 -0700444 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
445 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700446
447 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700448 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000449 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700450 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
451 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
452 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
453 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
454 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
455 this, mCurrentScalingMode,
456 temp.active.w, temp.active.h,
457 temp.active.crop.left,
458 temp.active.crop.top,
459 temp.active.crop.right,
460 temp.active.crop.bottom,
461 temp.active.crop.getWidth(),
462 temp.active.crop.getHeight(),
463 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700464 temp.requested.crop.left,
465 temp.requested.crop.top,
466 temp.requested.crop.right,
467 temp.requested.crop.bottom,
468 temp.requested.crop.getWidth(),
469 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700470 front.active.w, front.active.h,
471 front.active.crop.left,
472 front.active.crop.top,
473 front.active.crop.right,
474 front.active.crop.bottom,
475 front.active.crop.getWidth(),
476 front.active.crop.getHeight(),
477 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700478 front.requested.crop.left,
479 front.requested.crop.top,
480 front.requested.crop.right,
481 front.requested.crop.bottom,
482 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700483 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800484
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700485 // record the new size, form this point on, when the client request
486 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700487 mSurfaceTexture->setDefaultBufferSize(
488 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800489 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700490
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700491 if (!isFixedSize()) {
492
493 const bool resizePending = (temp.requested.w != temp.active.w) ||
494 (temp.requested.h != temp.active.h);
495
496 if (resizePending) {
497 // don't let LayerBase::doTransaction update the drawing state
498 // if we have a pending resize, unless we are in fixed-size mode.
499 // the drawing state will be updated only once we receive a buffer
500 // with the correct size.
501 //
502 // in particular, we want to make sure the clip (which is part
503 // of the geometry state) is latched together with the size but is
504 // latched immediately when no resizing is involved.
505
506 flags |= eDontUpdateGeometryState;
507 }
508 }
509
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800510 return LayerBase::doTransaction(flags);
511}
512
Mathias Agopiana138f892010-05-21 17:24:35 -0700513bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700514 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700515}
516
517bool Layer::isCropped() const {
518 return !mCurrentCrop.isEmpty();
519}
520
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800521// ----------------------------------------------------------------------------
522// pageflip handling...
523// ----------------------------------------------------------------------------
524
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800525bool Layer::onPreComposition() {
526 mRefreshPending = false;
527 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800528}
529
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800530void Layer::lockPageFlip(bool& recomputeVisibleRegions)
531{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800532 ATRACE_CALL();
533
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700534 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800535
536 // if we've already called updateTexImage() without going through
537 // a composition step, we have to skip this layer at this point
538 // because we cannot call updateTeximage() without a corresponding
539 // compositionComplete() call.
540 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800541 if (mRefreshPending) {
542 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800543 return;
544 }
545
Jamie Gennis351a5132011-09-14 18:23:37 -0700546 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700547 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700548 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700549
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700550 // signal another event if we have more frames pending
551 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800552 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700553 }
554
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700555 struct Reject : public SurfaceTexture::BufferRejecter {
556 Layer::State& front;
557 Layer::State& current;
558 bool& recomputeVisibleRegions;
559 Reject(Layer::State& front, Layer::State& current,
560 bool& recomputeVisibleRegions)
561 : front(front), current(current),
562 recomputeVisibleRegions(recomputeVisibleRegions) {
563 }
564
565 virtual bool reject(const sp<GraphicBuffer>& buf,
566 const BufferQueue::BufferItem& item) {
567 if (buf == NULL) {
568 return false;
569 }
570
571 uint32_t bufWidth = buf->getWidth();
572 uint32_t bufHeight = buf->getHeight();
573
574 // check that we received a buffer of the right size
575 // (Take the buffer's orientation into account)
576 if (item.mTransform & Transform::ROT_90) {
577 swap(bufWidth, bufHeight);
578 }
579
580
581 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
582 if (front.active != front.requested) {
583
584 if (isFixedSize ||
585 (bufWidth == front.requested.w &&
586 bufHeight == front.requested.h))
587 {
588 // Here we pretend the transaction happened by updating the
589 // current and drawing states. Drawing state is only accessed
590 // in this thread, no need to have it locked
591 front.active = front.requested;
592
593 // We also need to update the current state so that
594 // we don't end-up overwriting the drawing state with
595 // this stale current state during the next transaction
596 //
597 // NOTE: We don't need to hold the transaction lock here
598 // because State::active is only accessed from this thread.
599 current.active = front.active;
600
601 // recompute visible region
602 recomputeVisibleRegions = true;
603 }
604
605 ALOGD_IF(DEBUG_RESIZE,
606 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
607 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
608 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
609 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
610 front.active.w, front.active.h,
611 front.active.crop.left,
612 front.active.crop.top,
613 front.active.crop.right,
614 front.active.crop.bottom,
615 front.active.crop.getWidth(),
616 front.active.crop.getHeight(),
617 front.requested.w, front.requested.h,
618 front.requested.crop.left,
619 front.requested.crop.top,
620 front.requested.crop.right,
621 front.requested.crop.bottom,
622 front.requested.crop.getWidth(),
623 front.requested.crop.getHeight());
624 }
625
626 if (!isFixedSize) {
627 if (front.active.w != bufWidth ||
628 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700629 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700630 return true;
631 }
632 }
633 return false;
634 }
635 };
636
637
638 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
639
640 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700641 // something happened!
642 recomputeVisibleRegions = true;
643 return;
644 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700645
Jamie Gennis351a5132011-09-14 18:23:37 -0700646 // update the active buffer
647 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700648 if (mActiveBuffer == NULL) {
649 // this can only happen if the very first buffer was rejected.
650 return;
651 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800652
Mathias Agopian4824d402012-06-04 18:16:30 -0700653 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700654 mFrameLatencyNeeded = true;
Jesse Halldc5b4852012-06-29 15:21:18 -0700655 mNeedHwcFence = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700656 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700657 // the first time we receive a buffer, we need to trigger a
658 // geometry invalidation.
659 mFlinger->invalidateHwcGeometry();
660 }
661
Mathias Agopian702634a2012-05-23 17:50:31 -0700662 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700663 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
664 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700665 if ((crop != mCurrentCrop) ||
666 (transform != mCurrentTransform) ||
667 (scalingMode != mCurrentScalingMode))
668 {
669 mCurrentCrop = crop;
670 mCurrentTransform = transform;
671 mCurrentScalingMode = scalingMode;
672 mFlinger->invalidateHwcGeometry();
673 }
674
675 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700676 uint32_t bufWidth = mActiveBuffer->getWidth();
677 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700678 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
679 bufHeight != uint32_t(oldActiveBuffer->height)) {
680 mFlinger->invalidateHwcGeometry();
681 }
682 }
683
684 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
685 if (oldOpacity != isOpaque()) {
686 recomputeVisibleRegions = true;
687 }
688
689 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700690 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700691 mPostedDirtyRegion.set(front.active.w, front.active.h);
692
693 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
694 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700695 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800696}
697
698void Layer::unlockPageFlip(
699 const Transform& planeTransform, Region& outDirtyRegion)
700{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800701 ATRACE_CALL();
702
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800703 Region postedRegion(mPostedDirtyRegion);
704 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800705 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800706 if (!visibleRegionScreen.isEmpty()) {
707 // The dirty region is given in the layer's coordinate space
708 // transform the dirty region by the surface's transformation
709 // and the global transformation.
710 const Layer::State& s(drawingState());
711 const Transform tr(planeTransform * s.transform);
712 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800713
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800714 // At this point, the dirty region is in screen space.
715 // Make sure it's constrained by the visible region (which
716 // is in screen space as well).
717 postedRegion.andSelf(visibleRegionScreen);
718 outDirtyRegion.orSelf(postedRegion);
719 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720 }
721}
722
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700723void Layer::dump(String8& result, char* buffer, size_t SIZE) const
724{
725 LayerBaseClient::dump(result, buffer, SIZE);
726
Mathias Agopiana67932f2011-04-20 14:20:59 -0700727 sp<const GraphicBuffer> buf0(mActiveBuffer);
728 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700729 if (buf0 != 0) {
730 w0 = buf0->getWidth();
731 h0 = buf0->getHeight();
732 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700733 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700734 }
735 snprintf(buffer, SIZE,
736 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700737 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800738 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700739 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800740 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700741
742 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700743
Mathias Agopiana67932f2011-04-20 14:20:59 -0700744 if (mSurfaceTexture != 0) {
745 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700746 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700747}
748
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800749void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
750{
751 LayerBaseClient::dumpStats(result, buffer, SIZE);
752 const size_t o = mFrameLatencyOffset;
Mathias Agopian1b031492012-06-20 17:51:20 -0700753 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800754 const nsecs_t period = hw.getRefreshPeriod();
755 result.appendFormat("%lld\n", period);
756 for (size_t i=0 ; i<128 ; i++) {
757 const size_t index = (o+i) % 128;
758 const nsecs_t time_app = mFrameStats[index].timestamp;
759 const nsecs_t time_set = mFrameStats[index].set;
760 const nsecs_t time_vsync = mFrameStats[index].vsync;
761 result.appendFormat("%lld\t%lld\t%lld\n",
762 time_app,
763 time_vsync,
764 time_set);
765 }
766 result.append("\n");
767}
768
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800769void Layer::clearStats()
770{
771 LayerBaseClient::clearStats();
772 memset(mFrameStats, 0, sizeof(mFrameStats));
773}
774
Mathias Agopiana67932f2011-04-20 14:20:59 -0700775uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700776{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700777 // TODO: should we do something special if mSecure is set?
778 if (mProtectedByApp) {
779 // need a hardware-protected path to external video sink
780 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700781 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700782 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700783 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700784}
785
Mathias Agopiana4583642011-08-23 18:03:18 -0700786uint32_t Layer::getTransformHint() const {
787 uint32_t orientation = 0;
788 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700789 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700790 if (orientation & Transform::ROT_INVALID) {
791 orientation = 0;
792 }
793 }
794 return orientation;
795}
796
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800797// ---------------------------------------------------------------------------
798
799
800}; // namespace android