blob: 6aba16a5c642f861664bd98290b6a18234b0bbc5 [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 Agopian1b031492012-06-20 17:51:20 -070039#include "DisplayHardware.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070040#include "GLExtensions.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080042#include "SurfaceFlinger.h"
Mathias Agopiana67932f2011-04-20 14:20:59 -070043#include "SurfaceTextureLayer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044
Mathias Agopian1b031492012-06-20 17:51:20 -070045#include "DisplayHardware/HWComposer.h"
46
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080047#define DEBUG_RESIZE 0
48
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080049namespace android {
50
51// ---------------------------------------------------------------------------
52
Mathias Agopian96f08192010-06-02 23:28:45 -070053Layer::Layer(SurfaceFlinger* flinger,
54 DisplayID display, const sp<Client>& client)
55 : LayerBaseClient(flinger, display, client),
Mathias Agopiana67932f2011-04-20 14:20:59 -070056 mTextureName(-1U),
57 mQueuedFrames(0),
58 mCurrentTransform(0),
Mathias Agopian933389f2011-07-18 16:15:08 -070059 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
Mathias Agopiana67932f2011-04-20 14:20:59 -070060 mCurrentOpacity(true),
Mathias Agopian4d143ee2012-02-23 20:05:39 -080061 mRefreshPending(false),
Mathias Agopian82d7ab62012-01-19 18:34:40 -080062 mFrameLatencyNeeded(false),
63 mFrameLatencyOffset(0),
Mathias Agopian5bf3abe2011-03-11 17:01:07 -080064 mFormat(PIXEL_FORMAT_NONE),
Mathias Agopian1f7bec62010-06-25 18:02:21 -070065 mGLExtensions(GLExtensions::getInstance()),
Mathias Agopiana67932f2011-04-20 14:20:59 -070066 mOpaqueLayer(true),
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
Jesse Hallef194142012-06-14 14:45:17 -070074void Layer::onLayerDisplayed(HWComposer::HWCLayerInterface* layer) {
75 if (layer) {
76 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
77 }
78
Jamie Gennise8696a42012-01-15 18:54:57 -080079 if (mFrameLatencyNeeded) {
Mathias Agopian1b031492012-06-20 17:51:20 -070080 // we need a DisplayHardware for debugging only right now
81 // XXX: should this be called per DisplayHardware?
82 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -080083 mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp();
84 mFrameStats[mFrameLatencyOffset].set = systemTime();
85 mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp();
Jamie Gennise8696a42012-01-15 18:54:57 -080086 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
87 mFrameLatencyNeeded = false;
88 }
Mathias Agopiand606de62010-05-10 20:06:11 -070089}
90
Mathias Agopiana67932f2011-04-20 14:20:59 -070091void Layer::onFirstRef()
Mathias Agopian96f08192010-06-02 23:28:45 -070092{
Mathias Agopiana67932f2011-04-20 14:20:59 -070093 LayerBaseClient::onFirstRef();
Mathias Agopianddc31c32011-06-12 18:05:53 -070094
Mathias Agopiana67932f2011-04-20 14:20:59 -070095 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
96 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
97 private:
98 wp<Layer> mLayer;
99 virtual void onFrameAvailable() {
100 sp<Layer> that(mLayer.promote());
101 if (that != 0) {
102 that->onFrameQueued();
103 }
104 }
105 };
Daniel Lamb2675792012-02-23 14:35:13 -0800106
107 // Creates a custom BufferQueue for SurfaceTexture to use
108 sp<BufferQueue> bq = new SurfaceTextureLayer();
109 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
Mathias Agopiana0db3082012-04-23 13:59:36 -0700110 GL_TEXTURE_EXTERNAL_OES, false, bq);
Daniel Lamb2675792012-02-23 14:35:13 -0800111
Daniel Lamb2675792012-02-23 14:35:13 -0800112 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopiana67932f2011-04-20 14:20:59 -0700113 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
114 mSurfaceTexture->setSynchronousMode(true);
Daniel Lamb2675792012-02-23 14:35:13 -0800115
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700116#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
117#warning "disabling triple buffering"
Mathias Agopiana67932f2011-04-20 14:20:59 -0700118 mSurfaceTexture->setBufferCountServer(2);
Mathias Agopian7f42a9c2012-04-23 20:00:16 -0700119#else
120 mSurfaceTexture->setBufferCountServer(3);
Mathias Agopian303d5382012-02-05 01:49:16 -0800121#endif
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700122}
123
Mathias Agopiana67932f2011-04-20 14:20:59 -0700124Layer::~Layer()
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700125{
Mathias Agopian118d0242011-10-13 16:02:48 -0700126 mFlinger->postMessageAsync(
127 new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
Mathias Agopian96f08192010-06-02 23:28:45 -0700128}
129
Mathias Agopiana67932f2011-04-20 14:20:59 -0700130void Layer::onFrameQueued() {
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700131 android_atomic_inc(&mQueuedFrames);
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800132 mFlinger->signalLayerUpdate();
Mathias Agopian579b3f82010-06-08 19:54:15 -0700133}
134
Mathias Agopiand606de62010-05-10 20:06:11 -0700135// called with SurfaceFlinger::mStateLock as soon as the layer is entered
136// in the purgatory list
137void Layer::onRemoved()
138{
Jamie Gennisdbe64862011-07-30 14:33:49 -0700139 mSurfaceTexture->abandon();
Mathias Agopian48d819a2009-09-10 19:41:18 -0700140}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700141
Jamie Gennisa249f2d2011-09-16 17:31:54 -0700142void Layer::setName(const String8& name) {
143 LayerBase::setName(name);
144 mSurfaceTexture->setName(name);
145}
146
Mathias Agopian1b031492012-06-20 17:51:20 -0700147void Layer::validateVisibility(const Transform& globalTransform, const DisplayHardware& hw) {
148 LayerBase::validateVisibility(globalTransform, hw);
Daniel Lamb2675792012-02-23 14:35:13 -0800149
150 // This optimization allows the SurfaceTexture to bake in
151 // the rotation so hardware overlays can be used
152 mSurfaceTexture->setTransformHint(getTransformHint());
153}
154
Mathias Agopiana67932f2011-04-20 14:20:59 -0700155sp<ISurface> Layer::createSurface()
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800156{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700157 class BSurface : public BnSurface, public LayerCleaner {
158 wp<const Layer> mOwner;
159 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
160 sp<ISurfaceTexture> res;
161 sp<const Layer> that( mOwner.promote() );
162 if (that != NULL) {
Daniel Lamb2675792012-02-23 14:35:13 -0800163 res = that->mSurfaceTexture->getBufferQueue();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700164 }
165 return res;
166 }
167 public:
168 BSurface(const sp<SurfaceFlinger>& flinger,
169 const sp<Layer>& layer)
170 : LayerCleaner(flinger, layer), mOwner(layer) { }
171 };
172 sp<ISurface> sur(new BSurface(mFlinger, this));
Mathias Agopiana1f47b92011-02-15 19:01:06 -0800173 return sur;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800174}
175
Jamie Gennis582270d2011-08-17 18:19:00 -0700176wp<IBinder> Layer::getSurfaceTextureBinder() const
177{
Daniel Lamb2675792012-02-23 14:35:13 -0800178 return mSurfaceTexture->getBufferQueue()->asBinder();
Jamie Gennis582270d2011-08-17 18:19:00 -0700179}
180
Mathias Agopianf9d93272009-06-19 17:00:27 -0700181status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800182 PixelFormat format, uint32_t flags)
183{
Mathias Agopian401c2572009-09-23 19:16:27 -0700184 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800185 PixelFormatInfo info;
186 status_t err = getPixelFormatInfo(format, &info);
Mathias Agopianff615cc2012-02-24 14:58:36 -0800187 if (err) {
188 ALOGE("unsupported pixelformat %d", format);
189 return err;
190 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800191
Mathias Agopian401c2572009-09-23 19:16:27 -0700192 // the display's pixel format
Mathias Agopian1b031492012-06-20 17:51:20 -0700193 // XXX: we shouldn't rely on the DisplayHardware to do this
194 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700195 uint32_t const maxSurfaceDims = min(
196 hw.getMaxTextureSize(), hw.getMaxViewportDims());
197
198 // never allow a surface larger than what our underlying GL implementation
199 // can handle.
200 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
Mathias Agopianff615cc2012-02-24 14:58:36 -0800201 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700202 return BAD_VALUE;
203 }
204
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700205 mFormat = format;
Mathias Agopianeff062c2010-08-25 14:59:15 -0700206
Mathias Agopian3330b202009-10-05 17:07:12 -0700207 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
Glenn Kasten16f04532011-01-19 15:27:27 -0800208 mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700209 mOpaqueLayer = (flags & ISurfaceComposer::eOpaque);
210 mCurrentOpacity = getOpacityForFormat(format);
211
212 mSurfaceTexture->setDefaultBufferSize(w, h);
213 mSurfaceTexture->setDefaultBufferFormat(format);
Daniel Lamb2675792012-02-23 14:35:13 -0800214 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
Mathias Agopianca99fb82010-04-14 16:43:44 -0700215
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800216 return NO_ERROR;
217}
218
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700219Rect Layer::computeBufferCrop() const {
220 // Start with the SurfaceTexture's buffer crop...
221 Rect crop;
222 if (!mCurrentCrop.isEmpty()) {
223 crop = mCurrentCrop;
224 } else if (mActiveBuffer != NULL){
225 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
226 } else {
227 crop = Rect(mTransformedBounds.width(), mTransformedBounds.height());
228 }
229
230 // ... then reduce that in the same proportions as the window crop reduces
231 // the window size.
232 const State& s(drawingState());
Mathias Agopian93ffb862012-05-16 17:07:49 -0700233 if (!s.active.crop.isEmpty()) {
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700234 // Transform the window crop to match the buffer coordinate system,
235 // which means using the inverse of the current transform set on the
236 // SurfaceTexture.
237 uint32_t invTransform = mCurrentTransform;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700238 int winWidth = s.active.w;
239 int winHeight = s.active.h;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700240 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
241 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
242 NATIVE_WINDOW_TRANSFORM_FLIP_H;
Mathias Agopian93ffb862012-05-16 17:07:49 -0700243 winWidth = s.active.h;
244 winHeight = s.active.w;
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700245 }
Mathias Agopian93ffb862012-05-16 17:07:49 -0700246 Rect winCrop = s.active.crop.transform(invTransform,
247 s.active.w, s.active.h);
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700248
249 float xScale = float(crop.width()) / float(winWidth);
250 float yScale = float(crop.height()) / float(winHeight);
Mathias Agopian93ffb862012-05-16 17:07:49 -0700251 crop.left += int(ceilf(float(winCrop.left) * xScale));
252 crop.top += int(ceilf(float(winCrop.top) * yScale));
253 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
254 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
Jamie Gennisf15a83f2012-05-10 20:43:55 -0700255 }
256
257 return crop;
258}
259
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700260void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
Mathias Agopiana350ff92010-08-10 17:14:02 -0700261{
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700262 LayerBaseClient::setGeometry(layer);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700263
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700264 // enable this layer
265 layer.setSkip(false);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700266
267 // we can't do alpha-fade with the hwc HAL
268 const State& s(drawingState());
269 if (s.alpha < 0xFF) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700270 layer.setSkip(true);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700271 }
272
Mathias Agopian29a367b2011-07-12 14:51:45 -0700273 /*
274 * Transformations are applied in this order:
275 * 1) buffer orientation/flip/mirror
276 * 2) state transformation (window manager)
277 * 3) layer orientation (screen orientation)
Mathias Agopiand992db32011-08-18 18:31:00 -0700278 * mTransform is already the composition of (2) and (3)
Mathias Agopian29a367b2011-07-12 14:51:45 -0700279 * (NOTE: the matrices are multiplied in reverse order)
280 */
281
282 const Transform bufferOrientation(mCurrentTransform);
Mathias Agopiand992db32011-08-18 18:31:00 -0700283 const Transform tr(mTransform * bufferOrientation);
Mathias Agopian29a367b2011-07-12 14:51:45 -0700284
285 // this gives us only the "orientation" component of the transform
286 const uint32_t finalTransform = tr.getOrientation();
287
Mathias Agopiana350ff92010-08-10 17:14:02 -0700288 // we can only handle simple transformation
Mathias Agopian29a367b2011-07-12 14:51:45 -0700289 if (finalTransform & Transform::ROT_INVALID) {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700290 layer.setSkip(true);
Mathias Agopiana537c0f2011-08-02 15:51:37 -0700291 } else {
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700292 layer.setTransform(finalTransform);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700293 }
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700294 layer.setCrop(computeBufferCrop());
Mathias Agopiana350ff92010-08-10 17:14:02 -0700295}
296
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700297void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700298 const sp<GraphicBuffer>& buffer(mActiveBuffer);
Mathias Agopian3e8b8532012-05-13 20:42:01 -0700299 // NOTE: buffer can be NULL if the client never drew into this
300 // layer yet, or if we ran out of memory
301 layer.setBuffer(buffer);
Mathias Agopiana350ff92010-08-10 17:14:02 -0700302}
303
Mathias Agopian1b031492012-06-20 17:51:20 -0700304void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800305{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800306 ATRACE_CALL();
307
Mathias Agopiana67932f2011-04-20 14:20:59 -0700308 if (CC_UNLIKELY(mActiveBuffer == 0)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800309 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700310 // in fact never been drawn into. This happens frequently with
311 // SurfaceView because the WindowManager can't know when the client
312 // has drawn the first time.
313
314 // If there is nothing under us, we paint the screen in black, otherwise
315 // we just skip this update.
316
317 // figure out if there is something below us
318 Region under;
Mathias Agopianf7ae69d2011-08-23 12:34:29 -0700319 const SurfaceFlinger::LayerVector& drawingLayers(
320 mFlinger->mDrawingState.layersSortedByZ);
Mathias Agopian179169e2010-05-06 20:21:45 -0700321 const size_t count = drawingLayers.size();
322 for (size_t i=0 ; i<count ; ++i) {
323 const sp<LayerBase>& layer(drawingLayers[i]);
324 if (layer.get() == static_cast<LayerBase const*>(this))
325 break;
326 under.orSelf(layer->visibleRegionScreen);
327 }
328 // if not everything below us is covered, we plug the holes!
329 Region holes(clip.subtract(under));
330 if (!holes.isEmpty()) {
Mathias Agopian1b031492012-06-20 17:51:20 -0700331 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700332 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333 return;
334 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700335
Jamie Gennis9575f602011-10-07 14:51:16 -0700336 if (!isProtected()) {
Jamie Genniscbb1a952012-05-08 17:05:52 -0700337 // TODO: we could be more subtle with isFixedSize()
338 const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
339
340 // Query the texture matrix given our current filtering mode.
341 float textureMatrix[16];
342 mSurfaceTexture->setFilteringEnabled(useFiltering);
343 mSurfaceTexture->getTransformMatrix(textureMatrix);
344
345 // Set things up for texturing.
Mathias Agopianc492e672011-10-18 14:49:27 -0700346 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
347 GLenum filter = GL_NEAREST;
Jamie Genniscbb1a952012-05-08 17:05:52 -0700348 if (useFiltering) {
Mathias Agopianc492e672011-10-18 14:49:27 -0700349 filter = GL_LINEAR;
Jamie Gennis9575f602011-10-07 14:51:16 -0700350 }
Mathias Agopianc492e672011-10-18 14:49:27 -0700351 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
352 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
Jamie Gennis9575f602011-10-07 14:51:16 -0700353 glMatrixMode(GL_TEXTURE);
Jamie Genniscbb1a952012-05-08 17:05:52 -0700354 glLoadMatrixf(textureMatrix);
Jamie Gennis9575f602011-10-07 14:51:16 -0700355 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700356 glDisable(GL_TEXTURE_2D);
Xavier Ducrohet4c4163b2011-10-21 16:18:48 -0700357 glEnable(GL_TEXTURE_EXTERNAL_OES);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700358 } else {
Mathias Agopianc492e672011-10-18 14:49:27 -0700359 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
Jamie Gennis9575f602011-10-07 14:51:16 -0700360 glMatrixMode(GL_TEXTURE);
361 glLoadIdentity();
362 glMatrixMode(GL_MODELVIEW);
Mathias Agopianc492e672011-10-18 14:49:27 -0700363 glDisable(GL_TEXTURE_EXTERNAL_OES);
364 glEnable(GL_TEXTURE_2D);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700365 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700366
Mathias Agopian1b031492012-06-20 17:51:20 -0700367 drawWithOpenGL(hw, clip);
Mathias Agopiana67932f2011-04-20 14:20:59 -0700368
Mathias Agopianc492e672011-10-18 14:49:27 -0700369 glDisable(GL_TEXTURE_EXTERNAL_OES);
370 glDisable(GL_TEXTURE_2D);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800371}
372
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800373// As documented in libhardware header, formats in the range
374// 0x100 - 0x1FF are specific to the HAL implementation, and
375// are known to have no alpha channel
376// TODO: move definition for device-specific range into
377// hardware.h, instead of using hard-coded values here.
378#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
379
Mathias Agopiana67932f2011-04-20 14:20:59 -0700380bool Layer::getOpacityForFormat(uint32_t format)
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800381{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700382 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
383 return true;
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800384 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700385 PixelFormatInfo info;
386 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
387 // in case of error (unknown format), we assume no blending
388 return (err || info.h_alpha <= info.l_alpha);
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800389}
390
Eric Hassoldac45e6b2011-02-10 14:41:26 -0800391
Mathias Agopiana67932f2011-04-20 14:20:59 -0700392bool Layer::isOpaque() const
Mathias Agopiana7f66922010-05-26 22:08:52 -0700393{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700394 // if we don't have a buffer yet, we're translucent regardless of the
395 // layer's opaque flag.
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700396 if (mActiveBuffer == 0) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700397 return false;
Jamie Gennisdb5230f2011-07-28 14:54:07 -0700398 }
Mathias Agopiana67932f2011-04-20 14:20:59 -0700399
400 // if the layer has the opaque flag, then we're always opaque,
401 // otherwise we use the current buffer's format.
402 return mOpaqueLayer || mCurrentOpacity;
Mathias Agopiana7f66922010-05-26 22:08:52 -0700403}
404
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800405bool Layer::isProtected() const
406{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700407 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
Jamie Gennis7a4d0df2011-03-09 17:05:02 -0800408 return (activeBuffer != 0) &&
409 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
410}
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700411
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800412uint32_t Layer::doTransaction(uint32_t flags)
413{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800414 ATRACE_CALL();
415
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416 const Layer::State& front(drawingState());
417 const Layer::State& temp(currentState());
418
Mathias Agopian4824d402012-06-04 18:16:30 -0700419 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
420 (temp.requested.h != front.requested.h);
Mathias Agopiana138f892010-05-21 17:24:35 -0700421
422 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700423 // the size changed, we need to ask our client to request a new buffer
Steve Block9d453682011-12-20 16:23:08 +0000424 ALOGD_IF(DEBUG_RESIZE,
Mathias Agopian419e1962012-05-23 14:34:07 -0700425 "doTransaction: geometry (layer=%p), scalingMode=%d\n"
426 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
427 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
428 " drawing={ 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 this, mCurrentScalingMode,
431 temp.active.w, temp.active.h,
432 temp.active.crop.left,
433 temp.active.crop.top,
434 temp.active.crop.right,
435 temp.active.crop.bottom,
436 temp.active.crop.getWidth(),
437 temp.active.crop.getHeight(),
438 temp.requested.w, temp.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700439 temp.requested.crop.left,
440 temp.requested.crop.top,
441 temp.requested.crop.right,
442 temp.requested.crop.bottom,
443 temp.requested.crop.getWidth(),
444 temp.requested.crop.getHeight(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700445 front.active.w, front.active.h,
446 front.active.crop.left,
447 front.active.crop.top,
448 front.active.crop.right,
449 front.active.crop.bottom,
450 front.active.crop.getWidth(),
451 front.active.crop.getHeight(),
452 front.requested.w, front.requested.h,
Mathias Agopianb30c4152012-05-16 18:21:32 -0700453 front.requested.crop.left,
454 front.requested.crop.top,
455 front.requested.crop.right,
456 front.requested.crop.bottom,
457 front.requested.crop.getWidth(),
Mathias Agopian419e1962012-05-23 14:34:07 -0700458 front.requested.crop.getHeight());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800459
Jamie Gennis2a0d5b62011-09-26 16:54:44 -0700460 // record the new size, form this point on, when the client request
461 // a buffer, it'll get the new size.
Mathias Agopianb30c4152012-05-16 18:21:32 -0700462 mSurfaceTexture->setDefaultBufferSize(
463 temp.requested.w, temp.requested.h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800464 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700465
Mathias Agopian0cd545f2012-06-07 14:18:55 -0700466 if (!isFixedSize()) {
467
468 const bool resizePending = (temp.requested.w != temp.active.w) ||
469 (temp.requested.h != temp.active.h);
470
471 if (resizePending) {
472 // don't let LayerBase::doTransaction update the drawing state
473 // if we have a pending resize, unless we are in fixed-size mode.
474 // the drawing state will be updated only once we receive a buffer
475 // with the correct size.
476 //
477 // in particular, we want to make sure the clip (which is part
478 // of the geometry state) is latched together with the size but is
479 // latched immediately when no resizing is involved.
480
481 flags |= eDontUpdateGeometryState;
482 }
483 }
484
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800485 return LayerBase::doTransaction(flags);
486}
487
Mathias Agopiana138f892010-05-21 17:24:35 -0700488bool Layer::isFixedSize() const {
Mathias Agopian933389f2011-07-18 16:15:08 -0700489 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700490}
491
492bool Layer::isCropped() const {
493 return !mCurrentCrop.isEmpty();
494}
495
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800496// ----------------------------------------------------------------------------
497// pageflip handling...
498// ----------------------------------------------------------------------------
499
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800500bool Layer::onPreComposition() {
501 mRefreshPending = false;
502 return mQueuedFrames > 0;
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800503}
504
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505void Layer::lockPageFlip(bool& recomputeVisibleRegions)
506{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800507 ATRACE_CALL();
508
Jamie Gennis3d8063b2011-06-26 18:27:47 -0700509 if (mQueuedFrames > 0) {
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800510
511 // if we've already called updateTexImage() without going through
512 // a composition step, we have to skip this layer at this point
513 // because we cannot call updateTeximage() without a corresponding
514 // compositionComplete() call.
515 // we'll trigger an update in onPreComposition().
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800516 if (mRefreshPending) {
517 mPostedDirtyRegion.clear();
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800518 return;
519 }
520
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) {
Mathias Agopian4824d402012-06-04 18:16:30 -0700604 // reject this buffer
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700605 return true;
606 }
607 }
608 return false;
609 }
610 };
611
612
613 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
614
615 if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
Mathias Agopiana67932f2011-04-20 14:20:59 -0700616 // something happened!
617 recomputeVisibleRegions = true;
618 return;
619 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700620
Jamie Gennis351a5132011-09-14 18:23:37 -0700621 // update the active buffer
622 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
Mathias Agopiane31564d2012-05-29 20:41:03 -0700623 if (mActiveBuffer == NULL) {
624 // this can only happen if the very first buffer was rejected.
625 return;
626 }
Mathias Agopianda9584d2010-12-13 18:51:59 -0800627
Mathias Agopian4824d402012-06-04 18:16:30 -0700628 mRefreshPending = true;
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700629 mFrameLatencyNeeded = true;
Mathias Agopiane31564d2012-05-29 20:41:03 -0700630 if (oldActiveBuffer == NULL) {
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700631 // the first time we receive a buffer, we need to trigger a
632 // geometry invalidation.
633 mFlinger->invalidateHwcGeometry();
634 }
635
Mathias Agopian702634a2012-05-23 17:50:31 -0700636 Rect crop(mSurfaceTexture->getCurrentCrop());
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700637 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
638 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
Mathias Agopian702634a2012-05-23 17:50:31 -0700639 if ((crop != mCurrentCrop) ||
640 (transform != mCurrentTransform) ||
641 (scalingMode != mCurrentScalingMode))
642 {
643 mCurrentCrop = crop;
644 mCurrentTransform = transform;
645 mCurrentScalingMode = scalingMode;
646 mFlinger->invalidateHwcGeometry();
647 }
648
649 if (oldActiveBuffer != NULL) {
Mathias Agopiane31564d2012-05-29 20:41:03 -0700650 uint32_t bufWidth = mActiveBuffer->getWidth();
651 uint32_t bufHeight = mActiveBuffer->getHeight();
Mathias Agopian702634a2012-05-23 17:50:31 -0700652 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
653 bufHeight != uint32_t(oldActiveBuffer->height)) {
654 mFlinger->invalidateHwcGeometry();
655 }
656 }
657
658 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
659 if (oldOpacity != isOpaque()) {
660 recomputeVisibleRegions = true;
661 }
662
663 // FIXME: mPostedDirtyRegion = dirty & bounds
Mathias Agopian2c8207e2012-05-23 17:56:42 -0700664 const Layer::State& front(drawingState());
Mathias Agopian702634a2012-05-23 17:50:31 -0700665 mPostedDirtyRegion.set(front.active.w, front.active.h);
666
667 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
668 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700669 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800670}
671
672void Layer::unlockPageFlip(
673 const Transform& planeTransform, Region& outDirtyRegion)
674{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800675 ATRACE_CALL();
676
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800677 Region postedRegion(mPostedDirtyRegion);
678 if (!postedRegion.isEmpty()) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800679 mPostedDirtyRegion.clear();
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800680 if (!visibleRegionScreen.isEmpty()) {
681 // The dirty region is given in the layer's coordinate space
682 // transform the dirty region by the surface's transformation
683 // and the global transformation.
684 const Layer::State& s(drawingState());
685 const Transform tr(planeTransform * s.transform);
686 postedRegion = tr.transform(postedRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800687
Mathias Agopian4d143ee2012-02-23 20:05:39 -0800688 // At this point, the dirty region is in screen space.
689 // Make sure it's constrained by the visible region (which
690 // is in screen space as well).
691 postedRegion.andSelf(visibleRegionScreen);
692 outDirtyRegion.orSelf(postedRegion);
693 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694 }
695}
696
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700697void Layer::dump(String8& result, char* buffer, size_t SIZE) const
698{
699 LayerBaseClient::dump(result, buffer, SIZE);
700
Mathias Agopiana67932f2011-04-20 14:20:59 -0700701 sp<const GraphicBuffer> buf0(mActiveBuffer);
702 uint32_t w0=0, h0=0, s0=0, f0=0;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700703 if (buf0 != 0) {
704 w0 = buf0->getWidth();
705 h0 = buf0->getHeight();
706 s0 = buf0->getStride();
Mathias Agopiana67932f2011-04-20 14:20:59 -0700707 f0 = buf0->format;
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700708 }
709 snprintf(buffer, SIZE,
710 " "
Mathias Agopianad795ba2011-08-08 16:02:13 -0700711 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800712 " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
Mathias Agopiana67932f2011-04-20 14:20:59 -0700713 mFormat, w0, h0, s0,f0,
Mathias Agopian99ce5cd2012-01-31 18:24:27 -0800714 getTransformHint(), mQueuedFrames, mRefreshPending);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700715
716 result.append(buffer);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700717
Mathias Agopiana67932f2011-04-20 14:20:59 -0700718 if (mSurfaceTexture != 0) {
719 mSurfaceTexture->dump(result, " ", buffer, SIZE);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700720 }
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700721}
722
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800723void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
724{
725 LayerBaseClient::dumpStats(result, buffer, SIZE);
726 const size_t o = mFrameLatencyOffset;
Mathias Agopian1b031492012-06-20 17:51:20 -0700727 const DisplayHardware& hw(mFlinger->getDefaultDisplayHardware());
Mathias Agopian82d7ab62012-01-19 18:34:40 -0800728 const nsecs_t period = hw.getRefreshPeriod();
729 result.appendFormat("%lld\n", period);
730 for (size_t i=0 ; i<128 ; i++) {
731 const size_t index = (o+i) % 128;
732 const nsecs_t time_app = mFrameStats[index].timestamp;
733 const nsecs_t time_set = mFrameStats[index].set;
734 const nsecs_t time_vsync = mFrameStats[index].vsync;
735 result.appendFormat("%lld\t%lld\t%lld\n",
736 time_app,
737 time_vsync,
738 time_set);
739 }
740 result.append("\n");
741}
742
Mathias Agopian25e66fc2012-01-28 22:31:55 -0800743void Layer::clearStats()
744{
745 LayerBaseClient::clearStats();
746 memset(mFrameStats, 0, sizeof(mFrameStats));
747}
748
Mathias Agopiana67932f2011-04-20 14:20:59 -0700749uint32_t Layer::getEffectiveUsage(uint32_t usage) const
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700750{
Mathias Agopiana67932f2011-04-20 14:20:59 -0700751 // TODO: should we do something special if mSecure is set?
752 if (mProtectedByApp) {
753 // need a hardware-protected path to external video sink
754 usage |= GraphicBuffer::USAGE_PROTECTED;
Jamie Gennis54cc83e2010-11-02 11:51:32 -0700755 }
Jamie Gennis3599bf22011-08-10 11:48:07 -0700756 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
Mathias Agopiana67932f2011-04-20 14:20:59 -0700757 return usage;
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700758}
759
Mathias Agopiana4583642011-08-23 18:03:18 -0700760uint32_t Layer::getTransformHint() const {
761 uint32_t orientation = 0;
762 if (!mFlinger->mDebugDisableTransformHint) {
Jamie Gennis8d91b422011-09-23 15:54:34 -0700763 orientation = getPlaneOrientation();
Mathias Agopiana4583642011-08-23 18:03:18 -0700764 if (orientation & Transform::ROT_INVALID) {
765 orientation = 0;
766 }
767 }
768 return orientation;
769}
770
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800771// ---------------------------------------------------------------------------
772
773
774}; // namespace android