blob: 1fe997d415eabcaf55f7430386e2e71be54487cc [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(
63 client->ctrlblk, i, mBufferManager.getBufferCount(),
64 getIdentity());
65
66 mBufferManager.setActiveBufferIndex( lcblk->getFrontBuffer() );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080067}
68
69Layer::~Layer()
70{
Mathias Agopian0aa758d2009-04-22 15:23:34 -070071 destroy();
72 // the actual buffers will be destroyed here
Mathias Agopiand606de62010-05-10 20:06:11 -070073 delete lcblk;
74}
75
76// called with SurfaceFlinger::mStateLock as soon as the layer is entered
77// in the purgatory list
78void Layer::onRemoved()
79{
80 // wake up the condition
81 lcblk->setStatus(NO_INIT);
Mathias Agopian48d819a2009-09-10 19:41:18 -070082}
Mathias Agopiancbb288b2009-09-07 16:32:45 -070083
Mathias Agopian0aa758d2009-04-22 15:23:34 -070084void Layer::destroy()
85{
Mathias Agopiand606de62010-05-10 20:06:11 -070086 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
87 mBufferManager.destroy(dpy);
88
Mathias Agopian8c0a3d72009-09-23 16:44:00 -070089 mSurface.clear();
Mathias Agopiand606de62010-05-10 20:06:11 -070090
91 Mutex::Autolock _l(mLock);
92 mWidth = mHeight = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080093}
94
Mathias Agopian076b1cc2009-04-10 14:24:30 -070095sp<LayerBaseClient::Surface> Layer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080096{
97 return mSurface;
98}
99
Mathias Agopian9a112062009-04-17 19:36:26 -0700100status_t Layer::ditch()
101{
Mathias Agopian0aa758d2009-04-22 15:23:34 -0700102 // the layer is not on screen anymore. free as much resources as possible
Mathias Agopianf5430db2009-12-11 00:56:10 -0800103 mFreezeLock.clear();
Mathias Agopian8c0a3d72009-09-23 16:44:00 -0700104 destroy();
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{
214 // this ensures our client doesn't go away while we're accessing
215 // 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
222 status_t err;
223
224 // FIXME: resize() below is NOT thread-safe, we need to synchronize
225 // the users of lcblk in our process (ie: retire), and we assume the
226 // client is not mucking with the SharedStack, which is only enforced
227 // by construction, therefore we need to protect ourselves against
228 // buggy and malicious client (as always)
229
230 err = lcblk->resize(bufferCount);
231
232 return err;
233}
234
Mathias Agopian3330b202009-10-05 17:07:12 -0700235sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800236{
Mathias Agopian3330b202009-10-05 17:07:12 -0700237 sp<GraphicBuffer> buffer;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700238
239 // this ensures our client doesn't go away while we're accessing
240 // the shared area.
241 sp<Client> ourClient(client.promote());
242 if (ourClient == 0) {
243 // oops, the client is already gone
244 return buffer;
245 }
246
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700247 /*
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700248 * This is called from the client's Surface::dequeue(). This can happen
249 * at any time, especially while we're in the middle of using the
250 * buffer 'index' as our front buffer.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251 *
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700252 * Make sure the buffer we're resizing is not the front buffer and has been
253 * dequeued. Once this condition is asserted, we are guaranteed that this
254 * buffer cannot become the front buffer under our feet, since we're called
255 * from Surface::dequeue()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700256 */
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700257 status_t err = lcblk->assertReallocate(index);
258 LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
Mathias Agopian48d819a2009-09-10 19:41:18 -0700259 if (err != NO_ERROR) {
260 // the surface may have died
261 return buffer;
262 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800263
Mathias Agopian48d819a2009-09-10 19:41:18 -0700264 uint32_t w, h;
265 { // scope for the lock
266 Mutex::Autolock _l(mLock);
267 w = mWidth;
268 h = mHeight;
Mathias Agopiand606de62010-05-10 20:06:11 -0700269 buffer = mBufferManager.detachBuffer(index);
Mathias Agopian48d819a2009-09-10 19:41:18 -0700270 }
271
Mathias Agopian3330b202009-10-05 17:07:12 -0700272 const uint32_t effectiveUsage = getEffectiveUsage(usage);
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700273 if (buffer!=0 && buffer->getStrongCount() == 1) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700274 err = buffer->reallocate(w, h, mFormat, effectiveUsage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700275 } else {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700276 // here we have to reallocate a new buffer because we could have a
277 // client in our process with a reference to it (eg: status bar),
278 // and we can't release the handle under its feet.
279 buffer.clear();
Mathias Agopian3330b202009-10-05 17:07:12 -0700280 buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700281 err = buffer->initCheck();
282 }
283
284 if (err || buffer->handle == 0) {
285 LOGE_IF(err || buffer->handle == 0,
286 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
287 this, index, w, h, strerror(-err));
288 } else {
289 LOGD_IF(DEBUG_RESIZE,
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700290 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
291 this, index, w, h, buffer->handle);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700292 }
293
294 if (err == NO_ERROR && buffer->handle != 0) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700295 Mutex::Autolock _l(mLock);
296 if (mWidth && mHeight) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700297 mBufferManager.attachBuffer(index, buffer);
Mathias Agopian48d819a2009-09-10 19:41:18 -0700298 } else {
299 // oops we got killed while we were allocating the buffer
300 buffer.clear();
301 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700302 }
303 return buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800304}
305
Mathias Agopian3330b202009-10-05 17:07:12 -0700306uint32_t Layer::getEffectiveUsage(uint32_t usage) const
307{
308 /*
309 * buffers used for software rendering, but h/w composition
310 * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
311 *
312 * buffers used for h/w rendering and h/w composition
313 * are allocated with HW_RENDER | HW_TEXTURE
314 *
315 * buffers used with h/w rendering and either NPOT or no egl_image_ext
316 * are allocated with SW_READ_RARELY | HW_RENDER
317 *
318 */
319
320 if (mSecure) {
321 // secure buffer, don't store it into the GPU
322 usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
323 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
324 } else {
325 // it's allowed to modify the usage flags here, but generally
326 // the requested flags should be honored.
Mathias Agopian89141f92010-05-10 20:10:10 -0700327 // request EGLImage for all buffers
328 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
Mathias Agopian3330b202009-10-05 17:07:12 -0700329 }
330 return usage;
331}
332
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333uint32_t Layer::doTransaction(uint32_t flags)
334{
335 const Layer::State& front(drawingState());
336 const Layer::State& temp(currentState());
337
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700338 if ((front.requested_w != temp.requested_w) ||
339 (front.requested_h != temp.requested_h)) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700340 // the size changed, we need to ask our client to request a new buffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800341 LOGD_IF(DEBUG_RESIZE,
Mathias Agopiand606de62010-05-10 20:06:11 -0700342 "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700343 this,
344 int(temp.requested_w), int(temp.requested_h),
Mathias Agopiand606de62010-05-10 20:06:11 -0700345 int(front.requested_w), int(front.requested_h));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800346
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700347 // we're being resized and there is a freeze display request,
348 // acquire a freeze lock, so that the screen stays put
349 // until we've redrawn at the new size; this is to avoid
350 // glitches upon orientation changes.
351 if (mFlinger->hasFreezeRequest()) {
352 // if the surface is hidden, don't try to acquire the
353 // freeze lock, since hidden surfaces may never redraw
354 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
355 mFreezeLock = mFlinger->getFreezeLock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800356 }
357 }
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700358
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700359 // this will make sure LayerBase::doTransaction doesn't update
360 // the drawing state's size
361 Layer::State& editDraw(mDrawingState);
362 editDraw.requested_w = temp.requested_w;
363 editDraw.requested_h = temp.requested_h;
364
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700365 // record the new size, form this point on, when the client request a
366 // buffer, it'll get the new size.
367 setDrawingSize(temp.requested_w, temp.requested_h);
368
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700369 // all buffers need reallocation
370 lcblk->reallocate();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800371 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700372
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800373 if (temp.sequence != front.sequence) {
374 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
375 // this surface is now hidden, so it shouldn't hold a freeze lock
376 // (it may never redraw, which is fine if it is hidden)
377 mFreezeLock.clear();
378 }
379 }
380
381 return LayerBase::doTransaction(flags);
382}
383
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700384void Layer::setDrawingSize(uint32_t w, uint32_t h) {
385 Mutex::Autolock _l(mLock);
386 mWidth = w;
387 mHeight = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800388}
389
390// ----------------------------------------------------------------------------
391// pageflip handling...
392// ----------------------------------------------------------------------------
393
394void Layer::lockPageFlip(bool& recomputeVisibleRegions)
395{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700396 ssize_t buf = lcblk->retireAndLock();
Mathias Agopiand606de62010-05-10 20:06:11 -0700397 if (buf == NOT_ENOUGH_DATA) {
398 // NOTE: This is not an error, it simply means there is nothing to
399 // retire. The buffer is locked because we will use it
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700400 // for composition later in the loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800401 return;
402 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700403
Mathias Agopiand606de62010-05-10 20:06:11 -0700404 if (buf < NO_ERROR) {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700405 LOGE("retireAndLock() buffer index (%d) out of range", buf);
406 mPostedDirtyRegion.clear();
407 return;
408 }
409
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700410 // we retired a buffer, which becomes the new front buffer
Mathias Agopiand606de62010-05-10 20:06:11 -0700411 if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
412 LOGE("retireAndLock() buffer index (%d) out of range", buf);
413 mPostedDirtyRegion.clear();
414 return;
415 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800416
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700417 // get the dirty region
Mathias Agopian3330b202009-10-05 17:07:12 -0700418 sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700419 if (newFrontBuffer != NULL) {
420 // compute the posted region
421 const Region dirty(lcblk->getDirtyRegion(buf));
422 mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700423
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700424 // update the layer size and release freeze-lock
425 const Layer::State& front(drawingState());
426 if (newFrontBuffer->getWidth() == front.requested_w &&
427 newFrontBuffer->getHeight() == front.requested_h)
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700428 {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700429 if ((front.w != front.requested_w) ||
430 (front.h != front.requested_h))
431 {
432 // Here we pretend the transaction happened by updating the
433 // current and drawing states. Drawing state is only accessed
434 // in this thread, no need to have it locked
435 Layer::State& editDraw(mDrawingState);
436 editDraw.w = editDraw.requested_w;
437 editDraw.h = editDraw.requested_h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700438
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700439 // We also need to update the current state so that we don't
440 // end-up doing too much work during the next transaction.
441 // NOTE: We actually don't need hold the transaction lock here
442 // because State::w and State::h are only accessed from
443 // this thread
444 Layer::State& editTemp(currentState());
445 editTemp.w = editDraw.w;
446 editTemp.h = editDraw.h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700447
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700448 // recompute visible region
449 recomputeVisibleRegions = true;
450 }
451
452 // we now have the correct size, unfreeze the screen
453 mFreezeLock.clear();
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700454 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700455 } else {
456 // this should not happen unless we ran out of memory while
457 // allocating the buffer. we're hoping that things will get back
458 // to normal the next time the app tries to draw into this buffer.
459 // meanwhile, pretend the screen didn't update.
460 mPostedDirtyRegion.clear();
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700461 }
462
Mathias Agopiane7005012009-10-07 16:44:10 -0700463 if (lcblk->getQueuedCount()) {
464 // signal an event if we have more buffers waiting
465 mFlinger->signalEvent();
466 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800467
Mathias Agopian245e4d72010-04-21 15:24:11 -0700468 /* a buffer was posted, so we need to call reloadTexture(), which
469 * will update our internal data structures (eg: EGLImageKHR or
470 * texture names). we need to do this even if mPostedDirtyRegion is
471 * empty -- it's orthogonal to the fact that a new buffer was posted,
472 * for instance, a degenerate case could be that the user did an empty
473 * update but repainted the buffer with appropriate content (after a
474 * resize for instance).
475 */
476 reloadTexture( mPostedDirtyRegion );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800477}
478
479void Layer::unlockPageFlip(
480 const Transform& planeTransform, Region& outDirtyRegion)
481{
482 Region dirtyRegion(mPostedDirtyRegion);
483 if (!dirtyRegion.isEmpty()) {
484 mPostedDirtyRegion.clear();
485 // The dirty region is given in the layer's coordinate space
486 // transform the dirty region by the surface's transformation
487 // and the global transformation.
488 const Layer::State& s(drawingState());
489 const Transform tr(planeTransform * s.transform);
490 dirtyRegion = tr.transform(dirtyRegion);
491
492 // At this point, the dirty region is in screen space.
493 // Make sure it's constrained by the visible region (which
494 // is in screen space as well).
495 dirtyRegion.andSelf(visibleRegionScreen);
496 outDirtyRegion.orSelf(dirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 }
Mathias Agopianc61de172009-11-30 11:15:41 -0800498 if (visibleRegionScreen.isEmpty()) {
499 // an invisible layer should not hold a freeze-lock
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700500 // (because it may never be updated and therefore never release it)
Mathias Agopianc61de172009-11-30 11:15:41 -0800501 mFreezeLock.clear();
502 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800503}
504
505void Layer::finishPageFlip()
506{
Mathias Agopiand606de62010-05-10 20:06:11 -0700507 int buf = mBufferManager.getActiveBufferIndex();
508 status_t err = lcblk->unlock( buf );
509 LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800510}
511
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700512
513void Layer::dump(String8& result, char* buffer, size_t SIZE) const
514{
515 LayerBaseClient::dump(result, buffer, SIZE);
516
517 SharedBufferStack::Statistics stats = lcblk->getStats();
518 result.append( lcblk->dump(" ") );
519 sp<const GraphicBuffer> buf0(getBuffer(0));
520 sp<const GraphicBuffer> buf1(getBuffer(1));
521 uint32_t w0=0, h0=0, s0=0;
522 uint32_t w1=0, h1=0, s1=0;
523 if (buf0 != 0) {
524 w0 = buf0->getWidth();
525 h0 = buf0->getHeight();
526 s0 = buf0->getStride();
527 }
528 if (buf1 != 0) {
529 w1 = buf1->getWidth();
530 h1 = buf1->getHeight();
531 s1 = buf1->getStride();
532 }
533 snprintf(buffer, SIZE,
534 " "
535 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
536 " freezeLock=%p, dq-q-time=%u us\n",
537 pixelFormat(),
538 w0, h0, s0, w1, h1, s1,
539 getFreezeLock().get(), stats.totalTime);
540
541 result.append(buffer);
542}
543
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700544// ---------------------------------------------------------------------------
545
Mathias Agopiand606de62010-05-10 20:06:11 -0700546Layer::BufferManager::BufferManager(TextureManager& tm)
547 : mTextureManager(tm), mActiveBuffer(0), mFailover(false)
548{
549}
550
551size_t Layer::BufferManager::getBufferCount() const {
552 return NUM_BUFFERS;
553}
554
555// only for debugging
556sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
557 return mBufferData[index].buffer;
558}
559
560status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
561 // TODO: need to validate 'index'
562 mActiveBuffer = index;
563 return NO_ERROR;
564}
565
566size_t Layer::BufferManager::getActiveBufferIndex() const {
567 return mActiveBuffer;
568}
569
570Texture Layer::BufferManager::getActiveTexture() const {
571 return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture;
572}
573
574sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
575 Mutex::Autolock _l(mLock);
576 return mBufferData[mActiveBuffer].buffer;
577}
578
579sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
580{
581 sp<GraphicBuffer> buffer;
582 Mutex::Autolock _l(mLock);
583 buffer = mBufferData[index].buffer;
584 mBufferData[index].buffer = 0;
585 return buffer;
586}
587
588status_t Layer::BufferManager::attachBuffer(size_t index,
589 const sp<GraphicBuffer>& buffer)
590{
591 Mutex::Autolock _l(mLock);
592 mBufferData[index].buffer = buffer;
593 mBufferData[index].texture.dirty = true;
594 return NO_ERROR;
595}
596
597status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy)
598{
599 if (tex->name != -1U) {
600 glDeleteTextures(1, &tex->name);
601 tex->name = -1U;
602 }
603 if (tex->image != EGL_NO_IMAGE_KHR) {
604 eglDestroyImageKHR(dpy, tex->image);
605 tex->image = EGL_NO_IMAGE_KHR;
606 }
607 return NO_ERROR;
608}
609
610status_t Layer::BufferManager::destroy(EGLDisplay dpy)
611{
612 Mutex::Autolock _l(mLock);
613 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
614 destroyTexture(&mBufferData[i].texture, dpy);
615 mBufferData[i].buffer = 0;
616 }
617 destroyTexture(&mFailoverTexture, dpy);
618 return NO_ERROR;
619}
620
621status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
622 const sp<GraphicBuffer>& buffer)
623{
624 size_t index = mActiveBuffer;
625 Texture& texture(mBufferData[index].texture);
626 status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
627 // if EGLImage fails, we switch to regular texture mode, and we
628 // free all resources associated with using EGLImages.
629 if (err == NO_ERROR) {
630 mFailover = false;
631 destroyTexture(&mFailoverTexture, dpy);
632 } else {
633 mFailover = true;
634 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
635 destroyTexture(&mBufferData[i].texture, dpy);
636 }
637 }
638 return err;
639}
640
641status_t Layer::BufferManager::loadTexture(
642 const Region& dirty, const GGLSurface& t)
643{
644 return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
645}
646
647// ---------------------------------------------------------------------------
648
Mathias Agopian9a112062009-04-17 19:36:26 -0700649Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
650 SurfaceID id, const sp<Layer>& owner)
651 : Surface(flinger, id, owner->getIdentity(), owner)
652{
653}
654
655Layer::SurfaceLayer::~SurfaceLayer()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700656{
657}
658
Mathias Agopian3330b202009-10-05 17:07:12 -0700659sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700660{
Mathias Agopian3330b202009-10-05 17:07:12 -0700661 sp<GraphicBuffer> buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700662 sp<Layer> owner(getOwner());
663 if (owner != 0) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700664 buffer = owner->requestBuffer(index, usage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700665 }
666 return buffer;
667}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800668
Mathias Agopianb5b7f262010-05-07 15:58:44 -0700669status_t Layer::SurfaceLayer::setBufferCount(int bufferCount)
670{
671 status_t err = DEAD_OBJECT;
672 sp<Layer> owner(getOwner());
673 if (owner != 0) {
674 err = owner->setBufferCount(bufferCount);
675 }
676 return err;
677}
678
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800679// ---------------------------------------------------------------------------
680
681
682}; // namespace android