blob: 890bcb446720e115d106fcb221d7b85bb80df7b9 [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 Agopian3e8b8532012-05-13 20:42:01 -0700262void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700263{
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700264 LayerBaseClient::setGeometry(layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700265
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700266 // enable this layer
267 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700268
269 // we can't do alpha-fade with the hwc HAL
270 const State& s(drawingState());
271 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700272 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700273 }
274
Mathias Agopian29a367b2011-07-12 14:51:45 -0700275 /*
276 * Transformations are applied in this order:
277 * 1) buffer orientation/flip/mirror
278 * 2) state transformation (window manager)
279 * 3) layer orientation (screen orientation)
Mathias Agopiand992db32011-08-18 18:31:00 -0700280 * mTransform is already the composition of (2) and (3)
Mathias Agopian29a367b2011-07-12 14:51:45 -0700281 * (NOTE: the matrices are multiplied in reverse order)
282 */
283
284 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopiand992db32011-08-18 18:31:00 -0700285 const Transform tr(mTransform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700286
287 // this gives us only the "orientation" component of the transform
288 const uint32_t finalTransform = tr.getOrientation();
289
Mathias Agopiana350ff92010-08-10 17:14:02 -0700290 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700291 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700292 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700293 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700294 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700295 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700296 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700297}
298
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700299void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700300 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700301 // NOTE: buffer can be NULL if the client never drew into this
302 // layer yet, or if we ran out of memory
303 layer.setBuffer(buffer);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700304}
305
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800306void Layer::onDraw(const Region& clip) const
307{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800308 ATRACE_CALL();
309
Mathias Agopiana67932f2011-04-20 14:20:59 -0700310 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800311 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700312 // in fact never been drawn into. This happens frequently with
313 // SurfaceView because the WindowManager can't know when the client
314 // has drawn the first time.
315
316 // If there is nothing under us, we paint the screen in black, otherwise
317 // we just skip this update.
318
319 // figure out if there is something below us
320 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700321 const SurfaceFlinger::LayerVector& drawingLayers(
322 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700323 const size_t count = drawingLayers.size();
324 for (size_t i=0 ; i<count ; ++i) {
325 const sp<LayerBase>& layer(drawingLayers[i]);
326 if (layer.get() == static_cast<LayerBase const*>(this))
327 break;
328 under.orSelf(layer->visibleRegionScreen);
329 }
330 // if not everything below us is covered, we plug the holes!
331 Region holes(clip.subtract(under));
332 if (!holes.isEmpty()) {
Mathias Agopian0a917752010-06-14 21:20:00 -0700333 clearWithOpenGL(holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700334 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800335 return;
336 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700337
Jamie Gennis9575f602011-10-07 14:51:16 -0700338 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700339 // TODO: we could be more subtle with isFixedSize()
340 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
341
342 // Query the texture matrix given our current filtering mode.
343 float textureMatrix[16];
344 mSurfaceTexture->setFilteringEnabled(useFiltering);
345 mSurfaceTexture->getTransformMatrix(textureMatrix);
346
347 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700348 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
349 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700350 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700351 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700352 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700353 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
354 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700355 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700356 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700357 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700358 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700359 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700360 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700361 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700362 glMatrixMode(GL_TEXTURE);
363 glLoadIdentity();
364 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700365 glDisable(GL_TEXTURE_EXTERNAL_OES);
366 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700367 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700368
369 drawWithOpenGL(clip);
370
Mathias Agopianc492e672011-10-18 14:49:27 -0700371 glDisable(GL_TEXTURE_EXTERNAL_OES);
372 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800373}
374
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800375// As documented in libhardware header, formats in the range
376// 0x100 - 0x1FF are specific to the HAL implementation, and
377// are known to have no alpha channel
378// TODO: move definition for device-specific range into
379// hardware.h, instead of using hard-coded values here.
380#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
381
Mathias Agopiana67932f2011-04-20 14:20:59 -0700382bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800383{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700384 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
385 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800386 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700387 PixelFormatInfo info;
388 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
389 // in case of error (unknown format), we assume no blending
390 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800391}
392
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800393
Mathias Agopiana67932f2011-04-20 14:20:59 -0700394bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700395{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700396 // if we don't have a buffer yet, we're translucent regardless of the
397 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700398 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700399 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700400 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700401
402 // if the layer has the opaque flag, then we're always opaque,
403 // otherwise we use the current buffer's format.
404 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700405}
406
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800407bool Layer::isProtected() const
408{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700409 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800410 return (activeBuffer != 0) &&
411 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
412}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700413
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800414uint32_t Layer::doTransaction(uint32_t flags)
415{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800416 ATRACE_CALL();
417
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800418 const Layer::State& front(drawingState());
419 const Layer::State& temp(currentState());
420
Mathias Agopian4824d402012-06-04 18:16:30 -0700421 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
422 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700423
424 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700425 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000426 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700427 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
428 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
429 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
430 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
431 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
432 this, mCurrentScalingMode,
433 temp.active.w, temp.active.h,
434 temp.active.crop.left,
435 temp.active.crop.top,
436 temp.active.crop.right,
437 temp.active.crop.bottom,
438 temp.active.crop.getWidth(),
439 temp.active.crop.getHeight(),
440 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700441 temp.requested.crop.left,
442 temp.requested.crop.top,
443 temp.requested.crop.right,
444 temp.requested.crop.bottom,
445 temp.requested.crop.getWidth(),
446 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700447 front.active.w, front.active.h,
448 front.active.crop.left,
449 front.active.crop.top,
450 front.active.crop.right,
451 front.active.crop.bottom,
452 front.active.crop.getWidth(),
453 front.active.crop.getHeight(),
454 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700455 front.requested.crop.left,
456 front.requested.crop.top,
457 front.requested.crop.right,
458 front.requested.crop.bottom,
459 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700460 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700462 // record the new size, form this point on, when the client request
463 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700464 mSurfaceTexture->setDefaultBufferSize(
465 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800466 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700467
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700468 if (!isFixedSize()) {
469
470 const bool resizePending = (temp.requested.w != temp.active.w) ||
471 (temp.requested.h != temp.active.h);
472
473 if (resizePending) {
474 // don't let LayerBase::doTransaction update the drawing state
475 // if we have a pending resize, unless we are in fixed-size mode.
476 // the drawing state will be updated only once we receive a buffer
477 // with the correct size.
478 //
479 // in particular, we want to make sure the clip (which is part
480 // of the geometry state) is latched together with the size but is
481 // latched immediately when no resizing is involved.
482
483 flags |= eDontUpdateGeometryState;
484 }
485 }
486
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800487 return LayerBase::doTransaction(flags);
488}
489
Mathias Agopiana138f892010-05-21 17:24:35 -0700490bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700491 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700492}
493
494bool Layer::isCropped() const {
495 return !mCurrentCrop.isEmpty();
496}
497
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800498// ----------------------------------------------------------------------------
499// pageflip handling...
500// ----------------------------------------------------------------------------
501
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800502bool Layer::onPreComposition() {
503 mRefreshPending = false;
504 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800505}
506
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800507void Layer::lockPageFlip(bool& recomputeVisibleRegions)
508{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800509 ATRACE_CALL();
510
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700511 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800512
513 // if we've already called updateTexImage() without going through
514 // a composition step, we have to skip this layer at this point
515 // because we cannot call updateTeximage() without a corresponding
516 // compositionComplete() call.
517 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800518 if (mRefreshPending) {
519 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800520 return;
521 }
522
Jamie Gennis351a5132011-09-14 18:23:37 -0700523 // Capture the old state of the layer for comparisons later
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700524 const bool oldOpacity = isOpaque();
Jamie Gennis351a5132011-09-14 18:23:37 -0700525 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700526
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700527 // signal another event if we have more frames pending
528 if (android_atomic_dec(&mQueuedFrames) > 1) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800529 mFlinger->signalLayerUpdate();
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700530 }
531
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700532 struct Reject : public SurfaceTexture::BufferRejecter {
533 Layer::State& front;
534 Layer::State& current;
535 bool& recomputeVisibleRegions;
536 Reject(Layer::State& front, Layer::State& current,
537 bool& recomputeVisibleRegions)
538 : front(front), current(current),
539 recomputeVisibleRegions(recomputeVisibleRegions) {
540 }
541
542 virtual bool reject(const sp<GraphicBuffer>& buf,
543 const BufferQueue::BufferItem& item) {
544 if (buf == NULL) {
545 return false;
546 }
547
548 uint32_t bufWidth = buf->getWidth();
549 uint32_t bufHeight = buf->getHeight();
550
551 // check that we received a buffer of the right size
552 // (Take the buffer's orientation into account)
553 if (item.mTransform & Transform::ROT_90) {
554 swap(bufWidth, bufHeight);
555 }
556
557
558 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
559 if (front.active != front.requested) {
560
561 if (isFixedSize ||
562 (bufWidth == front.requested.w &&
563 bufHeight == front.requested.h))
564 {
565 // Here we pretend the transaction happened by updating the
566 // current and drawing states. Drawing state is only accessed
567 // in this thread, no need to have it locked
568 front.active = front.requested;
569
570 // We also need to update the current state so that
571 // we don't end-up overwriting the drawing state with
572 // this stale current state during the next transaction
573 //
574 // NOTE: We don't need to hold the transaction lock here
575 // because State::active is only accessed from this thread.
576 current.active = front.active;
577
578 // recompute visible region
579 recomputeVisibleRegions = true;
580 }
581
582 ALOGD_IF(DEBUG_RESIZE,
583 "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
584 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
585 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
586 this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
587 front.active.w, front.active.h,
588 front.active.crop.left,
589 front.active.crop.top,
590 front.active.crop.right,
591 front.active.crop.bottom,
592 front.active.crop.getWidth(),
593 front.active.crop.getHeight(),
594 front.requested.w, front.requested.h,
595 front.requested.crop.left,
596 front.requested.crop.top,
597 front.requested.crop.right,
598 front.requested.crop.bottom,
599 front.requested.crop.getWidth(),
600 front.requested.crop.getHeight());
601 }
602
603 if (!isFixedSize) {
604 if (front.active.w != bufWidth ||
605 front.active.h != bufHeight) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700606 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700607 return true;
608 }
609 }
610 return false;
611 }
612 };
613
614
615 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
616
617 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700618 // something happened!
619 recomputeVisibleRegions = true;
620 return;
621 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700622
Jamie Gennis351a5132011-09-14 18:23:37 -0700623 // update the active buffer
624 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700625 if (mActiveBuffer == NULL) {
626 // this can only happen if the very first buffer was rejected.
627 return;
628 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800629
Mathias Agopian4824d402012-06-04 18:16:30 -0700630 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700631 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700632 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700633 // the first time we receive a buffer, we need to trigger a
634 // geometry invalidation.
635 mFlinger->invalidateHwcGeometry();
636 }
637
Mathias Agopian702634a2012-05-23 17:50:31 -0700638 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700639 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
640 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700641 if ((crop != mCurrentCrop) ||
642 (transform != mCurrentTransform) ||
643 (scalingMode != mCurrentScalingMode))
644 {
645 mCurrentCrop = crop;
646 mCurrentTransform = transform;
647 mCurrentScalingMode = scalingMode;
648 mFlinger->invalidateHwcGeometry();
649 }
650
651 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700652 uint32_t bufWidth = mActiveBuffer->getWidth();
653 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700654 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
655 bufHeight != uint32_t(oldActiveBuffer->height)) {
656 mFlinger->invalidateHwcGeometry();
657 }
658 }
659
660 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
661 if (oldOpacity != isOpaque()) {
662 recomputeVisibleRegions = true;
663 }
664
665 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700666 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700667 mPostedDirtyRegion.set(front.active.w, front.active.h);
668
669 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
670 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700671 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800672}
673
674void Layer::unlockPageFlip(
675 const Transform& planeTransform, Region& outDirtyRegion)
676{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800677 ATRACE_CALL();
678
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800679 Region postedRegion(mPostedDirtyRegion);
680 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800681 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800682 if (!visibleRegionScreen.isEmpty()) {
683 // The dirty region is given in the layer's coordinate space
684 // transform the dirty region by the surface's transformation
685 // and the global transformation.
686 const Layer::State& s(drawingState());
687 const Transform tr(planeTransform * s.transform);
688 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800689
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800690 // At this point, the dirty region is in screen space.
691 // Make sure it's constrained by the visible region (which
692 // is in screen space as well).
693 postedRegion.andSelf(visibleRegionScreen);
694 outDirtyRegion.orSelf(postedRegion);
695 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800696 }
697}
698
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700699void Layer::dump(String8& result, char* buffer, size_t SIZE) const
700{
701 LayerBaseClient::dump(result, buffer, SIZE);
702
Mathias Agopiana67932f2011-04-20 14:20:59 -0700703 sp<const GraphicBuffer> buf0(mActiveBuffer);
704 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700705 if (buf0 != 0) {
706 w0 = buf0->getWidth();
707 h0 = buf0->getHeight();
708 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700709 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700710 }
711 snprintf(buffer, SIZE,
712 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700713 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800714 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700715 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800716 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700717
718 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700719
Mathias Agopiana67932f2011-04-20 14:20:59 -0700720 if (mSurfaceTexture != 0) {
721 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700722 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700723}
724
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800725void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
726{
727 LayerBaseClient::dumpStats(result, buffer, SIZE);
728 const size_t o = mFrameLatencyOffset;
729 const DisplayHardware& hw(graphicPlane(0).displayHardware());
730 const nsecs_t period = hw.getRefreshPeriod();
731 result.appendFormat("%lld\n", period);
732 for (size_t i=0 ; i<128 ; i++) {
733 const size_t index = (o+i) % 128;
734 const nsecs_t time_app = mFrameStats[index].timestamp;
735 const nsecs_t time_set = mFrameStats[index].set;
736 const nsecs_t time_vsync = mFrameStats[index].vsync;
737 result.appendFormat("%lld\t%lld\t%lld\n",
738 time_app,
739 time_vsync,
740 time_set);
741 }
742 result.append("\n");
743}
744
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800745void Layer::clearStats()
746{
747 LayerBaseClient::clearStats();
748 memset(mFrameStats, 0, sizeof(mFrameStats));
749}
750
Mathias Agopiana67932f2011-04-20 14:20:59 -0700751uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700752{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700753 // TODO: should we do something special if mSecure is set?
754 if (mProtectedByApp) {
755 // need a hardware-protected path to external video sink
756 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700757 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700758 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700759 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700760}
761
Mathias Agopiana4583642011-08-23 18:03:18 -0700762uint32_t Layer::getTransformHint() const {
763 uint32_t orientation = 0;
764 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700765 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700766 if (orientation & Transform::ROT_INVALID) {
767 orientation = 0;
768 }
769 }
770 return orientation;
771}
772
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800773// ---------------------------------------------------------------------------
774
775
776}; // namespace android