blob: 621b7e3682ce7bf0479e92c81900f095c7651d95 [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 Agopiancbb288b2009-09-07 16:32:45 -070050Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
Mathias Agopiand606de62010-05-10 20:06:11 -070051 const sp<Client>& client, int32_t i)
52 : LayerBaseClient(flinger, display, client, i),
53 lcblk(NULL),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080054 mSecure(false),
Mathias Agopian401c2572009-09-23 19:16:27 -070055 mNeedsBlending(true),
Mathias Agopiand606de62010-05-10 20:06:11 -070056 mNeedsDithering(false),
57 mTextureManager(mFlags),
58 mBufferManager(mTextureManager)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059{
60 // no OpenGL operation is possible here, since we might not be
61 // in the OpenGL thread.
Mathias Agopiand606de62010-05-10 20:06:11 -070062 lcblk = new SharedBufferServer(
Mathias Agopianbb641242010-05-18 17:06:55 -070063 client->ctrlblk, i, mBufferManager.getDefaultBufferCount(),
Mathias Agopiand606de62010-05-10 20:06:11 -070064 getIdentity());
65
66 mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080067}
68
69Layer::~Layer()
70{
Mathias Agopianbb641242010-05-18 17:06:55 -070071 // FIXME: must be called from the main UI thread
72 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
73 mBufferManager.destroy(dpy);
74
Mathias Agopian0aa758d2009-04-22 15:23:34 -070075 // the actual buffers will be destroyed here
Mathias Agopiand606de62010-05-10 20:06:11 -070076 delete lcblk;
77}
78
79// called with SurfaceFlinger::mStateLock as soon as the layer is entered
80// in the purgatory list
81void Layer::onRemoved()
82{
83 // wake up the condition
84 lcblk->setStatus(NO_INIT);
Mathias Agopian48d819a2009-09-10 19:41:18 -070085}
Mathias Agopiancbb288b2009-09-07 16:32:45 -070086
Mathias Agopian076b1cc2009-04-10 14:24:30 -070087sp<LayerBaseClient::Surface> Layer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080088{
89 return mSurface;
90}
91
Mathias Agopian9a112062009-04-17 19:36:26 -070092status_t Layer::ditch()
93{
Mathias Agopianbb641242010-05-18 17:06:55 -070094 // NOTE: Called from the main UI thread
95
Mathias Agopian0aa758d2009-04-22 15:23:34 -070096 // the layer is not on screen anymore. free as much resources as possible
Mathias Agopianf5430db2009-12-11 00:56:10 -080097 mFreezeLock.clear();
Mathias Agopianbb641242010-05-18 17:06:55 -070098
99 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
100 mBufferManager.destroy(dpy);
101 mSurface.clear();
102
103 Mutex::Autolock _l(mLock);
104 mWidth = mHeight = 0;
Mathias Agopian9a112062009-04-17 19:36:26 -0700105 return NO_ERROR;
106}
107
Mathias Agopianf9d93272009-06-19 17:00:27 -0700108status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800109 PixelFormat format, uint32_t flags)
110{
Mathias Agopian401c2572009-09-23 19:16:27 -0700111 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800112 PixelFormatInfo info;
113 status_t err = getPixelFormatInfo(format, &info);
114 if (err) return err;
115
Mathias Agopian401c2572009-09-23 19:16:27 -0700116 // the display's pixel format
117 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700118 uint32_t const maxSurfaceDims = min(
119 hw.getMaxTextureSize(), hw.getMaxViewportDims());
120
121 // never allow a surface larger than what our underlying GL implementation
122 // can handle.
123 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
124 return BAD_VALUE;
125 }
126
Mathias Agopian401c2572009-09-23 19:16:27 -0700127 PixelFormatInfo displayInfo;
128 getPixelFormatInfo(hw.getFormat(), &displayInfo);
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700129 const uint32_t hwFlags = hw.getFlags();
130
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700131 mFormat = format;
Mathias Agopianca99fb82010-04-14 16:43:44 -0700132 mWidth = w;
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700133 mHeight = h;
Mathias Agopian3330b202009-10-05 17:07:12 -0700134 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800135 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
Mathias Agopianca99fb82010-04-14 16:43:44 -0700136
Mathias Agopian401c2572009-09-23 19:16:27 -0700137 // we use the red index
138 int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
139 int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
140 mNeedsDithering = layerRedsize > displayRedSize;
141
Mathias Agopian9a112062009-04-17 19:36:26 -0700142 mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800143 return NO_ERROR;
144}
145
146void Layer::reloadTexture(const Region& dirty)
147{
Mathias Agopiand606de62010-05-10 20:06:11 -0700148 sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
Mathias Agopian8f03b472009-12-10 15:52:29 -0800149 if (buffer == NULL) {
150 // this situation can happen if we ran out of memory for instance.
151 // not much we can do. continue to use whatever texture was bound
152 // to this context.
153 return;
154 }
155
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700156#ifdef EGL_ANDROID_image_native_buffer
Mathias Agopian57720c32009-10-21 16:27:21 -0700157 if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700158 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
159 if (mBufferManager.initEglImage(dpy, buffer) != NO_ERROR) {
160 // not sure what we can do here...
161 mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
162 goto slowpath;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700163 }
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700164 } else
165#endif
166 {
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800167slowpath:
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700168 GGLSurface t;
Mathias Agopian3330b202009-10-05 17:07:12 -0700169 status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
Mathias Agopian0926f502009-05-04 14:17:04 -0700170 LOGE_IF(res, "error %d (%s) locking buffer %p",
171 res, strerror(res), buffer.get());
172 if (res == NO_ERROR) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700173 mBufferManager.loadTexture(dirty, t);
Mathias Agopian0926f502009-05-04 14:17:04 -0700174 buffer->unlock();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700175 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800177}
178
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179void Layer::onDraw(const Region& clip) const
180{
Mathias Agopiand606de62010-05-10 20:06:11 -0700181 Texture tex(mBufferManager.getActiveTexture());
182 if (tex.name == -1LU) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800183 // the texture has not been created yet, this Layer has
Mathias Agopian179169e2010-05-06 20:21:45 -0700184 // in fact never been drawn into. This happens frequently with
185 // SurfaceView because the WindowManager can't know when the client
186 // has drawn the first time.
187
188 // If there is nothing under us, we paint the screen in black, otherwise
189 // we just skip this update.
190
191 // figure out if there is something below us
192 Region under;
193 const SurfaceFlinger::LayerVector& drawingLayers(mFlinger->mDrawingState.layersSortedByZ);
194 const size_t count = drawingLayers.size();
195 for (size_t i=0 ; i<count ; ++i) {
196 const sp<LayerBase>& layer(drawingLayers[i]);
197 if (layer.get() == static_cast<LayerBase const*>(this))
198 break;
199 under.orSelf(layer->visibleRegionScreen);
200 }
201 // if not everything below us is covered, we plug the holes!
202 Region holes(clip.subtract(under));
203 if (!holes.isEmpty()) {
204 clearWithOpenGL(holes);
205 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800206 return;
207 }
Mathias Agopiand606de62010-05-10 20:06:11 -0700208 drawWithOpenGL(clip, tex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800209}
210
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700211
212status_t Layer::setBufferCount(int bufferCount)
213{
Mathias Agopianbb641242010-05-18 17:06:55 -0700214 // Ensures our client doesn't go away while we're accessing
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700215 // the shared area.
216 sp<Client> ourClient(client.promote());
217 if (ourClient == 0) {
218 // oops, the client is already gone
219 return DEAD_OBJECT;
220 }
221
Mathias Agopianbb641242010-05-18 17:06:55 -0700222 // NOTE: lcblk->resize() is protected by an internal lock
223 status_t err = lcblk->resize(bufferCount);
224 if (err == NO_ERROR)
225 mBufferManager.resize(bufferCount);
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700226
227 return err;
228}
229
Mathias Agopian3330b202009-10-05 17:07:12 -0700230sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800231{
Mathias Agopian3330b202009-10-05 17:07:12 -0700232 sp<GraphicBuffer> buffer;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700233
234 // this ensures our client doesn't go away while we're accessing
235 // the shared area.
236 sp<Client> ourClient(client.promote());
237 if (ourClient == 0) {
238 // oops, the client is already gone
239 return buffer;
240 }
241
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700242 /*
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700243 * This is called from the client's Surface::dequeue(). This can happen
244 * at any time, especially while we're in the middle of using the
245 * buffer 'index' as our front buffer.
Mathias Agopianbb641242010-05-18 17:06:55 -0700246 *
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700247 * Make sure the buffer we're resizing is not the front buffer and has been
248 * dequeued. Once this condition is asserted, we are guaranteed that this
249 * buffer cannot become the front buffer under our feet, since we're called
250 * from Surface::dequeue()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251 */
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700252 status_t err = lcblk->assertReallocate(index);
253 LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
Mathias Agopian48d819a2009-09-10 19:41:18 -0700254 if (err != NO_ERROR) {
255 // the surface may have died
256 return buffer;
257 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800258
Mathias Agopian48d819a2009-09-10 19:41:18 -0700259 uint32_t w, h;
260 { // scope for the lock
261 Mutex::Autolock _l(mLock);
262 w = mWidth;
263 h = mHeight;
Mathias Agopiand606de62010-05-10 20:06:11 -0700264 buffer = mBufferManager.detachBuffer(index);
Mathias Agopian48d819a2009-09-10 19:41:18 -0700265 }
266
Mathias Agopian3330b202009-10-05 17:07:12 -0700267 const uint32_t effectiveUsage = getEffectiveUsage(usage);
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700268 if (buffer!=0 && buffer->getStrongCount() == 1) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700269 err = buffer->reallocate(w, h, mFormat, effectiveUsage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700270 } else {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700271 // here we have to reallocate a new buffer because we could have a
272 // client in our process with a reference to it (eg: status bar),
273 // and we can't release the handle under its feet.
274 buffer.clear();
Mathias Agopian3330b202009-10-05 17:07:12 -0700275 buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700276 err = buffer->initCheck();
277 }
278
279 if (err || buffer->handle == 0) {
280 LOGE_IF(err || buffer->handle == 0,
281 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
282 this, index, w, h, strerror(-err));
283 } else {
284 LOGD_IF(DEBUG_RESIZE,
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700285 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
286 this, index, w, h, buffer->handle);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700287 }
288
289 if (err == NO_ERROR && buffer->handle != 0) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700290 Mutex::Autolock _l(mLock);
291 if (mWidth && mHeight) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700292 mBufferManager.attachBuffer(index, buffer);
Mathias Agopian48d819a2009-09-10 19:41:18 -0700293 } else {
294 // oops we got killed while we were allocating the buffer
295 buffer.clear();
296 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700297 }
298 return buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800299}
300
Mathias Agopian3330b202009-10-05 17:07:12 -0700301uint32_t Layer::getEffectiveUsage(uint32_t usage) const
302{
303 /*
304 * buffers used for software rendering, but h/w composition
305 * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
306 *
307 * buffers used for h/w rendering and h/w composition
308 * are allocated with HW_RENDER | HW_TEXTURE
309 *
310 * buffers used with h/w rendering and either NPOT or no egl_image_ext
311 * are allocated with SW_READ_RARELY | HW_RENDER
312 *
313 */
314
315 if (mSecure) {
316 // secure buffer, don't store it into the GPU
317 usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
318 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
319 } else {
320 // it's allowed to modify the usage flags here, but generally
321 // the requested flags should be honored.
Mathias Agopian89141f92010-05-10 20:10:10 -0700322 // request EGLImage for all buffers
323 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
Mathias Agopian3330b202009-10-05 17:07:12 -0700324 }
325 return usage;
326}
327
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800328uint32_t Layer::doTransaction(uint32_t flags)
329{
330 const Layer::State& front(drawingState());
331 const Layer::State& temp(currentState());
332
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700333 if ((front.requested_w != temp.requested_w) ||
334 (front.requested_h != temp.requested_h)) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700335 // the size changed, we need to ask our client to request a new buffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800336 LOGD_IF(DEBUG_RESIZE,
Mathias Agopiand606de62010-05-10 20:06:11 -0700337 "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700338 this,
339 int(temp.requested_w), int(temp.requested_h),
Mathias Agopiand606de62010-05-10 20:06:11 -0700340 int(front.requested_w), int(front.requested_h));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800341
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700342 // we're being resized and there is a freeze display request,
343 // acquire a freeze lock, so that the screen stays put
344 // until we've redrawn at the new size; this is to avoid
345 // glitches upon orientation changes.
346 if (mFlinger->hasFreezeRequest()) {
347 // if the surface is hidden, don't try to acquire the
348 // freeze lock, since hidden surfaces may never redraw
349 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
350 mFreezeLock = mFlinger->getFreezeLock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351 }
352 }
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700353
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700354 // this will make sure LayerBase::doTransaction doesn't update
355 // the drawing state's size
356 Layer::State& editDraw(mDrawingState);
357 editDraw.requested_w = temp.requested_w;
358 editDraw.requested_h = temp.requested_h;
359
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700360 // record the new size, form this point on, when the client request a
361 // buffer, it'll get the new size.
362 setDrawingSize(temp.requested_w, temp.requested_h);
363
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700364 // all buffers need reallocation
365 lcblk->reallocate();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800366 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700367
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800368 if (temp.sequence != front.sequence) {
369 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
370 // this surface is now hidden, so it shouldn't hold a freeze lock
371 // (it may never redraw, which is fine if it is hidden)
372 mFreezeLock.clear();
373 }
374 }
375
376 return LayerBase::doTransaction(flags);
377}
378
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700379void Layer::setDrawingSize(uint32_t w, uint32_t h) {
380 Mutex::Autolock _l(mLock);
381 mWidth = w;
382 mHeight = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800383}
384
385// ----------------------------------------------------------------------------
386// pageflip handling...
387// ----------------------------------------------------------------------------
388
389void Layer::lockPageFlip(bool& recomputeVisibleRegions)
390{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700391 ssize_t buf = lcblk->retireAndLock();
Mathias Agopiand606de62010-05-10 20:06:11 -0700392 if (buf == NOT_ENOUGH_DATA) {
393 // NOTE: This is not an error, it simply means there is nothing to
394 // retire. The buffer is locked because we will use it
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700395 // for composition later in the loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800396 return;
397 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700398
Mathias Agopiand606de62010-05-10 20:06:11 -0700399 if (buf < NO_ERROR) {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700400 LOGE("retireAndLock() buffer index (%d) out of range", buf);
401 mPostedDirtyRegion.clear();
402 return;
403 }
404
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700405 // we retired a buffer, which becomes the new front buffer
Mathias Agopiand606de62010-05-10 20:06:11 -0700406 if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
407 LOGE("retireAndLock() buffer index (%d) out of range", buf);
408 mPostedDirtyRegion.clear();
409 return;
410 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700412 // get the dirty region
Mathias Agopian3330b202009-10-05 17:07:12 -0700413 sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700414 if (newFrontBuffer != NULL) {
415 // compute the posted region
416 const Region dirty(lcblk->getDirtyRegion(buf));
417 mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700418
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700419 // update the layer size and release freeze-lock
420 const Layer::State& front(drawingState());
421 if (newFrontBuffer->getWidth() == front.requested_w &&
422 newFrontBuffer->getHeight() == front.requested_h)
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700423 {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700424 if ((front.w != front.requested_w) ||
425 (front.h != front.requested_h))
426 {
427 // Here we pretend the transaction happened by updating the
428 // current and drawing states. Drawing state is only accessed
429 // in this thread, no need to have it locked
430 Layer::State& editDraw(mDrawingState);
431 editDraw.w = editDraw.requested_w;
432 editDraw.h = editDraw.requested_h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700433
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700434 // We also need to update the current state so that we don't
435 // end-up doing too much work during the next transaction.
436 // NOTE: We actually don't need hold the transaction lock here
437 // because State::w and State::h are only accessed from
438 // this thread
439 Layer::State& editTemp(currentState());
440 editTemp.w = editDraw.w;
441 editTemp.h = editDraw.h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700442
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700443 // recompute visible region
444 recomputeVisibleRegions = true;
445 }
446
447 // we now have the correct size, unfreeze the screen
448 mFreezeLock.clear();
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700449 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700450 } else {
451 // this should not happen unless we ran out of memory while
452 // allocating the buffer. we're hoping that things will get back
453 // to normal the next time the app tries to draw into this buffer.
454 // meanwhile, pretend the screen didn't update.
455 mPostedDirtyRegion.clear();
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700456 }
457
Mathias Agopiane7005012009-10-07 16:44:10 -0700458 if (lcblk->getQueuedCount()) {
459 // signal an event if we have more buffers waiting
460 mFlinger->signalEvent();
461 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800462
Mathias Agopian245e4d72010-04-21 15:24:11 -0700463 /* a buffer was posted, so we need to call reloadTexture(), which
464 * will update our internal data structures (eg: EGLImageKHR or
465 * texture names). we need to do this even if mPostedDirtyRegion is
466 * empty -- it's orthogonal to the fact that a new buffer was posted,
467 * for instance, a degenerate case could be that the user did an empty
468 * update but repainted the buffer with appropriate content (after a
469 * resize for instance).
470 */
471 reloadTexture( mPostedDirtyRegion );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800472}
473
474void Layer::unlockPageFlip(
475 const Transform& planeTransform, Region& outDirtyRegion)
476{
477 Region dirtyRegion(mPostedDirtyRegion);
478 if (!dirtyRegion.isEmpty()) {
479 mPostedDirtyRegion.clear();
480 // The dirty region is given in the layer's coordinate space
481 // transform the dirty region by the surface's transformation
482 // and the global transformation.
483 const Layer::State& s(drawingState());
484 const Transform tr(planeTransform * s.transform);
485 dirtyRegion = tr.transform(dirtyRegion);
486
487 // At this point, the dirty region is in screen space.
488 // Make sure it's constrained by the visible region (which
489 // is in screen space as well).
490 dirtyRegion.andSelf(visibleRegionScreen);
491 outDirtyRegion.orSelf(dirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800492 }
Mathias Agopianc61de172009-11-30 11:15:41 -0800493 if (visibleRegionScreen.isEmpty()) {
494 // an invisible layer should not hold a freeze-lock
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700495 // (because it may never be updated and therefore never release it)
Mathias Agopianc61de172009-11-30 11:15:41 -0800496 mFreezeLock.clear();
497 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800498}
499
500void Layer::finishPageFlip()
501{
Mathias Agopiand606de62010-05-10 20:06:11 -0700502 int buf = mBufferManager.getActiveBufferIndex();
503 status_t err = lcblk->unlock( buf );
504 LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505}
506
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700507
508void Layer::dump(String8& result, char* buffer, size_t SIZE) const
509{
510 LayerBaseClient::dump(result, buffer, SIZE);
511
512 SharedBufferStack::Statistics stats = lcblk->getStats();
513 result.append( lcblk->dump(" ") );
514 sp<const GraphicBuffer> buf0(getBuffer(0));
515 sp<const GraphicBuffer> buf1(getBuffer(1));
516 uint32_t w0=0, h0=0, s0=0;
517 uint32_t w1=0, h1=0, s1=0;
518 if (buf0 != 0) {
519 w0 = buf0->getWidth();
520 h0 = buf0->getHeight();
521 s0 = buf0->getStride();
522 }
523 if (buf1 != 0) {
524 w1 = buf1->getWidth();
525 h1 = buf1->getHeight();
526 s1 = buf1->getStride();
527 }
528 snprintf(buffer, SIZE,
529 " "
530 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
531 " freezeLock=%p, dq-q-time=%u us\n",
532 pixelFormat(),
533 w0, h0, s0, w1, h1, s1,
534 getFreezeLock().get(), stats.totalTime);
535
536 result.append(buffer);
537}
538
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700539// ---------------------------------------------------------------------------
540
Mathias Agopiand606de62010-05-10 20:06:11 -0700541Layer::BufferManager::BufferManager(TextureManager& tm)
Mathias Agopianbb641242010-05-18 17:06:55 -0700542 : mNumBuffers(NUM_BUFFERS), mTextureManager(tm),
543 mActiveBuffer(0), mFailover(false)
Mathias Agopiand606de62010-05-10 20:06:11 -0700544{
545}
546
Mathias Agopianbb641242010-05-18 17:06:55 -0700547Layer::BufferManager::~BufferManager()
548{
549}
550
551status_t Layer::BufferManager::resize(size_t size)
552{
553 Mutex::Autolock _l(mLock);
554 mNumBuffers = size;
555 return NO_ERROR;
Mathias Agopiand606de62010-05-10 20:06:11 -0700556}
557
558// only for debugging
559sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
560 return mBufferData[index].buffer;
561}
562
563status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
564 // TODO: need to validate 'index'
565 mActiveBuffer = index;
566 return NO_ERROR;
567}
568
569size_t Layer::BufferManager::getActiveBufferIndex() const {
570 return mActiveBuffer;
571}
572
573Texture Layer::BufferManager::getActiveTexture() const {
Mathias Agopianbb641242010-05-18 17:06:55 -0700574 Texture res;
575 if (mFailover) {
576 res = mFailoverTexture;
577 } else {
578 static_cast<Image&>(res) = mBufferData[mActiveBuffer].texture;
579 }
580 return res;
Mathias Agopiand606de62010-05-10 20:06:11 -0700581}
582
583sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
Mathias Agopianbb641242010-05-18 17:06:55 -0700584 const size_t activeBuffer = mActiveBuffer;
585 BufferData const * const buffers = mBufferData;
Mathias Agopiand606de62010-05-10 20:06:11 -0700586 Mutex::Autolock _l(mLock);
Mathias Agopianbb641242010-05-18 17:06:55 -0700587 return buffers[activeBuffer].buffer;
Mathias Agopiand606de62010-05-10 20:06:11 -0700588}
589
590sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
591{
Mathias Agopianbb641242010-05-18 17:06:55 -0700592 BufferData* const buffers = mBufferData;
Mathias Agopiand606de62010-05-10 20:06:11 -0700593 sp<GraphicBuffer> buffer;
594 Mutex::Autolock _l(mLock);
Mathias Agopianbb641242010-05-18 17:06:55 -0700595 buffer = buffers[index].buffer;
596 buffers[index].buffer = 0;
Mathias Agopiand606de62010-05-10 20:06:11 -0700597 return buffer;
598}
599
600status_t Layer::BufferManager::attachBuffer(size_t index,
601 const sp<GraphicBuffer>& buffer)
602{
Mathias Agopianbb641242010-05-18 17:06:55 -0700603 BufferData* const buffers = mBufferData;
Mathias Agopiand606de62010-05-10 20:06:11 -0700604 Mutex::Autolock _l(mLock);
Mathias Agopianbb641242010-05-18 17:06:55 -0700605 buffers[index].buffer = buffer;
606 buffers[index].texture.dirty = true;
Mathias Agopiand606de62010-05-10 20:06:11 -0700607 return NO_ERROR;
608}
609
610status_t Layer::BufferManager::destroy(EGLDisplay dpy)
611{
Mathias Agopianbb641242010-05-18 17:06:55 -0700612 BufferData* const buffers = mBufferData;
613 size_t num;
614 { // scope for the lock
615 Mutex::Autolock _l(mLock);
616 num = mNumBuffers;
617 for (size_t i=0 ; i<num ; i++) {
618 buffers[i].buffer = 0;
619 }
620 }
621 for (size_t i=0 ; i<num ; i++) {
622 destroyTexture(&buffers[i].texture, dpy);
Mathias Agopiand606de62010-05-10 20:06:11 -0700623 }
624 destroyTexture(&mFailoverTexture, dpy);
625 return NO_ERROR;
626}
627
628status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
629 const sp<GraphicBuffer>& buffer)
630{
631 size_t index = mActiveBuffer;
Mathias Agopianbb641242010-05-18 17:06:55 -0700632 Image& texture(mBufferData[index].texture);
Mathias Agopiand606de62010-05-10 20:06:11 -0700633 status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
634 // if EGLImage fails, we switch to regular texture mode, and we
635 // free all resources associated with using EGLImages.
636 if (err == NO_ERROR) {
637 mFailover = false;
638 destroyTexture(&mFailoverTexture, dpy);
639 } else {
640 mFailover = true;
Mathias Agopianbb641242010-05-18 17:06:55 -0700641 const size_t num = mNumBuffers;
642 for (size_t i=0 ; i<num ; i++) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700643 destroyTexture(&mBufferData[i].texture, dpy);
644 }
645 }
646 return err;
647}
648
649status_t Layer::BufferManager::loadTexture(
650 const Region& dirty, const GGLSurface& t)
651{
652 return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
653}
654
Mathias Agopianbb641242010-05-18 17:06:55 -0700655status_t Layer::BufferManager::destroyTexture(Image* tex, EGLDisplay dpy)
656{
657 if (tex->name != -1U) {
658 glDeleteTextures(1, &tex->name);
659 tex->name = -1U;
660 }
661 if (tex->image != EGL_NO_IMAGE_KHR) {
662 eglDestroyImageKHR(dpy, tex->image);
663 tex->image = EGL_NO_IMAGE_KHR;
664 }
665 return NO_ERROR;
666}
667
Mathias Agopiand606de62010-05-10 20:06:11 -0700668// ---------------------------------------------------------------------------
669
Mathias Agopian9a112062009-04-17 19:36:26 -0700670Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
671 SurfaceID id, const sp<Layer>& owner)
672 : Surface(flinger, id, owner->getIdentity(), owner)
673{
674}
675
676Layer::SurfaceLayer::~SurfaceLayer()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700677{
678}
679
Mathias Agopian3330b202009-10-05 17:07:12 -0700680sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700681{
Mathias Agopian3330b202009-10-05 17:07:12 -0700682 sp<GraphicBuffer> buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700683 sp<Layer> owner(getOwner());
684 if (owner != 0) {
Mathias Agopianbb641242010-05-18 17:06:55 -0700685 /*
686 * requestBuffer() cannot be called from the main thread
687 * as it could cause a dead-lock, since it may have to wait
688 * on conditions updated my the main thread.
689 */
Mathias Agopiand606de62010-05-10 20:06:11 -0700690 buffer = owner->requestBuffer(index, usage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700691 }
692 return buffer;
693}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800694
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700695status_t Layer::SurfaceLayer::setBufferCount(int bufferCount)
696{
697 status_t err = DEAD_OBJECT;
698 sp<Layer> owner(getOwner());
699 if (owner != 0) {
Mathias Agopianbb641242010-05-18 17:06:55 -0700700 /*
701 * setBufferCount() cannot be called from the main thread
702 * as it could cause a dead-lock, since it may have to wait
703 * on conditions updated my the main thread.
704 */
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700705 err = owner->setBufferCount(bufferCount);
706 }
707 return err;
708}
709
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800710// ---------------------------------------------------------------------------
711
712
713}; // namespace android