blob: d07a4b685207ea1c6e0e04b9cca2f9b39a67735c [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 Agopian05cec9d2012-05-23 14:35:49 -0700431 const bool sizeChanged = (temp.requested.w != front.active.w) ||
432 (temp.requested.h != front.active.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 }
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800519 mRefreshPending = true;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800520
Jamie Gennis351a5132011-09-14 18:23:37 -0700521 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700522 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700523 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700524
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700525 // signal another event if we have more frames pending
526 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800527 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700528 }
529
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700530 struct Reject : public SurfaceTexture::BufferRejecter {
531 Layer::State& front;
532 Layer::State& current;
533 bool& recomputeVisibleRegions;
534 Reject(Layer::State& front, Layer::State& current,
535 bool& recomputeVisibleRegions)
536 : front(front), current(current),
537 recomputeVisibleRegions(recomputeVisibleRegions) {
538 }
539
540 virtual bool reject(const sp<GraphicBuffer>& buf,
541 const BufferQueue::BufferItem& item) {
542 if (buf == NULL) {
543 return false;
544 }
545
546 uint32_t bufWidth = buf->getWidth();
547 uint32_t bufHeight = buf->getHeight();
548
549 // check that we received a buffer of the right size
550 // (Take the buffer's orientation into account)
551 if (item.mTransform & Transform::ROT_90) {
552 swap(bufWidth, bufHeight);
553 }
554
555
556 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
557 if (front.active != front.requested) {
558
559 if (isFixedSize ||
560 (bufWidth == front.requested.w &&
561 bufHeight == front.requested.h))
562 {
563 // Here we pretend the transaction happened by updating the
564 // current and drawing states. Drawing state is only accessed
565 // in this thread, no need to have it locked
566 front.active = front.requested;
567
568 // We also need to update the current state so that
569 // we don't end-up overwriting the drawing state with
570 // this stale current state during the next transaction
571 //
572 // NOTE: We don't need to hold the transaction lock here
573 // because State::active is only accessed from this thread.
574 current.active = front.active;
575
576 // recompute visible region
577 recomputeVisibleRegions = true;
578 }
579
580 ALOGD_IF(DEBUG_RESIZE,
581 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
582 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
583 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
584 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
585 front.active.w, front.active.h,
586 front.active.crop.left,
587 front.active.crop.top,
588 front.active.crop.right,
589 front.active.crop.bottom,
590 front.active.crop.getWidth(),
591 front.active.crop.getHeight(),
592 front.requested.w, front.requested.h,
593 front.requested.crop.left,
594 front.requested.crop.top,
595 front.requested.crop.right,
596 front.requested.crop.bottom,
597 front.requested.crop.getWidth(),
598 front.requested.crop.getHeight());
599 }
600
601 if (!isFixedSize) {
602 if (front.active.w != bufWidth ||
603 front.active.h != bufHeight) {
604 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
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700620
Jamie Gennis351a5132011-09-14 18:23:37 -0700621 // update the active buffer
622 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopianda9584d2010-12-13 18:51:59 -0800623
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700624 mFrameLatencyNeeded = true;
625 if (oldActiveBuffer == NULL && mActiveBuffer != NULL) {
626 // the first time we receive a buffer, we need to trigger a
627 // geometry invalidation.
628 mFlinger->invalidateHwcGeometry();
629 }
630
Jamie Gennis351a5132011-09-14 18:23:37 -0700631 uint32_t bufWidth = mActiveBuffer->getWidth();
632 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700633
634 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700635 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
636 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700637 if ((crop != mCurrentCrop) ||
638 (transform != mCurrentTransform) ||
639 (scalingMode != mCurrentScalingMode))
640 {
641 mCurrentCrop = crop;
642 mCurrentTransform = transform;
643 mCurrentScalingMode = scalingMode;
644 mFlinger->invalidateHwcGeometry();
645 }
646
647 if (oldActiveBuffer != NULL) {
648 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
649 bufHeight != uint32_t(oldActiveBuffer->height)) {
650 mFlinger->invalidateHwcGeometry();
651 }
652 }
653
654 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
655 if (oldOpacity != isOpaque()) {
656 recomputeVisibleRegions = true;
657 }
658
659 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700660 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700661 mPostedDirtyRegion.set(front.active.w, front.active.h);
662
663 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
664 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700665 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800666}
667
668void Layer::unlockPageFlip(
669 const Transform& planeTransform, Region& outDirtyRegion)
670{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800671 ATRACE_CALL();
672
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800673 Region postedRegion(mPostedDirtyRegion);
674 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800675 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800676 if (!visibleRegionScreen.isEmpty()) {
677 // The dirty region is given in the layer's coordinate space
678 // transform the dirty region by the surface's transformation
679 // and the global transformation.
680 const Layer::State& s(drawingState());
681 const Transform tr(planeTransform * s.transform);
682 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800683
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800684 // At this point, the dirty region is in screen space.
685 // Make sure it's constrained by the visible region (which
686 // is in screen space as well).
687 postedRegion.andSelf(visibleRegionScreen);
688 outDirtyRegion.orSelf(postedRegion);
689 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800690 }
691}
692
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700693void Layer::dump(String8& result, char* buffer, size_t SIZE) const
694{
695 LayerBaseClient::dump(result, buffer, SIZE);
696
Mathias Agopiana67932f2011-04-20 14:20:59 -0700697 sp<const GraphicBuffer> buf0(mActiveBuffer);
698 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700699 if (buf0 != 0) {
700 w0 = buf0->getWidth();
701 h0 = buf0->getHeight();
702 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700703 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700704 }
705 snprintf(buffer, SIZE,
706 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700707 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800708 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700709 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800710 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700711
712 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700713
Mathias Agopiana67932f2011-04-20 14:20:59 -0700714 if (mSurfaceTexture != 0) {
715 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700716 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700717}
718
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800719void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
720{
721 LayerBaseClient::dumpStats(result, buffer, SIZE);
722 const size_t o = mFrameLatencyOffset;
723 const DisplayHardware& hw(graphicPlane(0).displayHardware());
724 const nsecs_t period = hw.getRefreshPeriod();
725 result.appendFormat("%lld\n", period);
726 for (size_t i=0 ; i<128 ; i++) {
727 const size_t index = (o+i) % 128;
728 const nsecs_t time_app = mFrameStats[index].timestamp;
729 const nsecs_t time_set = mFrameStats[index].set;
730 const nsecs_t time_vsync = mFrameStats[index].vsync;
731 result.appendFormat("%lld\t%lld\t%lld\n",
732 time_app,
733 time_vsync,
734 time_set);
735 }
736 result.append("\n");
737}
738
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800739void Layer::clearStats()
740{
741 LayerBaseClient::clearStats();
742 memset(mFrameStats, 0, sizeof(mFrameStats));
743}
744
Mathias Agopiana67932f2011-04-20 14:20:59 -0700745uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700746{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700747 // TODO: should we do something special if mSecure is set?
748 if (mProtectedByApp) {
749 // need a hardware-protected path to external video sink
750 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700751 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700752 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700753 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700754}
755
Mathias Agopiana4583642011-08-23 18:03:18 -0700756uint32_t Layer::getTransformHint() const {
757 uint32_t orientation = 0;
758 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700759 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700760 if (orientation & Transform::ROT_INVALID) {
761 orientation = 0;
762 }
763 }
764 return orientation;
765}
766
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800767// ---------------------------------------------------------------------------
768
769
770}; // namespace android