blob: fc7c767b55036cf78bc42ce9650d8fc6f388df00 [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 Agopian93ffb862012-05-16 17:07:49 -0700431 const bool sizeChanged = (front.requested.w != temp.requested.w) ||
432 (front.requested.h != temp.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
Mathias Agopiana138f892010-05-21 17:24:35 -0700472 if (!isFixedSize()) {
Mathias Agopiana138f892010-05-21 17:24:35 -0700473 // this will make sure LayerBase::doTransaction doesn't update
Mathias Agopianb30c4152012-05-16 18:21:32 -0700474 // the drawing state's geometry
Mathias Agopiana138f892010-05-21 17:24:35 -0700475 Layer::State& editDraw(mDrawingState);
Mathias Agopianb30c4152012-05-16 18:21:32 -0700476 editDraw.requested = temp.requested;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800477 }
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700478
479 // record the new size, form this point on, when the client request
480 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700481 mSurfaceTexture->setDefaultBufferSize(
482 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800483 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700484
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800485 return LayerBase::doTransaction(flags);
486}
487
Mathias Agopiana138f892010-05-21 17:24:35 -0700488bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700489 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700490}
491
492bool Layer::isCropped() const {
493 return !mCurrentCrop.isEmpty();
494}
495
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800496// ----------------------------------------------------------------------------
497// pageflip handling...
498// ----------------------------------------------------------------------------
499
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800500bool Layer::onPreComposition() {
501 mRefreshPending = false;
502 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800503}
504
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505void Layer::lockPageFlip(bool& recomputeVisibleRegions)
506{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800507 ATRACE_CALL();
508
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700509 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800510
511 // if we've already called updateTexImage() without going through
512 // a composition step, we have to skip this layer at this point
513 // because we cannot call updateTeximage() without a corresponding
514 // compositionComplete() call.
515 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800516 if (mRefreshPending) {
517 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800518 return;
519 }
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800520 mRefreshPending = true;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800521
Jamie Gennis351a5132011-09-14 18:23:37 -0700522 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700523 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700524 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700525
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700526 // signal another event if we have more frames pending
527 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800528 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700529 }
530
Mathias Agopiana67932f2011-04-20 14:20:59 -0700531 if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
532 // something happened!
533 recomputeVisibleRegions = true;
534 return;
535 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700536
Jamie Gennis351a5132011-09-14 18:23:37 -0700537 // update the active buffer
538 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Jamie Gennise8696a42012-01-15 18:54:57 -0800539 mFrameLatencyNeeded = true;
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700540
Mathias Agopianec923ee2012-02-27 16:58:04 -0800541 if (oldActiveBuffer == NULL && mActiveBuffer != NULL) {
542 // the first time we receive a buffer, we need to trigger a
543 // geometry invalidation.
544 mFlinger->invalidateHwcGeometry();
545 }
546
Jamie Gennis161534a2012-05-07 13:51:53 -0700547 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopiana67932f2011-04-20 14:20:59 -0700548 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
Mathias Agopian933389f2011-07-18 16:15:08 -0700549 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
550 if ((crop != mCurrentCrop) ||
551 (transform != mCurrentTransform) ||
552 (scalingMode != mCurrentScalingMode))
553 {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700554 mCurrentCrop = crop;
555 mCurrentTransform = transform;
Mathias Agopian933389f2011-07-18 16:15:08 -0700556 mCurrentScalingMode = scalingMode;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700557 mFlinger->invalidateHwcGeometry();
558 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800559
Jamie Gennis351a5132011-09-14 18:23:37 -0700560 uint32_t bufWidth = mActiveBuffer->getWidth();
561 uint32_t bufHeight = mActiveBuffer->getHeight();
562 if (oldActiveBuffer != NULL) {
563 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
564 bufHeight != uint32_t(oldActiveBuffer->height)) {
Mathias Agopianc7f33812011-08-30 15:02:41 -0700565 mFlinger->invalidateHwcGeometry();
566 }
567 }
568
Jamie Gennis351a5132011-09-14 18:23:37 -0700569 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700570 if (oldOpacity != isOpaque()) {
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800571 recomputeVisibleRegions = true;
572 }
573
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700574 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
575 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700576
Jamie Gennisa402c4c2011-10-14 16:44:08 -0700577 // update the layer size if needed
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700578 const Layer::State& front(drawingState());
Mathias Agopiana67932f2011-04-20 14:20:59 -0700579
580 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian93ffb862012-05-16 17:07:49 -0700581 mPostedDirtyRegion.set(front.active.w, front.active.h);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700582
Mathias Agopianb30c4152012-05-16 18:21:32 -0700583 if (front.active != front.requested) {
Mathias Agopian97c602c2011-07-19 15:24:46 -0700584 // check that we received a buffer of the right size
585 // (Take the buffer's orientation into account)
Mathias Agopian97c602c2011-07-19 15:24:46 -0700586 if (mCurrentTransform & Transform::ROT_90) {
587 swap(bufWidth, bufHeight);
588 }
589
590 if (isFixedSize() ||
Mathias Agopian93ffb862012-05-16 17:07:49 -0700591 (bufWidth == front.requested.w &&
592 bufHeight == front.requested.h))
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700593 {
594 // Here we pretend the transaction happened by updating the
595 // current and drawing states. Drawing state is only accessed
596 // in this thread, no need to have it locked
Mathias Agopian419e1962012-05-23 14:34:07 -0700597 Layer::State& editFront(mDrawingState);
598 editFront.active = front.requested;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700599
Mathias Agopian419e1962012-05-23 14:34:07 -0700600 // We also need to update the current state so that
601 // we don't end-up overwriting the drawing state with
602 // this stale current state during the next transaction
603 //
604 // NOTE: We don't need to hold the transaction lock here
605 // because State::active is only accessed from this thread.
606 Layer::State& editCurrent(currentState());
607 editCurrent.active = front.active;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700608
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700609 // recompute visible region
610 recomputeVisibleRegions = true;
Mathias Agopian97c602c2011-07-19 15:24:46 -0700611 }
Mathias Agopian3fbce7c2011-07-25 19:56:08 -0700612
Steve Block9d453682011-12-20 16:23:08 +0000613 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700614 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
615 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
616 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
617 this, bufWidth, bufHeight, mCurrentTransform, mCurrentScalingMode,
618 front.active.w, front.active.h,
619 front.active.crop.left,
620 front.active.crop.top,
621 front.active.crop.right,
622 front.active.crop.bottom,
623 front.active.crop.getWidth(),
624 front.active.crop.getHeight(),
625 front.requested.w, front.requested.h,
626 front.requested.crop.left,
627 front.requested.crop.top,
628 front.requested.crop.right,
629 front.requested.crop.bottom,
630 front.requested.crop.getWidth(),
631 front.requested.crop.getHeight());
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700632 }
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700633 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800634}
635
636void Layer::unlockPageFlip(
637 const Transform& planeTransform, Region& outDirtyRegion)
638{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800639 ATRACE_CALL();
640
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800641 Region postedRegion(mPostedDirtyRegion);
642 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800643 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800644 if (!visibleRegionScreen.isEmpty()) {
645 // The dirty region is given in the layer's coordinate space
646 // transform the dirty region by the surface's transformation
647 // and the global transformation.
648 const Layer::State& s(drawingState());
649 const Transform tr(planeTransform * s.transform);
650 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800651
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800652 // At this point, the dirty region is in screen space.
653 // Make sure it's constrained by the visible region (which
654 // is in screen space as well).
655 postedRegion.andSelf(visibleRegionScreen);
656 outDirtyRegion.orSelf(postedRegion);
657 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800658 }
659}
660
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700661void Layer::dump(String8& result, char* buffer, size_t SIZE) const
662{
663 LayerBaseClient::dump(result, buffer, SIZE);
664
Mathias Agopiana67932f2011-04-20 14:20:59 -0700665 sp<const GraphicBuffer> buf0(mActiveBuffer);
666 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700667 if (buf0 != 0) {
668 w0 = buf0->getWidth();
669 h0 = buf0->getHeight();
670 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700671 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700672 }
673 snprintf(buffer, SIZE,
674 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700675 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800676 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700677 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800678 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700679
680 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700681
Mathias Agopiana67932f2011-04-20 14:20:59 -0700682 if (mSurfaceTexture != 0) {
683 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700684 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700685}
686
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800687void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
688{
689 LayerBaseClient::dumpStats(result, buffer, SIZE);
690 const size_t o = mFrameLatencyOffset;
691 const DisplayHardware& hw(graphicPlane(0).displayHardware());
692 const nsecs_t period = hw.getRefreshPeriod();
693 result.appendFormat("%lld\n", period);
694 for (size_t i=0 ; i<128 ; i++) {
695 const size_t index = (o+i) % 128;
696 const nsecs_t time_app = mFrameStats[index].timestamp;
697 const nsecs_t time_set = mFrameStats[index].set;
698 const nsecs_t time_vsync = mFrameStats[index].vsync;
699 result.appendFormat("%lld\t%lld\t%lld\n",
700 time_app,
701 time_vsync,
702 time_set);
703 }
704 result.append("\n");
705}
706
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800707void Layer::clearStats()
708{
709 LayerBaseClient::clearStats();
710 memset(mFrameStats, 0, sizeof(mFrameStats));
711}
712
Mathias Agopiana67932f2011-04-20 14:20:59 -0700713uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700714{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700715 // TODO: should we do something special if mSecure is set?
716 if (mProtectedByApp) {
717 // need a hardware-protected path to external video sink
718 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700719 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700720 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700721 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700722}
723
Mathias Agopiana4583642011-08-23 18:03:18 -0700724uint32_t Layer::getTransformHint() const {
725 uint32_t orientation = 0;
726 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700727 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700728 if (orientation & Transform::ROT_INVALID) {
729 orientation = 0;
730 }
731 }
732 return orientation;
733}
734
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800735// ---------------------------------------------------------------------------
736
737
738}; // namespace android