blob: 593f1781ae7e3916fa750a1e8eefc2c6e8f352de [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
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 Agopian05cec9d2012-05-23 14:35:49 -0700475 flags |= eDontUpdateGeometryState;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800476 }
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700477
478 // record the new size, form this point on, when the client request
479 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700480 mSurfaceTexture->setDefaultBufferSize(
481 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800482 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700483
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800484 return LayerBase::doTransaction(flags);
485}
486
Mathias Agopiana138f892010-05-21 17:24:35 -0700487bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700488 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700489}
490
491bool Layer::isCropped() const {
492 return !mCurrentCrop.isEmpty();
493}
494
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800495// ----------------------------------------------------------------------------
496// pageflip handling...
497// ----------------------------------------------------------------------------
498
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800499bool Layer::onPreComposition() {
500 mRefreshPending = false;
501 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800502}
503
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800504void Layer::lockPageFlip(bool& recomputeVisibleRegions)
505{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800506 ATRACE_CALL();
507
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700508 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800509
510 // if we've already called updateTexImage() without going through
511 // a composition step, we have to skip this layer at this point
512 // because we cannot call updateTeximage() without a corresponding
513 // compositionComplete() call.
514 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800515 if (mRefreshPending) {
516 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800517 return;
518 }
519
Jamie Gennis351a5132011-09-14 18:23:37 -0700520 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700521 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700522 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700523
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700524 // signal another event if we have more frames pending
525 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800526 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700527 }
528
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700529 struct Reject : public SurfaceTexture::BufferRejecter {
530 Layer::State& front;
531 Layer::State& current;
532 bool& recomputeVisibleRegions;
533 Reject(Layer::State& front, Layer::State& current,
534 bool& recomputeVisibleRegions)
535 : front(front), current(current),
536 recomputeVisibleRegions(recomputeVisibleRegions) {
537 }
538
539 virtual bool reject(const sp<GraphicBuffer>& buf,
540 const BufferQueue::BufferItem& item) {
541 if (buf == NULL) {
542 return false;
543 }
544
545 uint32_t bufWidth = buf->getWidth();
546 uint32_t bufHeight = buf->getHeight();
547
548 // check that we received a buffer of the right size
549 // (Take the buffer's orientation into account)
550 if (item.mTransform & Transform::ROT_90) {
551 swap(bufWidth, bufHeight);
552 }
553
554
555 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
556 if (front.active != front.requested) {
557
558 if (isFixedSize ||
559 (bufWidth == front.requested.w &&
560 bufHeight == front.requested.h))
561 {
562 // Here we pretend the transaction happened by updating the
563 // current and drawing states. Drawing state is only accessed
564 // in this thread, no need to have it locked
565 front.active = front.requested;
566
567 // We also need to update the current state so that
568 // we don't end-up overwriting the drawing state with
569 // this stale current state during the next transaction
570 //
571 // NOTE: We don't need to hold the transaction lock here
572 // because State::active is only accessed from this thread.
573 current.active = front.active;
574
575 // recompute visible region
576 recomputeVisibleRegions = true;
577 }
578
579 ALOGD_IF(DEBUG_RESIZE,
580 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
581 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
582 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
583 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
584 front.active.w, front.active.h,
585 front.active.crop.left,
586 front.active.crop.top,
587 front.active.crop.right,
588 front.active.crop.bottom,
589 front.active.crop.getWidth(),
590 front.active.crop.getHeight(),
591 front.requested.w, front.requested.h,
592 front.requested.crop.left,
593 front.requested.crop.top,
594 front.requested.crop.right,
595 front.requested.crop.bottom,
596 front.requested.crop.getWidth(),
597 front.requested.crop.getHeight());
598 }
599
600 if (!isFixedSize) {
601 if (front.active.w != bufWidth ||
602 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700603 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700604 return true;
605 }
606 }
607 return false;
608 }
609 };
610
611
612 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
613
614 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700615 // something happened!
616 recomputeVisibleRegions = true;
617 return;
618 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700619
Jamie Gennis351a5132011-09-14 18:23:37 -0700620 // update the active buffer
621 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700622 if (mActiveBuffer == NULL) {
623 // this can only happen if the very first buffer was rejected.
624 return;
625 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800626
Mathias Agopian4824d402012-06-04 18:16:30 -0700627 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700628 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700629 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700630 // the first time we receive a buffer, we need to trigger a
631 // geometry invalidation.
632 mFlinger->invalidateHwcGeometry();
633 }
634
Mathias Agopian702634a2012-05-23 17:50:31 -0700635 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700636 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
637 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700638 if ((crop != mCurrentCrop) ||
639 (transform != mCurrentTransform) ||
640 (scalingMode != mCurrentScalingMode))
641 {
642 mCurrentCrop = crop;
643 mCurrentTransform = transform;
644 mCurrentScalingMode = scalingMode;
645 mFlinger->invalidateHwcGeometry();
646 }
647
648 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700649 uint32_t bufWidth = mActiveBuffer->getWidth();
650 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700651 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
652 bufHeight != uint32_t(oldActiveBuffer->height)) {
653 mFlinger->invalidateHwcGeometry();
654 }
655 }
656
657 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
658 if (oldOpacity != isOpaque()) {
659 recomputeVisibleRegions = true;
660 }
661
662 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700663 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700664 mPostedDirtyRegion.set(front.active.w, front.active.h);
665
666 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
667 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700668 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800669}
670
671void Layer::unlockPageFlip(
672 const Transform& planeTransform, Region& outDirtyRegion)
673{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800674 ATRACE_CALL();
675
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800676 Region postedRegion(mPostedDirtyRegion);
677 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800678 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800679 if (!visibleRegionScreen.isEmpty()) {
680 // The dirty region is given in the layer's coordinate space
681 // transform the dirty region by the surface's transformation
682 // and the global transformation.
683 const Layer::State& s(drawingState());
684 const Transform tr(planeTransform * s.transform);
685 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800686
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800687 // At this point, the dirty region is in screen space.
688 // Make sure it's constrained by the visible region (which
689 // is in screen space as well).
690 postedRegion.andSelf(visibleRegionScreen);
691 outDirtyRegion.orSelf(postedRegion);
692 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800693 }
694}
695
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700696void Layer::dump(String8& result, char* buffer, size_t SIZE) const
697{
698 LayerBaseClient::dump(result, buffer, SIZE);
699
Mathias Agopiana67932f2011-04-20 14:20:59 -0700700 sp<const GraphicBuffer> buf0(mActiveBuffer);
701 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700702 if (buf0 != 0) {
703 w0 = buf0->getWidth();
704 h0 = buf0->getHeight();
705 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700706 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700707 }
708 snprintf(buffer, SIZE,
709 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700710 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800711 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700712 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800713 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700714
715 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700716
Mathias Agopiana67932f2011-04-20 14:20:59 -0700717 if (mSurfaceTexture != 0) {
718 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700719 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700720}
721
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800722void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
723{
724 LayerBaseClient::dumpStats(result, buffer, SIZE);
725 const size_t o = mFrameLatencyOffset;
726 const DisplayHardware& hw(graphicPlane(0).displayHardware());
727 const nsecs_t period = hw.getRefreshPeriod();
728 result.appendFormat("%lld\n", period);
729 for (size_t i=0 ; i<128 ; i++) {
730 const size_t index = (o+i) % 128;
731 const nsecs_t time_app = mFrameStats[index].timestamp;
732 const nsecs_t time_set = mFrameStats[index].set;
733 const nsecs_t time_vsync = mFrameStats[index].vsync;
734 result.appendFormat("%lld\t%lld\t%lld\n",
735 time_app,
736 time_vsync,
737 time_set);
738 }
739 result.append("\n");
740}
741
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800742void Layer::clearStats()
743{
744 LayerBaseClient::clearStats();
745 memset(mFrameStats, 0, sizeof(mFrameStats));
746}
747
Mathias Agopiana67932f2011-04-20 14:20:59 -0700748uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700749{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700750 // TODO: should we do something special if mSecure is set?
751 if (mProtectedByApp) {
752 // need a hardware-protected path to external video sink
753 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700754 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700755 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700756 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700757}
758
Mathias Agopiana4583642011-08-23 18:03:18 -0700759uint32_t Layer::getTransformHint() const {
760 uint32_t orientation = 0;
761 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700762 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700763 if (orientation & Transform::ROT_INVALID) {
764 orientation = 0;
765 }
766 }
767 return orientation;
768}
769
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800770// ---------------------------------------------------------------------------
771
772
773}; // namespace android