blob: 40623404d421c8421159c8cdc9e016d97004cc1d [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 Agopiana67932f2011-04-20 14:20:59 -070039#include "DisplayHardware/DisplayHardware.h"
40#include "DisplayHardware/HWComposer.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070041#include "GLExtensions.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080043#include "SurfaceFlinger.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070044#include "SurfaceTextureLayer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080045
46#define DEBUG_RESIZE 0
47
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048namespace android {
49
50// ---------------------------------------------------------------------------
51
Mathias Agopian96f08192010-06-02 23:28:45 -070052Layer::Layer(SurfaceFlinger* flinger,
53 DisplayID display, const sp<Client>& client)
54 : LayerBaseClient(flinger, display, 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 Agopiand606de62010-05-10 20:06:11 -070066 mNeedsDithering(false),
Mathias Agopianb7e930d2010-06-01 15:12:58 -070067 mSecure(false),
Mathias Agopian933389f2011-07-18 16:15:08 -070068 mProtectedByApp(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080069{
Mathias Agopiana67932f2011-04-20 14:20:59 -070070 mCurrentCrop.makeInvalid();
71 glGenTextures(1, &mTextureName);
Jamie Gennise8696a42012-01-15 18:54:57 -080072}
73
74void Layer::onLayerDisplayed() {
75 if (mFrameLatencyNeeded) {
Mathias Agopian82d7ab62012-01-19 18:34:40 -080076 const DisplayHardware& hw(graphicPlane(0).displayHardware());
77 mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
78 mFrameStats[mFrameLatencyOffset].set = systemTime();
79 mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
Jamie Gennise8696a42012-01-15 18:54:57 -080080 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
81 mFrameLatencyNeeded = false;
82 }
Mathias Agopiand606de62010-05-10 20:06:11 -070083}
84
Mathias Agopiana67932f2011-04-20 14:20:59 -070085void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070086{
Mathias Agopiana67932f2011-04-20 14:20:59 -070087 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070088
Mathias Agopiana67932f2011-04-20 14:20:59 -070089 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
90 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
91 private:
92 wp<Layer> mLayer;
93 virtual void onFrameAvailable() {
94 sp<Layer> that(mLayer.promote());
95 if (that != 0) {
96 that->onFrameQueued();
97 }
98 }
99 };
Daniel Lamb2675792012-02-23 14:35:13 -0800100
101 // Creates a custom BufferQueue for SurfaceTexture to use
102 sp<BufferQueue> bq = new SurfaceTextureLayer();
103 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -0700104 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800105
Daniel Lamb2675792012-02-23 14:35:13 -0800106 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700107 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
108 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800109
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700110#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
111#warning "disabling triple buffering"
Mathias Agopiana67932f2011-04-20 14:20:59 -0700112 mSurfaceTexture->setBufferCountServer(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700113#else
114 mSurfaceTexture->setBufferCountServer(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800115#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700116}
117
Mathias Agopiana67932f2011-04-20 14:20:59 -0700118Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700119{
Mathias Agopian118d0242011-10-13 16:02:48 -0700120 mFlinger->postMessageAsync(
121 new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
Mathias Agopian96f08192010-06-02 23:28:45 -0700122}
123
Mathias Agopiana67932f2011-04-20 14:20:59 -0700124void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700125 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800126 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700127}
128
Mathias Agopiand606de62010-05-10 20:06:11 -0700129// called with SurfaceFlinger::mStateLock as soon as the layer is entered
130// in the purgatory list
131void Layer::onRemoved()
132{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700133 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700134}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700135
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700136void Layer::setName(const String8& name) {
137 LayerBase::setName(name);
138 mSurfaceTexture->setName(name);
139}
140
Daniel Lamb2675792012-02-23 14:35:13 -0800141void Layer::validateVisibility(const Transform& globalTransform) {
142 LayerBase::validateVisibility(globalTransform);
143
144 // This optimization allows the SurfaceTexture to bake in
145 // the rotation so hardware overlays can be used
146 mSurfaceTexture->setTransformHint(getTransformHint());
147}
148
Mathias Agopiana67932f2011-04-20 14:20:59 -0700149sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800150{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700151 class BSurface : public BnSurface, public LayerCleaner {
152 wp<const Layer> mOwner;
153 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
154 sp<ISurfaceTexture> res;
155 sp<const Layer> that( mOwner.promote() );
156 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800157 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700158 }
159 return res;
160 }
161 public:
162 BSurface(const sp<SurfaceFlinger>& flinger,
163 const sp<Layer>& layer)
164 : LayerCleaner(flinger, layer), mOwner(layer) { }
165 };
166 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800167 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800168}
169
Jamie Gennis582270d2011-08-17 18:19:00 -0700170wp<IBinder> Layer::getSurfaceTextureBinder() const
171{
Daniel Lamb2675792012-02-23 14:35:13 -0800172 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700173}
174
Mathias Agopianf9d93272009-06-19 17:00:27 -0700175status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176 PixelFormat format, uint32_t flags)
177{
Mathias Agopian401c2572009-09-23 19:16:27 -0700178 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179 PixelFormatInfo info;
180 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800181 if (err) {
182 ALOGE("unsupported pixelformat %d", format);
183 return err;
184 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800185
Mathias Agopian401c2572009-09-23 19:16:27 -0700186 // the display's pixel format
187 const DisplayHardware& hw(graphicPlane(0).displayHardware());
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 Agopian401c2572009-09-23 19:16:27 -0700198 PixelFormatInfo displayInfo;
199 getPixelFormatInfo(hw.getFormat(), &displayInfo);
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700200 const uint32_t hwFlags = hw.getFlags();
201
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700202 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700203
Mathias Agopian3330b202009-10-05 17:07:12 -0700204 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800205 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700206 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
207 mCurrentOpacity = getOpacityForFormat(format);
208
209 mSurfaceTexture->setDefaultBufferSize(w, h);
210 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800211 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700212
Mathias Agopian401c2572009-09-23 19:16:27 -0700213 // we use the red index
214 int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
215 int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
216 mNeedsDithering = layerRedsize > displayRedSize;
217
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800218 return NO_ERROR;
219}
220
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700221Rect Layer::computeBufferCrop() const {
222 // Start with the SurfaceTexture's buffer crop...
223 Rect crop;
224 if (!mCurrentCrop.isEmpty()) {
225 crop = mCurrentCrop;
226 } else if (mActiveBuffer != NULL){
227 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
228 } else {
229 crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
230 }
231
232 // ... then reduce that in the same proportions as the window crop reduces
233 // the window size.
234 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700235 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700236 // Transform the window crop to match the buffer coordinate system,
237 // which means using the inverse of the current transform set on the
238 // SurfaceTexture.
239 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700240 int winWidth = s.active.w;
241 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700242 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
243 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
244 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700245 winWidth = s.active.h;
246 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700247 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700248 Rect winCrop = s.active.crop.transform(invTransform,
249 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700250
251 float xScale = float(crop.width()) / float(winWidth);
252 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700253 crop.left += int(ceilf(float(winCrop.left) * xScale));
254 crop.top += int(ceilf(float(winCrop.top) * yScale));
255 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
256 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700257 }
258
259 return crop;
260}
261
Mathias Agopiana350ff92010-08-10 17:14:02 -0700262void Layer::setGeometry(hwc_layer_t* hwcl)
263{
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700264 LayerBaseClient::setGeometry(hwcl);
265
266 hwcl->flags &= ~HWC_SKIP_LAYER;
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) {
271 hwcl->flags = HWC_SKIP_LAYER;
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 Agopiana350ff92010-08-10 17:14:02 -0700291 hwcl->flags = HWC_SKIP_LAYER;
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700292 } else {
293 hwcl->transform = finalTransform;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700294 }
Mathias Agopianc7f33812011-08-30 15:02:41 -0700295
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700296 Rect crop = computeBufferCrop();
297 hwcl->sourceCrop.left = crop.left;
298 hwcl->sourceCrop.top = crop.top;
299 hwcl->sourceCrop.right = crop.right;
300 hwcl->sourceCrop.bottom = crop.bottom;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700301}
302
303void Layer::setPerFrameData(hwc_layer_t* hwcl) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700304 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700305 if (buffer == NULL) {
Mathias Agopianda9584d2010-12-13 18:51:59 -0800306 // this can happen if the client never drew into this layer yet,
307 // or if we ran out of memory. In that case, don't let
308 // HWC handle it.
309 hwcl->flags |= HWC_SKIP_LAYER;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700310 hwcl->handle = NULL;
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700311 } else {
312 hwcl->handle = buffer->handle;
Mathias Agopiana350ff92010-08-10 17:14:02 -0700313 }
Mathias Agopiana350ff92010-08-10 17:14:02 -0700314}
315
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800316void Layer::onDraw(const Region& clip) const
317{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800318 ATRACE_CALL();
319
Mathias Agopiana67932f2011-04-20 14:20:59 -0700320 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800321 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700322 // in fact never been drawn into. This happens frequently with
323 // SurfaceView because the WindowManager can't know when the client
324 // has drawn the first time.
325
326 // If there is nothing under us, we paint the screen in black, otherwise
327 // we just skip this update.
328
329 // figure out if there is something below us
330 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700331 const SurfaceFlinger::LayerVector& drawingLayers(
332 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700333 const size_t count = drawingLayers.size();
334 for (size_t i=0 ; i<count ; ++i) {
335 const sp<LayerBase>& layer(drawingLayers[i]);
336 if (layer.get() == static_cast<LayerBase const*>(this))
337 break;
338 under.orSelf(layer->visibleRegionScreen);
339 }
340 // if not everything below us is covered, we plug the holes!
341 Region holes(clip.subtract(under));
342 if (!holes.isEmpty()) {
Mathias Agopian0a917752010-06-14 21:20:00 -0700343 clearWithOpenGL(holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700344 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800345 return;
346 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700347
Jamie Gennis9575f602011-10-07 14:51:16 -0700348 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700349 // TODO: we could be more subtle with isFixedSize()
350 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
351
352 // Query the texture matrix given our current filtering mode.
353 float textureMatrix[16];
354 mSurfaceTexture->setFilteringEnabled(useFiltering);
355 mSurfaceTexture->getTransformMatrix(textureMatrix);
356
357 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700358 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
359 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700360 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700361 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700362 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700363 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
364 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700365 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700366 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700367 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700368 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700369 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700370 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700371 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700372 glMatrixMode(GL_TEXTURE);
373 glLoadIdentity();
374 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700375 glDisable(GL_TEXTURE_EXTERNAL_OES);
376 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700377 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700378
379 drawWithOpenGL(clip);
380
Mathias Agopianc492e672011-10-18 14:49:27 -0700381 glDisable(GL_TEXTURE_EXTERNAL_OES);
382 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800383}
384
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800385// As documented in libhardware header, formats in the range
386// 0x100 - 0x1FF are specific to the HAL implementation, and
387// are known to have no alpha channel
388// TODO: move definition for device-specific range into
389// hardware.h, instead of using hard-coded values here.
390#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
391
Mathias Agopiana67932f2011-04-20 14:20:59 -0700392bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800393{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700394 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
395 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800396 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700397 PixelFormatInfo info;
398 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
399 // in case of error (unknown format), we assume no blending
400 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800401}
402
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800403
Mathias Agopiana67932f2011-04-20 14:20:59 -0700404bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700405{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700406 // if we don't have a buffer yet, we're translucent regardless of the
407 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700408 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700409 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700410 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700411
412 // if the layer has the opaque flag, then we're always opaque,
413 // otherwise we use the current buffer's format.
414 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700415}
416
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800417bool Layer::isProtected() const
418{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700419 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800420 return (activeBuffer != 0) &&
421 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
422}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700423
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800424uint32_t Layer::doTransaction(uint32_t flags)
425{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800426 ATRACE_CALL();
427
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800428 const Layer::State& front(drawingState());
429 const Layer::State& temp(currentState());
430
Mathias Agopian4824d402012-06-04 18:16:30 -0700431 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
432 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700433
434 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700435 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000436 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700437 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
438 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
439 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
440 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
441 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
442 this, mCurrentScalingMode,
443 temp.active.w, temp.active.h,
444 temp.active.crop.left,
445 temp.active.crop.top,
446 temp.active.crop.right,
447 temp.active.crop.bottom,
448 temp.active.crop.getWidth(),
449 temp.active.crop.getHeight(),
450 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700451 temp.requested.crop.left,
452 temp.requested.crop.top,
453 temp.requested.crop.right,
454 temp.requested.crop.bottom,
455 temp.requested.crop.getWidth(),
456 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700457 front.active.w, front.active.h,
458 front.active.crop.left,
459 front.active.crop.top,
460 front.active.crop.right,
461 front.active.crop.bottom,
462 front.active.crop.getWidth(),
463 front.active.crop.getHeight(),
464 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700465 front.requested.crop.left,
466 front.requested.crop.top,
467 front.requested.crop.right,
468 front.requested.crop.bottom,
469 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700470 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800471
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700472 // record the new size, form this point on, when the client request
473 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700474 mSurfaceTexture->setDefaultBufferSize(
475 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800476 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700477
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700478 if (!isFixedSize()) {
479
480 const bool resizePending = (temp.requested.w != temp.active.w) ||
481 (temp.requested.h != temp.active.h);
482
483 if (resizePending) {
484 // don't let LayerBase::doTransaction update the drawing state
485 // if we have a pending resize, unless we are in fixed-size mode.
486 // the drawing state will be updated only once we receive a buffer
487 // with the correct size.
488 //
489 // in particular, we want to make sure the clip (which is part
490 // of the geometry state) is latched together with the size but is
491 // latched immediately when no resizing is involved.
492
493 flags |= eDontUpdateGeometryState;
494 }
495 }
496
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 return LayerBase::doTransaction(flags);
498}
499
Mathias Agopiana138f892010-05-21 17:24:35 -0700500bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700501 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700502}
503
504bool Layer::isCropped() const {
505 return !mCurrentCrop.isEmpty();
506}
507
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800508// ----------------------------------------------------------------------------
509// pageflip handling...
510// ----------------------------------------------------------------------------
511
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800512bool Layer::onPreComposition() {
513 mRefreshPending = false;
514 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800515}
516
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800517void Layer::lockPageFlip(bool& recomputeVisibleRegions)
518{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800519 ATRACE_CALL();
520
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700521 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800522
523 // if we've already called updateTexImage() without going through
524 // a composition step, we have to skip this layer at this point
525 // because we cannot call updateTeximage() without a corresponding
526 // compositionComplete() call.
527 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800528 if (mRefreshPending) {
529 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800530 return;
531 }
532
Jamie Gennis351a5132011-09-14 18:23:37 -0700533 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700534 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700535 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700536
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700537 // signal another event if we have more frames pending
538 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800539 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700540 }
541
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700542 struct Reject : public SurfaceTexture::BufferRejecter {
543 Layer::State& front;
544 Layer::State& current;
545 bool& recomputeVisibleRegions;
546 Reject(Layer::State& front, Layer::State& current,
547 bool& recomputeVisibleRegions)
548 : front(front), current(current),
549 recomputeVisibleRegions(recomputeVisibleRegions) {
550 }
551
552 virtual bool reject(const sp<GraphicBuffer>& buf,
553 const BufferQueue::BufferItem& item) {
554 if (buf == NULL) {
555 return false;
556 }
557
558 uint32_t bufWidth = buf->getWidth();
559 uint32_t bufHeight = buf->getHeight();
560
561 // check that we received a buffer of the right size
562 // (Take the buffer's orientation into account)
563 if (item.mTransform & Transform::ROT_90) {
564 swap(bufWidth, bufHeight);
565 }
566
567
568 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
569 if (front.active != front.requested) {
570
571 if (isFixedSize ||
572 (bufWidth == front.requested.w &&
573 bufHeight == front.requested.h))
574 {
575 // Here we pretend the transaction happened by updating the
576 // current and drawing states. Drawing state is only accessed
577 // in this thread, no need to have it locked
578 front.active = front.requested;
579
580 // We also need to update the current state so that
581 // we don't end-up overwriting the drawing state with
582 // this stale current state during the next transaction
583 //
584 // NOTE: We don't need to hold the transaction lock here
585 // because State::active is only accessed from this thread.
586 current.active = front.active;
587
588 // recompute visible region
589 recomputeVisibleRegions = true;
590 }
591
592 ALOGD_IF(DEBUG_RESIZE,
593 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
594 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
595 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
596 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
597 front.active.w, front.active.h,
598 front.active.crop.left,
599 front.active.crop.top,
600 front.active.crop.right,
601 front.active.crop.bottom,
602 front.active.crop.getWidth(),
603 front.active.crop.getHeight(),
604 front.requested.w, front.requested.h,
605 front.requested.crop.left,
606 front.requested.crop.top,
607 front.requested.crop.right,
608 front.requested.crop.bottom,
609 front.requested.crop.getWidth(),
610 front.requested.crop.getHeight());
611 }
612
613 if (!isFixedSize) {
614 if (front.active.w != bufWidth ||
615 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700616 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700617 return true;
618 }
619 }
620 return false;
621 }
622 };
623
624
625 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
626
627 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700628 // something happened!
629 recomputeVisibleRegions = true;
630 return;
631 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700632
Jamie Gennis351a5132011-09-14 18:23:37 -0700633 // update the active buffer
634 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700635 if (mActiveBuffer == NULL) {
636 // this can only happen if the very first buffer was rejected.
637 return;
638 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800639
Mathias Agopian4824d402012-06-04 18:16:30 -0700640 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700641 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700642 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700643 // the first time we receive a buffer, we need to trigger a
644 // geometry invalidation.
645 mFlinger->invalidateHwcGeometry();
646 }
647
Mathias Agopian702634a2012-05-23 17:50:31 -0700648 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700649 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
650 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700651 if ((crop != mCurrentCrop) ||
652 (transform != mCurrentTransform) ||
653 (scalingMode != mCurrentScalingMode))
654 {
655 mCurrentCrop = crop;
656 mCurrentTransform = transform;
657 mCurrentScalingMode = scalingMode;
658 mFlinger->invalidateHwcGeometry();
659 }
660
661 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700662 uint32_t bufWidth = mActiveBuffer->getWidth();
663 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700664 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
665 bufHeight != uint32_t(oldActiveBuffer->height)) {
666 mFlinger->invalidateHwcGeometry();
667 }
668 }
669
670 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
671 if (oldOpacity != isOpaque()) {
672 recomputeVisibleRegions = true;
673 }
674
675 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700676 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700677 mPostedDirtyRegion.set(front.active.w, front.active.h);
678
679 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
680 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700681 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800682}
683
684void Layer::unlockPageFlip(
685 const Transform& planeTransform, Region& outDirtyRegion)
686{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800687 ATRACE_CALL();
688
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800689 Region postedRegion(mPostedDirtyRegion);
690 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800691 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800692 if (!visibleRegionScreen.isEmpty()) {
693 // The dirty region is given in the layer's coordinate space
694 // transform the dirty region by the surface's transformation
695 // and the global transformation.
696 const Layer::State& s(drawingState());
697 const Transform tr(planeTransform * s.transform);
698 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800699
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800700 // At this point, the dirty region is in screen space.
701 // Make sure it's constrained by the visible region (which
702 // is in screen space as well).
703 postedRegion.andSelf(visibleRegionScreen);
704 outDirtyRegion.orSelf(postedRegion);
705 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800706 }
707}
708
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700709void Layer::dump(String8& result, char* buffer, size_t SIZE) const
710{
711 LayerBaseClient::dump(result, buffer, SIZE);
712
Mathias Agopiana67932f2011-04-20 14:20:59 -0700713 sp<const GraphicBuffer> buf0(mActiveBuffer);
714 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700715 if (buf0 != 0) {
716 w0 = buf0->getWidth();
717 h0 = buf0->getHeight();
718 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700719 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700720 }
721 snprintf(buffer, SIZE,
722 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700723 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800724 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700725 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800726 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700727
728 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700729
Mathias Agopiana67932f2011-04-20 14:20:59 -0700730 if (mSurfaceTexture != 0) {
731 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700732 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700733}
734
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800735void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
736{
737 LayerBaseClient::dumpStats(result, buffer, SIZE);
738 const size_t o = mFrameLatencyOffset;
739 const DisplayHardware& hw(graphicPlane(0).displayHardware());
740 const nsecs_t period = hw.getRefreshPeriod();
741 result.appendFormat("%lld\n", period);
742 for (size_t i=0 ; i<128 ; i++) {
743 const size_t index = (o+i) % 128;
744 const nsecs_t time_app = mFrameStats[index].timestamp;
745 const nsecs_t time_set = mFrameStats[index].set;
746 const nsecs_t time_vsync = mFrameStats[index].vsync;
747 result.appendFormat("%lld\t%lld\t%lld\n",
748 time_app,
749 time_vsync,
750 time_set);
751 }
752 result.append("\n");
753}
754
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800755void Layer::clearStats()
756{
757 LayerBaseClient::clearStats();
758 memset(mFrameStats, 0, sizeof(mFrameStats));
759}
760
Mathias Agopiana67932f2011-04-20 14:20:59 -0700761uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700762{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700763 // TODO: should we do something special if mSecure is set?
764 if (mProtectedByApp) {
765 // need a hardware-protected path to external video sink
766 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700767 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700768 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700769 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700770}
771
Mathias Agopiana4583642011-08-23 18:03:18 -0700772uint32_t Layer::getTransformHint() const {
773 uint32_t orientation = 0;
774 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700775 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700776 if (orientation & Transform::ROT_INVALID) {
777 orientation = 0;
778 }
779 }
780 return orientation;
781}
782
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800783// ---------------------------------------------------------------------------
784
785
786}; // namespace android