blob: e606f713e07df07ffb0cc5b89b389acd5258e838 [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
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080017#include <stdlib.h>
18#include <stdint.h>
19#include <sys/types.h>
20
21#include <cutils/properties.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070022#include <cutils/native_handle.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080023
24#include <utils/Errors.h>
25#include <utils/Log.h>
26#include <utils/StopWatch.h>
27
Mathias Agopian3330b202009-10-05 17:07:12 -070028#include <ui/GraphicBuffer.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080029#include <ui/PixelFormat.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080030
31#include <surfaceflinger/Surface.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032
33#include "clz.h"
34#include "Layer.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080035#include "SurfaceFlinger.h"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080036#include "DisplayHardware/DisplayHardware.h"
37
38
39#define DEBUG_RESIZE 0
40
41
42namespace android {
43
Mathias Agopianca99fb82010-04-14 16:43:44 -070044template <typename T> inline T min(T a, T b) {
45 return a<b ? a : b;
46}
47
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080048// ---------------------------------------------------------------------------
49
Mathias Agopian96f08192010-06-02 23:28:45 -070050Layer::Layer(SurfaceFlinger* flinger,
51 DisplayID display, const sp<Client>& client)
52 : LayerBaseClient(flinger, display, client),
Mathias Agopian401c2572009-09-23 19:16:27 -070053 mNeedsBlending(true),
Mathias Agopiand606de62010-05-10 20:06:11 -070054 mNeedsDithering(false),
Mathias Agopianb7e930d2010-06-01 15:12:58 -070055 mSecure(false),
Andreas Hubere049a952010-06-25 09:25:19 -070056 mTextureManager(mFlags),
Mathias Agopiana138f892010-05-21 17:24:35 -070057 mBufferManager(mTextureManager),
58 mWidth(0), mHeight(0), mFixedSize(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080060}
61
62Layer::~Layer()
63{
Mathias Agopianbb641242010-05-18 17:06:55 -070064 // FIXME: must be called from the main UI thread
65 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
66 mBufferManager.destroy(dpy);
67
Mathias Agopianb7e930d2010-06-01 15:12:58 -070068 // we can use getUserClientUnsafe here because we know we're
69 // single-threaded at that point.
70 sp<UserClient> ourClient(mUserClientRef.getUserClientUnsafe());
71 if (ourClient != 0) {
72 ourClient->detachLayer(this);
73 }
Mathias Agopiand606de62010-05-10 20:06:11 -070074}
75
Mathias Agopianb7e930d2010-06-01 15:12:58 -070076status_t Layer::setToken(const sp<UserClient>& userClient,
77 SharedClient* sharedClient, int32_t token)
Mathias Agopian96f08192010-06-02 23:28:45 -070078{
Mathias Agopian579b3f82010-06-08 19:54:15 -070079 sp<SharedBufferServer> lcblk = new SharedBufferServer(
Mathias Agopianb7e930d2010-06-01 15:12:58 -070080 sharedClient, token, mBufferManager.getDefaultBufferCount(),
Mathias Agopian96f08192010-06-02 23:28:45 -070081 getIdentity());
82
Mathias Agopianb7e930d2010-06-01 15:12:58 -070083 status_t err = mUserClientRef.setToken(userClient, lcblk, token);
Mathias Agopian579b3f82010-06-08 19:54:15 -070084
85 LOGE_IF(err != NO_ERROR,
86 "ClientRef::setToken(%p, %p, %u) failed",
87 userClient.get(), lcblk.get(), token);
88
89 if (err == NO_ERROR) {
90 // we need to free the buffers associated with this surface
Mathias Agopianb7e930d2010-06-01 15:12:58 -070091 }
92
93 return err;
94}
95
96int32_t Layer::getToken() const
97{
98 return mUserClientRef.getToken();
Mathias Agopian96f08192010-06-02 23:28:45 -070099}
100
Mathias Agopian579b3f82010-06-08 19:54:15 -0700101sp<UserClient> Layer::getClient() const
102{
103 return mUserClientRef.getClient();
104}
105
Mathias Agopiand606de62010-05-10 20:06:11 -0700106// called with SurfaceFlinger::mStateLock as soon as the layer is entered
107// in the purgatory list
108void Layer::onRemoved()
109{
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700110 ClientRef::Access sharedClient(mUserClientRef);
111 SharedBufferServer* lcblk(sharedClient.get());
112 if (lcblk) {
Mathias Agopian96f08192010-06-02 23:28:45 -0700113 // wake up the condition
114 lcblk->setStatus(NO_INIT);
115 }
Mathias Agopian48d819a2009-09-10 19:41:18 -0700116}
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700117
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700118sp<LayerBaseClient::Surface> Layer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800119{
120 return mSurface;
121}
122
Mathias Agopian9a112062009-04-17 19:36:26 -0700123status_t Layer::ditch()
124{
Mathias Agopianbb641242010-05-18 17:06:55 -0700125 // NOTE: Called from the main UI thread
126
Mathias Agopian0aa758d2009-04-22 15:23:34 -0700127 // the layer is not on screen anymore. free as much resources as possible
Mathias Agopianf5430db2009-12-11 00:56:10 -0800128 mFreezeLock.clear();
Mathias Agopianbb641242010-05-18 17:06:55 -0700129
130 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
131 mBufferManager.destroy(dpy);
132 mSurface.clear();
133
134 Mutex::Autolock _l(mLock);
135 mWidth = mHeight = 0;
Mathias Agopian9a112062009-04-17 19:36:26 -0700136 return NO_ERROR;
137}
138
Mathias Agopianf9d93272009-06-19 17:00:27 -0700139status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800140 PixelFormat format, uint32_t flags)
141{
Mathias Agopian401c2572009-09-23 19:16:27 -0700142 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800143 PixelFormatInfo info;
144 status_t err = getPixelFormatInfo(format, &info);
145 if (err) return err;
146
Mathias Agopian401c2572009-09-23 19:16:27 -0700147 // the display's pixel format
148 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700149 uint32_t const maxSurfaceDims = min(
150 hw.getMaxTextureSize(), hw.getMaxViewportDims());
151
152 // never allow a surface larger than what our underlying GL implementation
153 // can handle.
154 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
155 return BAD_VALUE;
156 }
157
Mathias Agopian401c2572009-09-23 19:16:27 -0700158 PixelFormatInfo displayInfo;
159 getPixelFormatInfo(hw.getFormat(), &displayInfo);
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700160 const uint32_t hwFlags = hw.getFlags();
161
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700162 mFormat = format;
Mathias Agopianf955be92010-06-21 15:19:26 -0700163 mReqFormat = format;
Mathias Agopianca99fb82010-04-14 16:43:44 -0700164 mWidth = w;
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700165 mHeight = h;
Mathias Agopian3330b202009-10-05 17:07:12 -0700166 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800167 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
Mathias Agopianca99fb82010-04-14 16:43:44 -0700168
Mathias Agopian401c2572009-09-23 19:16:27 -0700169 // we use the red index
170 int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
171 int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
172 mNeedsDithering = layerRedsize > displayRedSize;
173
Mathias Agopian96f08192010-06-02 23:28:45 -0700174 mSurface = new SurfaceLayer(mFlinger, this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800175 return NO_ERROR;
176}
177
178void Layer::reloadTexture(const Region& dirty)
179{
Mathias Agopiand606de62010-05-10 20:06:11 -0700180 sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
Mathias Agopian8f03b472009-12-10 15:52:29 -0800181 if (buffer == NULL) {
182 // this situation can happen if we ran out of memory for instance.
183 // not much we can do. continue to use whatever texture was bound
184 // to this context.
185 return;
186 }
187
Andreas Hubere049a952010-06-25 09:25:19 -0700188#ifdef EGL_ANDROID_image_native_buffer
189 if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700190 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
191 if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
192 // not sure what we can do here...
Andreas Hubere049a952010-06-25 09:25:19 -0700193 mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
Mathias Agopiand606de62010-05-10 20:06:11 -0700194 goto slowpath;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700195 }
Andreas Hubere049a952010-06-25 09:25:19 -0700196 } else
197#endif
198 {
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800199slowpath:
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700200 GGLSurface t;
Mathias Agopian3330b202009-10-05 17:07:12 -0700201 status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
Mathias Agopian0926f502009-05-04 14:17:04 -0700202 LOGE_IF(res, "error %d (%s) locking buffer %p",
203 res, strerror(res), buffer.get());
204 if (res == NO_ERROR) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700205 mBufferManager.loadTexture(dirty, t);
Mathias Agopian0926f502009-05-04 14:17:04 -0700206 buffer->unlock();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700207 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800208 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209}
210
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800211void Layer::onDraw(const Region& clip) const
212{
Mathias Agopiand606de62010-05-10 20:06:11 -0700213 Texture tex(mBufferManager.getActiveTexture());
214 if (tex.name == -1LU) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800215 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700216 // in fact never been drawn into. This happens frequently with
217 // SurfaceView because the WindowManager can't know when the client
218 // has drawn the first time.
219
220 // If there is nothing under us, we paint the screen in black, otherwise
221 // we just skip this update.
222
223 // figure out if there is something below us
224 Region under;
225 const SurfaceFlinger::LayerVector& drawingLayers(mFlinger->mDrawingState.layersSortedByZ);
226 const size_t count = drawingLayers.size();
227 for (size_t i=0 ; i<count ; ++i) {
228 const sp<LayerBase>& layer(drawingLayers[i]);
229 if (layer.get() == static_cast<LayerBase const*>(this))
230 break;
231 under.orSelf(layer->visibleRegionScreen);
232 }
233 // if not everything below us is covered, we plug the holes!
234 Region holes(clip.subtract(under));
235 if (!holes.isEmpty()) {
Mathias Agopian0a917752010-06-14 21:20:00 -0700236 clearWithOpenGL(holes, 0, 0, 0, 1);
Mathias Agopian179169e2010-05-06 20:21:45 -0700237 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800238 return;
239 }
Mathias Agopiand606de62010-05-10 20:06:11 -0700240 drawWithOpenGL(clip, tex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800241}
242
Mathias Agopiana7f66922010-05-26 22:08:52 -0700243bool Layer::needsFiltering() const
244{
245 if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
246 // NOTE: there is a race here, because mFixedSize is updated in a
247 // binder transaction. however, it doesn't really matter since it is
248 // evaluated each time we draw. To be perfectly correct, this flag
249 // would have to be associated with a buffer.
250 if (mFixedSize)
251 return true;
252 }
253 return LayerBase::needsFiltering();
254}
255
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700256
257status_t Layer::setBufferCount(int bufferCount)
258{
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700259 ClientRef::Access sharedClient(mUserClientRef);
260 SharedBufferServer* lcblk(sharedClient.get());
261 if (!lcblk) {
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700262 // oops, the client is already gone
263 return DEAD_OBJECT;
264 }
265
Mathias Agopianbb641242010-05-18 17:06:55 -0700266 // NOTE: lcblk->resize() is protected by an internal lock
267 status_t err = lcblk->resize(bufferCount);
268 if (err == NO_ERROR)
269 mBufferManager.resize(bufferCount);
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700270
271 return err;
272}
273
Mathias Agopiana138f892010-05-21 17:24:35 -0700274sp<GraphicBuffer> Layer::requestBuffer(int index,
275 uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
276 uint32_t usage)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800277{
Mathias Agopian3330b202009-10-05 17:07:12 -0700278 sp<GraphicBuffer> buffer;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700279
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700280 if (int32_t(reqWidth | reqHeight | reqFormat) < 0)
Mathias Agopiana138f892010-05-21 17:24:35 -0700281 return buffer;
282
283 if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
284 return buffer;
285
Mathias Agopian48d819a2009-09-10 19:41:18 -0700286 // this ensures our client doesn't go away while we're accessing
287 // the shared area.
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700288 ClientRef::Access sharedClient(mUserClientRef);
289 SharedBufferServer* lcblk(sharedClient.get());
290 if (!lcblk) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700291 // oops, the client is already gone
292 return buffer;
293 }
294
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700295 /*
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700296 * This is called from the client's Surface::dequeue(). This can happen
297 * at any time, especially while we're in the middle of using the
298 * buffer 'index' as our front buffer.
Mathias Agopianbb641242010-05-18 17:06:55 -0700299 *
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700300 * Make sure the buffer we're resizing is not the front buffer and has been
301 * dequeued. Once this condition is asserted, we are guaranteed that this
302 * buffer cannot become the front buffer under our feet, since we're called
303 * from Surface::dequeue()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700304 */
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700305 status_t err = lcblk->assertReallocate(index);
306 LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
Mathias Agopian48d819a2009-09-10 19:41:18 -0700307 if (err != NO_ERROR) {
308 // the surface may have died
309 return buffer;
310 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800311
Mathias Agopiana138f892010-05-21 17:24:35 -0700312 uint32_t w, h, f;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700313 { // scope for the lock
314 Mutex::Autolock _l(mLock);
Mathias Agopiana138f892010-05-21 17:24:35 -0700315 const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
316 const bool formatChanged = mReqFormat != reqFormat;
317 mReqWidth = reqWidth;
318 mReqHeight = reqHeight;
319 mReqFormat = reqFormat;
320 mFixedSize = reqWidth && reqHeight;
321 w = reqWidth ? reqWidth : mWidth;
322 h = reqHeight ? reqHeight : mHeight;
323 f = reqFormat ? reqFormat : mFormat;
Mathias Agopiand606de62010-05-10 20:06:11 -0700324 buffer = mBufferManager.detachBuffer(index);
Mathias Agopiana138f892010-05-21 17:24:35 -0700325 if (fixedSizeChanged || formatChanged) {
326 lcblk->reallocateAllExcept(index);
327 }
Mathias Agopian48d819a2009-09-10 19:41:18 -0700328 }
329
Mathias Agopian3330b202009-10-05 17:07:12 -0700330 const uint32_t effectiveUsage = getEffectiveUsage(usage);
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700331 if (buffer!=0 && buffer->getStrongCount() == 1) {
Mathias Agopiana138f892010-05-21 17:24:35 -0700332 err = buffer->reallocate(w, h, f, effectiveUsage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700333 } else {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700334 // here we have to reallocate a new buffer because we could have a
335 // client in our process with a reference to it (eg: status bar),
336 // and we can't release the handle under its feet.
337 buffer.clear();
Mathias Agopiana138f892010-05-21 17:24:35 -0700338 buffer = new GraphicBuffer(w, h, f, effectiveUsage);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700339 err = buffer->initCheck();
340 }
341
342 if (err || buffer->handle == 0) {
343 LOGE_IF(err || buffer->handle == 0,
344 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
345 this, index, w, h, strerror(-err));
346 } else {
347 LOGD_IF(DEBUG_RESIZE,
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700348 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
349 this, index, w, h, buffer->handle);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700350 }
351
352 if (err == NO_ERROR && buffer->handle != 0) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700353 Mutex::Autolock _l(mLock);
Mathias Agopiana138f892010-05-21 17:24:35 -0700354 mBufferManager.attachBuffer(index, buffer);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700355 }
356 return buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800357}
358
Mathias Agopian3330b202009-10-05 17:07:12 -0700359uint32_t Layer::getEffectiveUsage(uint32_t usage) const
360{
361 /*
362 * buffers used for software rendering, but h/w composition
363 * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
364 *
365 * buffers used for h/w rendering and h/w composition
366 * are allocated with HW_RENDER | HW_TEXTURE
367 *
368 * buffers used with h/w rendering and either NPOT or no egl_image_ext
369 * are allocated with SW_READ_RARELY | HW_RENDER
370 *
371 */
372
373 if (mSecure) {
374 // secure buffer, don't store it into the GPU
375 usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
376 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
377 } else {
378 // it's allowed to modify the usage flags here, but generally
379 // the requested flags should be honored.
Mathias Agopian89141f92010-05-10 20:10:10 -0700380 // request EGLImage for all buffers
381 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
Mathias Agopian3330b202009-10-05 17:07:12 -0700382 }
383 return usage;
384}
385
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800386uint32_t Layer::doTransaction(uint32_t flags)
387{
388 const Layer::State& front(drawingState());
389 const Layer::State& temp(currentState());
390
Mathias Agopiana138f892010-05-21 17:24:35 -0700391 const bool sizeChanged = (front.requested_w != temp.requested_w) ||
392 (front.requested_h != temp.requested_h);
393
394 if (sizeChanged) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700395 // the size changed, we need to ask our client to request a new buffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800396 LOGD_IF(DEBUG_RESIZE,
Mathias Agopiana138f892010-05-21 17:24:35 -0700397 "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
398 this,
399 int(temp.requested_w), int(temp.requested_h),
400 int(front.requested_w), int(front.requested_h));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800401
Mathias Agopiana138f892010-05-21 17:24:35 -0700402 if (!isFixedSize()) {
403 // we're being resized and there is a freeze display request,
404 // acquire a freeze lock, so that the screen stays put
405 // until we've redrawn at the new size; this is to avoid
406 // glitches upon orientation changes.
407 if (mFlinger->hasFreezeRequest()) {
408 // if the surface is hidden, don't try to acquire the
409 // freeze lock, since hidden surfaces may never redraw
410 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
411 mFreezeLock = mFlinger->getFreezeLock();
412 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800413 }
Mathias Agopiana138f892010-05-21 17:24:35 -0700414
415 // this will make sure LayerBase::doTransaction doesn't update
416 // the drawing state's size
417 Layer::State& editDraw(mDrawingState);
418 editDraw.requested_w = temp.requested_w;
419 editDraw.requested_h = temp.requested_h;
420
421 // record the new size, form this point on, when the client request
422 // a buffer, it'll get the new size.
423 setBufferSize(temp.requested_w, temp.requested_h);
424
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700425 ClientRef::Access sharedClient(mUserClientRef);
426 SharedBufferServer* lcblk(sharedClient.get());
427 if (lcblk) {
Mathias Agopian96f08192010-06-02 23:28:45 -0700428 // all buffers need reallocation
429 lcblk->reallocateAll();
430 }
Mathias Agopiana138f892010-05-21 17:24:35 -0700431 } else {
432 // record the new size
433 setBufferSize(temp.requested_w, temp.requested_h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800434 }
435 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700436
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437 if (temp.sequence != front.sequence) {
438 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
439 // this surface is now hidden, so it shouldn't hold a freeze lock
440 // (it may never redraw, which is fine if it is hidden)
441 mFreezeLock.clear();
442 }
443 }
444
445 return LayerBase::doTransaction(flags);
446}
447
Mathias Agopiana138f892010-05-21 17:24:35 -0700448void Layer::setBufferSize(uint32_t w, uint32_t h) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700449 Mutex::Autolock _l(mLock);
450 mWidth = w;
451 mHeight = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800452}
453
Mathias Agopiana138f892010-05-21 17:24:35 -0700454bool Layer::isFixedSize() const {
455 Mutex::Autolock _l(mLock);
456 return mFixedSize;
457}
458
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800459// ----------------------------------------------------------------------------
460// pageflip handling...
461// ----------------------------------------------------------------------------
462
463void Layer::lockPageFlip(bool& recomputeVisibleRegions)
464{
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700465 ClientRef::Access sharedClient(mUserClientRef);
466 SharedBufferServer* lcblk(sharedClient.get());
467 if (!lcblk) {
Mathias Agopian96f08192010-06-02 23:28:45 -0700468 // client died
469 recomputeVisibleRegions = true;
470 return;
471 }
472
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700473 ssize_t buf = lcblk->retireAndLock();
Mathias Agopiand606de62010-05-10 20:06:11 -0700474 if (buf == NOT_ENOUGH_DATA) {
475 // NOTE: This is not an error, it simply means there is nothing to
476 // retire. The buffer is locked because we will use it
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700477 // for composition later in the loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800478 return;
479 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700480
Mathias Agopiand606de62010-05-10 20:06:11 -0700481 if (buf < NO_ERROR) {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700482 LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700483 mPostedDirtyRegion.clear();
484 return;
485 }
486
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700487 // we retired a buffer, which becomes the new front buffer
Mathias Agopiand606de62010-05-10 20:06:11 -0700488 if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700489 LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
Mathias Agopiand606de62010-05-10 20:06:11 -0700490 mPostedDirtyRegion.clear();
491 return;
492 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700494 // get the dirty region
Mathias Agopian3330b202009-10-05 17:07:12 -0700495 sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700496 if (newFrontBuffer != NULL) {
497 // compute the posted region
498 const Region dirty(lcblk->getDirtyRegion(buf));
499 mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700500
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700501 // update the layer size and release freeze-lock
502 const Layer::State& front(drawingState());
503 if (newFrontBuffer->getWidth() == front.requested_w &&
504 newFrontBuffer->getHeight() == front.requested_h)
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700505 {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700506 if ((front.w != front.requested_w) ||
507 (front.h != front.requested_h))
508 {
509 // Here we pretend the transaction happened by updating the
510 // current and drawing states. Drawing state is only accessed
511 // in this thread, no need to have it locked
512 Layer::State& editDraw(mDrawingState);
513 editDraw.w = editDraw.requested_w;
514 editDraw.h = editDraw.requested_h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700515
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700516 // We also need to update the current state so that we don't
517 // end-up doing too much work during the next transaction.
518 // NOTE: We actually don't need hold the transaction lock here
519 // because State::w and State::h are only accessed from
520 // this thread
521 Layer::State& editTemp(currentState());
522 editTemp.w = editDraw.w;
523 editTemp.h = editDraw.h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700524
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700525 // recompute visible region
526 recomputeVisibleRegions = true;
527 }
528
529 // we now have the correct size, unfreeze the screen
530 mFreezeLock.clear();
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700531 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700532 } else {
533 // this should not happen unless we ran out of memory while
534 // allocating the buffer. we're hoping that things will get back
535 // to normal the next time the app tries to draw into this buffer.
536 // meanwhile, pretend the screen didn't update.
537 mPostedDirtyRegion.clear();
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700538 }
539
Mathias Agopiane7005012009-10-07 16:44:10 -0700540 if (lcblk->getQueuedCount()) {
541 // signal an event if we have more buffers waiting
542 mFlinger->signalEvent();
543 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800544
Mathias Agopian245e4d72010-04-21 15:24:11 -0700545 /* a buffer was posted, so we need to call reloadTexture(), which
546 * will update our internal data structures (eg: EGLImageKHR or
547 * texture names). we need to do this even if mPostedDirtyRegion is
548 * empty -- it's orthogonal to the fact that a new buffer was posted,
549 * for instance, a degenerate case could be that the user did an empty
550 * update but repainted the buffer with appropriate content (after a
551 * resize for instance).
552 */
553 reloadTexture( mPostedDirtyRegion );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800554}
555
556void Layer::unlockPageFlip(
557 const Transform& planeTransform, Region& outDirtyRegion)
558{
559 Region dirtyRegion(mPostedDirtyRegion);
560 if (!dirtyRegion.isEmpty()) {
561 mPostedDirtyRegion.clear();
562 // The dirty region is given in the layer's coordinate space
563 // transform the dirty region by the surface's transformation
564 // and the global transformation.
565 const Layer::State& s(drawingState());
566 const Transform tr(planeTransform * s.transform);
567 dirtyRegion = tr.transform(dirtyRegion);
568
569 // At this point, the dirty region is in screen space.
570 // Make sure it's constrained by the visible region (which
571 // is in screen space as well).
572 dirtyRegion.andSelf(visibleRegionScreen);
573 outDirtyRegion.orSelf(dirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800574 }
Mathias Agopianc61de172009-11-30 11:15:41 -0800575 if (visibleRegionScreen.isEmpty()) {
576 // an invisible layer should not hold a freeze-lock
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700577 // (because it may never be updated and therefore never release it)
Mathias Agopianc61de172009-11-30 11:15:41 -0800578 mFreezeLock.clear();
579 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800580}
581
582void Layer::finishPageFlip()
583{
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700584 ClientRef::Access sharedClient(mUserClientRef);
585 SharedBufferServer* lcblk(sharedClient.get());
586 if (lcblk) {
Mathias Agopian96f08192010-06-02 23:28:45 -0700587 int buf = mBufferManager.getActiveBufferIndex();
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700588 if (buf >= 0) {
589 status_t err = lcblk->unlock( buf );
590 LOGE_IF(err!=NO_ERROR,
591 "layer %p, buffer=%d wasn't locked!",
592 this, buf);
593 }
Mathias Agopian96f08192010-06-02 23:28:45 -0700594 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800595}
596
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700597
598void Layer::dump(String8& result, char* buffer, size_t SIZE) const
599{
600 LayerBaseClient::dump(result, buffer, SIZE);
601
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700602 ClientRef::Access sharedClient(mUserClientRef);
603 SharedBufferServer* lcblk(sharedClient.get());
604 uint32_t totalTime = 0;
605 if (lcblk) {
606 SharedBufferStack::Statistics stats = lcblk->getStats();
607 totalTime= stats.totalTime;
608 result.append( lcblk->dump(" ") );
609 }
610
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700611 sp<const GraphicBuffer> buf0(getBuffer(0));
612 sp<const GraphicBuffer> buf1(getBuffer(1));
613 uint32_t w0=0, h0=0, s0=0;
614 uint32_t w1=0, h1=0, s1=0;
615 if (buf0 != 0) {
616 w0 = buf0->getWidth();
617 h0 = buf0->getHeight();
618 s0 = buf0->getStride();
619 }
620 if (buf1 != 0) {
621 w1 = buf1->getWidth();
622 h1 = buf1->getHeight();
623 s1 = buf1->getStride();
624 }
625 snprintf(buffer, SIZE,
626 " "
627 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
628 " freezeLock=%p, dq-q-time=%u us\n",
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700629 mFormat, w0, h0, s0, w1, h1, s1,
630 getFreezeLock().get(), totalTime);
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700631
632 result.append(buffer);
633}
634
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700635// ---------------------------------------------------------------------------
636
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700637Layer::ClientRef::ClientRef()
Mathias Agopian579b3f82010-06-08 19:54:15 -0700638 : mControlBlock(0), mToken(-1) {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700639}
640
641Layer::ClientRef::~ClientRef() {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700642}
643
644int32_t Layer::ClientRef::getToken() const {
645 Mutex::Autolock _l(mLock);
646 return mToken;
647}
648
Mathias Agopian579b3f82010-06-08 19:54:15 -0700649sp<UserClient> Layer::ClientRef::getClient() const {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700650 Mutex::Autolock _l(mLock);
Mathias Agopian579b3f82010-06-08 19:54:15 -0700651 return mUserClient.promote();
652}
653
654status_t Layer::ClientRef::setToken(const sp<UserClient>& uc,
655 const sp<SharedBufferServer>& sharedClient, int32_t token) {
656 Mutex::Autolock _l(mLock);
657
658 { // scope for strong mUserClient reference
659 sp<UserClient> userClient(mUserClient.promote());
660 if (mUserClient != 0 && mControlBlock != 0) {
661 mControlBlock->setStatus(NO_INIT);
662 }
663 }
664
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700665 mUserClient = uc;
666 mToken = token;
Mathias Agopian579b3f82010-06-08 19:54:15 -0700667 mControlBlock = sharedClient;
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700668 return NO_ERROR;
669}
670
671sp<UserClient> Layer::ClientRef::getUserClientUnsafe() const {
672 return mUserClient.promote();
673}
674
675// this class gives us access to SharedBufferServer safely
676// it makes sure the UserClient (and its associated shared memory)
677// won't go away while we're accessing it.
678Layer::ClientRef::Access::Access(const ClientRef& ref)
Mathias Agopian579b3f82010-06-08 19:54:15 -0700679 : mControlBlock(0)
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700680{
681 Mutex::Autolock _l(ref.mLock);
682 mUserClientStrongRef = ref.mUserClient.promote();
683 if (mUserClientStrongRef != 0)
Mathias Agopian579b3f82010-06-08 19:54:15 -0700684 mControlBlock = ref.mControlBlock;
685}
686
687Layer::ClientRef::Access::~Access()
688{
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700689}
690
691// ---------------------------------------------------------------------------
692
Mathias Agopiand606de62010-05-10 20:06:11 -0700693Layer::BufferManager::BufferManager(TextureManager& tm)
Mathias Agopianbb641242010-05-18 17:06:55 -0700694 : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700695 mActiveBuffer(-1), mFailover(false)
Mathias Agopiand606de62010-05-10 20:06:11 -0700696{
697}
698
Mathias Agopianbb641242010-05-18 17:06:55 -0700699Layer::BufferManager::~BufferManager()
700{
701}
702
703status_t Layer::BufferManager::resize(size_t size)
704{
705 Mutex::Autolock _l(mLock);
706 mNumBuffers = size;
707 return NO_ERROR;
Mathias Agopiand606de62010-05-10 20:06:11 -0700708}
709
710// only for debugging
711sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
712 return mBufferData[index].buffer;
713}
714
715status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700716 mActiveBuffer = index;
717 return NO_ERROR;
718}
719
720size_t Layer::BufferManager::getActiveBufferIndex() const {
721 return mActiveBuffer;
722}
723
724Texture Layer::BufferManager::getActiveTexture() const {
Mathias Agopianbb641242010-05-18 17:06:55 -0700725 Texture res;
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700726 if (mFailover || mActiveBuffer<0) {
Mathias Agopianbb641242010-05-18 17:06:55 -0700727 res = mFailoverTexture;
728 } else {
729 static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
730 }
731 return res;
Mathias Agopiand606de62010-05-10 20:06:11 -0700732}
733
734sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700735 sp<GraphicBuffer> result;
736 const ssize_t activeBuffer = mActiveBuffer;
737 if (activeBuffer >= 0) {
738 BufferData const * const buffers = mBufferData;
739 Mutex::Autolock _l(mLock);
740 result = buffers[activeBuffer].buffer;
741 }
742 return result;
Mathias Agopiand606de62010-05-10 20:06:11 -0700743}
744
745sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
746{
Mathias Agopianbb641242010-05-18 17:06:55 -0700747 BufferData* const buffers = mBufferData;
Mathias Agopiand606de62010-05-10 20:06:11 -0700748 sp<GraphicBuffer> buffer;
749 Mutex::Autolock _l(mLock);
Mathias Agopianbb641242010-05-18 17:06:55 -0700750 buffer = buffers[index].buffer;
751 buffers[index].buffer = 0;
Mathias Agopiand606de62010-05-10 20:06:11 -0700752 return buffer;
753}
754
755status_t Layer::BufferManager::attachBuffer(size_t index,
756 const sp<GraphicBuffer>& buffer)
757{
Mathias Agopianbb641242010-05-18 17:06:55 -0700758 BufferData* const buffers = mBufferData;
Mathias Agopiand606de62010-05-10 20:06:11 -0700759 Mutex::Autolock _l(mLock);
Mathias Agopianbb641242010-05-18 17:06:55 -0700760 buffers[index].buffer = buffer;
761 buffers[index].texture.dirty = true;
Mathias Agopiand606de62010-05-10 20:06:11 -0700762 return NO_ERROR;
763}
764
765status_t Layer::BufferManager::destroy(EGLDisplay dpy)
766{
Mathias Agopianbb641242010-05-18 17:06:55 -0700767 BufferData* const buffers = mBufferData;
768 size_t num;
769 { // scope for the lock
770 Mutex::Autolock _l(mLock);
771 num = mNumBuffers;
772 for (size_t i=0 ; i<num ; i++) {
773 buffers[i].buffer = 0;
774 }
775 }
776 for (size_t i=0 ; i<num ; i++) {
777 destroyTexture(&buffers[i].texture, dpy);
Mathias Agopiand606de62010-05-10 20:06:11 -0700778 }
779 destroyTexture(&mFailoverTexture, dpy);
780 return NO_ERROR;
781}
782
783status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
784 const sp<GraphicBuffer>& buffer)
785{
Mathias Agopianb7e930d2010-06-01 15:12:58 -0700786 status_t err = NO_INIT;
787 ssize_t index = mActiveBuffer;
788 if (index >= 0) {
Andreas Hubere049a952010-06-25 09:25:19 -0700789 Image& texture(mBufferData[index].texture);
790 err = mTextureManager.initEglImage(&texture, dpy, buffer);
791 // if EGLImage fails, we switch to regular texture mode, and we
792 // free all resources associated with using EGLImages.
793 if (err == NO_ERROR) {
794 mFailover = false;
795 destroyTexture(&mFailoverTexture, dpy);
Mathias Agopian01e44832010-06-24 21:22:43 -0700796 } else {
Andreas Hubere049a952010-06-25 09:25:19 -0700797 mFailover = true;
798 const size_t num = mNumBuffers;
799 for (size_t i=0 ; i<num ; i++) {
800 destroyTexture(&mBufferData[i].texture, dpy);
801 }
Mathias Agopiand606de62010-05-10 20:06:11 -0700802 }
803 }
804 return err;
805}
806
807status_t Layer::BufferManager::loadTexture(
808 const Region& dirty, const GGLSurface& t)
809{
810 return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
811}
812
Mathias Agopianbb641242010-05-18 17:06:55 -0700813status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy)
814{
815 if (tex->name != -1U) {
816 glDeleteTextures(1, &tex->name);
817 tex->name = -1U;
818 }
819 if (tex->image != EGL_NO_IMAGE_KHR) {
820 eglDestroyImageKHR(dpy, tex->image);
821 tex->image = EGL_NO_IMAGE_KHR;
822 }
823 return NO_ERROR;
824}
825
Mathias Agopiand606de62010-05-10 20:06:11 -0700826// ---------------------------------------------------------------------------
827
Mathias Agopian9a112062009-04-17 19:36:26 -0700828Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
Mathias Agopian96f08192010-06-02 23:28:45 -0700829 const sp<Layer>& owner)
830 : Surface(flinger, owner->getIdentity(), owner)
Mathias Agopian9a112062009-04-17 19:36:26 -0700831{
832}
833
834Layer::SurfaceLayer::~SurfaceLayer()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700835{
836}
837
Mathias Agopiana138f892010-05-21 17:24:35 -0700838sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
839 uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700840{
Mathias Agopian3330b202009-10-05 17:07:12 -0700841 sp<GraphicBuffer> buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700842 sp<Layer> owner(getOwner());
843 if (owner != 0) {
Mathias Agopianbb641242010-05-18 17:06:55 -0700844 /*
845 * requestBuffer() cannot be called from the main thread
846 * as it could cause a dead-lock, since it may have to wait
847 * on conditions updated my the main thread.
848 */
Mathias Agopiana138f892010-05-21 17:24:35 -0700849 buffer = owner->requestBuffer(index, w, h, format, usage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700850 }
851 return buffer;
852}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800853
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700854status_t Layer::SurfaceLayer::setBufferCount(int bufferCount)
855{
856 status_t err = DEAD_OBJECT;
857 sp<Layer> owner(getOwner());
858 if (owner != 0) {
Mathias Agopianbb641242010-05-18 17:06:55 -0700859 /*
860 * setBufferCount() cannot be called from the main thread
861 * as it could cause a dead-lock, since it may have to wait
862 * on conditions updated my the main thread.
863 */
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700864 err = owner->setBufferCount(bufferCount);
865 }
866 return err;
867}
868
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800869// ---------------------------------------------------------------------------
870
871
872}; // namespace android