blob: 71573ac64e64175b73b0690116d88eb53da56728 [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 Agopian3330b202009-10-05 17:07:12 -0700211sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800212{
Mathias Agopian3330b202009-10-05 17:07:12 -0700213 sp<GraphicBuffer> buffer;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700214
215 // this ensures our client doesn't go away while we're accessing
216 // the shared area.
217 sp<Client> ourClient(client.promote());
218 if (ourClient == 0) {
219 // oops, the client is already gone
220 return buffer;
221 }
222
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700223 /*
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700224 * This is called from the client's Surface::dequeue(). This can happen
225 * at any time, especially while we're in the middle of using the
226 * buffer 'index' as our front buffer.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700227 *
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700228 * Make sure the buffer we're resizing is not the front buffer and has been
229 * dequeued. Once this condition is asserted, we are guaranteed that this
230 * buffer cannot become the front buffer under our feet, since we're called
231 * from Surface::dequeue()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700232 */
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700233 status_t err = lcblk->assertReallocate(index);
234 LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
Mathias Agopian48d819a2009-09-10 19:41:18 -0700235 if (err != NO_ERROR) {
236 // the surface may have died
237 return buffer;
238 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800239
Mathias Agopian48d819a2009-09-10 19:41:18 -0700240 uint32_t w, h;
241 { // scope for the lock
242 Mutex::Autolock _l(mLock);
243 w = mWidth;
244 h = mHeight;
Mathias Agopiand606de62010-05-10 20:06:11 -0700245 buffer = mBufferManager.detachBuffer(index);
Mathias Agopian48d819a2009-09-10 19:41:18 -0700246 }
247
Mathias Agopian3330b202009-10-05 17:07:12 -0700248 const uint32_t effectiveUsage = getEffectiveUsage(usage);
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700249 if (buffer!=0 && buffer->getStrongCount() == 1) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700250 err = buffer->reallocate(w, h, mFormat, effectiveUsage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700251 } else {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700252 // here we have to reallocate a new buffer because we could have a
253 // client in our process with a reference to it (eg: status bar),
254 // and we can't release the handle under its feet.
255 buffer.clear();
Mathias Agopian3330b202009-10-05 17:07:12 -0700256 buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700257 err = buffer->initCheck();
258 }
259
260 if (err || buffer->handle == 0) {
261 LOGE_IF(err || buffer->handle == 0,
262 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
263 this, index, w, h, strerror(-err));
264 } else {
265 LOGD_IF(DEBUG_RESIZE,
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700266 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
267 this, index, w, h, buffer->handle);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700268 }
269
270 if (err == NO_ERROR && buffer->handle != 0) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700271 Mutex::Autolock _l(mLock);
272 if (mWidth && mHeight) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700273 mBufferManager.attachBuffer(index, buffer);
Mathias Agopian48d819a2009-09-10 19:41:18 -0700274 } else {
275 // oops we got killed while we were allocating the buffer
276 buffer.clear();
277 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700278 }
279 return buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800280}
281
Mathias Agopian3330b202009-10-05 17:07:12 -0700282uint32_t Layer::getEffectiveUsage(uint32_t usage) const
283{
284 /*
285 * buffers used for software rendering, but h/w composition
286 * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
287 *
288 * buffers used for h/w rendering and h/w composition
289 * are allocated with HW_RENDER | HW_TEXTURE
290 *
291 * buffers used with h/w rendering and either NPOT or no egl_image_ext
292 * are allocated with SW_READ_RARELY | HW_RENDER
293 *
294 */
295
296 if (mSecure) {
297 // secure buffer, don't store it into the GPU
298 usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
299 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
300 } else {
301 // it's allowed to modify the usage flags here, but generally
302 // the requested flags should be honored.
Mathias Agopian89141f92010-05-10 20:10:10 -0700303 // request EGLImage for all buffers
304 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
Mathias Agopian3330b202009-10-05 17:07:12 -0700305 }
306 return usage;
307}
308
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800309uint32_t Layer::doTransaction(uint32_t flags)
310{
311 const Layer::State& front(drawingState());
312 const Layer::State& temp(currentState());
313
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700314 if ((front.requested_w != temp.requested_w) ||
315 (front.requested_h != temp.requested_h)) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700316 // the size changed, we need to ask our client to request a new buffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317 LOGD_IF(DEBUG_RESIZE,
Mathias Agopiand606de62010-05-10 20:06:11 -0700318 "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700319 this,
320 int(temp.requested_w), int(temp.requested_h),
Mathias Agopiand606de62010-05-10 20:06:11 -0700321 int(front.requested_w), int(front.requested_h));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800322
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700323 // we're being resized and there is a freeze display request,
324 // acquire a freeze lock, so that the screen stays put
325 // until we've redrawn at the new size; this is to avoid
326 // glitches upon orientation changes.
327 if (mFlinger->hasFreezeRequest()) {
328 // if the surface is hidden, don't try to acquire the
329 // freeze lock, since hidden surfaces may never redraw
330 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
331 mFreezeLock = mFlinger->getFreezeLock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800332 }
333 }
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700334
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700335 // this will make sure LayerBase::doTransaction doesn't update
336 // the drawing state's size
337 Layer::State& editDraw(mDrawingState);
338 editDraw.requested_w = temp.requested_w;
339 editDraw.requested_h = temp.requested_h;
340
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700341 // record the new size, form this point on, when the client request a
342 // buffer, it'll get the new size.
343 setDrawingSize(temp.requested_w, temp.requested_h);
344
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700345 // all buffers need reallocation
346 lcblk->reallocate();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800347 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700348
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800349 if (temp.sequence != front.sequence) {
350 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
351 // this surface is now hidden, so it shouldn't hold a freeze lock
352 // (it may never redraw, which is fine if it is hidden)
353 mFreezeLock.clear();
354 }
355 }
356
357 return LayerBase::doTransaction(flags);
358}
359
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700360void Layer::setDrawingSize(uint32_t w, uint32_t h) {
361 Mutex::Autolock _l(mLock);
362 mWidth = w;
363 mHeight = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800364}
365
366// ----------------------------------------------------------------------------
367// pageflip handling...
368// ----------------------------------------------------------------------------
369
370void Layer::lockPageFlip(bool& recomputeVisibleRegions)
371{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700372 ssize_t buf = lcblk->retireAndLock();
Mathias Agopiand606de62010-05-10 20:06:11 -0700373 if (buf == NOT_ENOUGH_DATA) {
374 // NOTE: This is not an error, it simply means there is nothing to
375 // retire. The buffer is locked because we will use it
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700376 // for composition later in the loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800377 return;
378 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700379
Mathias Agopiand606de62010-05-10 20:06:11 -0700380 if (buf < NO_ERROR) {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700381 LOGE("retireAndLock() buffer index (%d) out of range", buf);
382 mPostedDirtyRegion.clear();
383 return;
384 }
385
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700386 // we retired a buffer, which becomes the new front buffer
Mathias Agopiand606de62010-05-10 20:06:11 -0700387 if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
388 LOGE("retireAndLock() buffer index (%d) out of range", buf);
389 mPostedDirtyRegion.clear();
390 return;
391 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800392
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700393 // get the dirty region
Mathias Agopian3330b202009-10-05 17:07:12 -0700394 sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700395 if (newFrontBuffer != NULL) {
396 // compute the posted region
397 const Region dirty(lcblk->getDirtyRegion(buf));
398 mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700399
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700400 // update the layer size and release freeze-lock
401 const Layer::State& front(drawingState());
402 if (newFrontBuffer->getWidth() == front.requested_w &&
403 newFrontBuffer->getHeight() == front.requested_h)
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700404 {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700405 if ((front.w != front.requested_w) ||
406 (front.h != front.requested_h))
407 {
408 // Here we pretend the transaction happened by updating the
409 // current and drawing states. Drawing state is only accessed
410 // in this thread, no need to have it locked
411 Layer::State& editDraw(mDrawingState);
412 editDraw.w = editDraw.requested_w;
413 editDraw.h = editDraw.requested_h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700414
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700415 // We also need to update the current state so that we don't
416 // end-up doing too much work during the next transaction.
417 // NOTE: We actually don't need hold the transaction lock here
418 // because State::w and State::h are only accessed from
419 // this thread
420 Layer::State& editTemp(currentState());
421 editTemp.w = editDraw.w;
422 editTemp.h = editDraw.h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700423
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700424 // recompute visible region
425 recomputeVisibleRegions = true;
426 }
427
428 // we now have the correct size, unfreeze the screen
429 mFreezeLock.clear();
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700430 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700431 } else {
432 // this should not happen unless we ran out of memory while
433 // allocating the buffer. we're hoping that things will get back
434 // to normal the next time the app tries to draw into this buffer.
435 // meanwhile, pretend the screen didn't update.
436 mPostedDirtyRegion.clear();
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700437 }
438
Mathias Agopiane7005012009-10-07 16:44:10 -0700439 if (lcblk->getQueuedCount()) {
440 // signal an event if we have more buffers waiting
441 mFlinger->signalEvent();
442 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443
Mathias Agopian245e4d72010-04-21 15:24:11 -0700444 /* a buffer was posted, so we need to call reloadTexture(), which
445 * will update our internal data structures (eg: EGLImageKHR or
446 * texture names). we need to do this even if mPostedDirtyRegion is
447 * empty -- it's orthogonal to the fact that a new buffer was posted,
448 * for instance, a degenerate case could be that the user did an empty
449 * update but repainted the buffer with appropriate content (after a
450 * resize for instance).
451 */
452 reloadTexture( mPostedDirtyRegion );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800453}
454
455void Layer::unlockPageFlip(
456 const Transform& planeTransform, Region& outDirtyRegion)
457{
458 Region dirtyRegion(mPostedDirtyRegion);
459 if (!dirtyRegion.isEmpty()) {
460 mPostedDirtyRegion.clear();
461 // The dirty region is given in the layer's coordinate space
462 // transform the dirty region by the surface's transformation
463 // and the global transformation.
464 const Layer::State& s(drawingState());
465 const Transform tr(planeTransform * s.transform);
466 dirtyRegion = tr.transform(dirtyRegion);
467
468 // At this point, the dirty region is in screen space.
469 // Make sure it's constrained by the visible region (which
470 // is in screen space as well).
471 dirtyRegion.andSelf(visibleRegionScreen);
472 outDirtyRegion.orSelf(dirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800473 }
Mathias Agopianc61de172009-11-30 11:15:41 -0800474 if (visibleRegionScreen.isEmpty()) {
475 // an invisible layer should not hold a freeze-lock
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700476 // (because it may never be updated and therefore never release it)
Mathias Agopianc61de172009-11-30 11:15:41 -0800477 mFreezeLock.clear();
478 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800479}
480
481void Layer::finishPageFlip()
482{
Mathias Agopiand606de62010-05-10 20:06:11 -0700483 int buf = mBufferManager.getActiveBufferIndex();
484 status_t err = lcblk->unlock( buf );
485 LOGE_IF(err!=NO_ERROR, "layer %p, buffer=%d wasn't locked!", this, buf);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800486}
487
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700488
489void Layer::dump(String8& result, char* buffer, size_t SIZE) const
490{
491 LayerBaseClient::dump(result, buffer, SIZE);
492
493 SharedBufferStack::Statistics stats = lcblk->getStats();
494 result.append( lcblk->dump(" ") );
495 sp<const GraphicBuffer> buf0(getBuffer(0));
496 sp<const GraphicBuffer> buf1(getBuffer(1));
497 uint32_t w0=0, h0=0, s0=0;
498 uint32_t w1=0, h1=0, s1=0;
499 if (buf0 != 0) {
500 w0 = buf0->getWidth();
501 h0 = buf0->getHeight();
502 s0 = buf0->getStride();
503 }
504 if (buf1 != 0) {
505 w1 = buf1->getWidth();
506 h1 = buf1->getHeight();
507 s1 = buf1->getStride();
508 }
509 snprintf(buffer, SIZE,
510 " "
511 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
512 " freezeLock=%p, dq-q-time=%u us\n",
513 pixelFormat(),
514 w0, h0, s0, w1, h1, s1,
515 getFreezeLock().get(), stats.totalTime);
516
517 result.append(buffer);
518}
519
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700520// ---------------------------------------------------------------------------
521
Mathias Agopiand606de62010-05-10 20:06:11 -0700522Layer::BufferManager::BufferManager(TextureManager& tm)
523 : mTextureManager(tm), mActiveBuffer(0), mFailover(false)
524{
525}
526
527size_t Layer::BufferManager::getBufferCount() const {
528 return NUM_BUFFERS;
529}
530
531// only for debugging
532sp<GraphicBuffer> Layer::BufferManager::getBuffer(size_t index) const {
533 return mBufferData[index].buffer;
534}
535
536status_t Layer::BufferManager::setActiveBufferIndex(size_t index) {
537 // TODO: need to validate 'index'
538 mActiveBuffer = index;
539 return NO_ERROR;
540}
541
542size_t Layer::BufferManager::getActiveBufferIndex() const {
543 return mActiveBuffer;
544}
545
546Texture Layer::BufferManager::getActiveTexture() const {
547 return mFailover ? mFailoverTexture : mBufferData[mActiveBuffer].texture;
548}
549
550sp<GraphicBuffer> Layer::BufferManager::getActiveBuffer() const {
551 Mutex::Autolock _l(mLock);
552 return mBufferData[mActiveBuffer].buffer;
553}
554
555sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
556{
557 sp<GraphicBuffer> buffer;
558 Mutex::Autolock _l(mLock);
559 buffer = mBufferData[index].buffer;
560 mBufferData[index].buffer = 0;
561 return buffer;
562}
563
564status_t Layer::BufferManager::attachBuffer(size_t index,
565 const sp<GraphicBuffer>& buffer)
566{
567 Mutex::Autolock _l(mLock);
568 mBufferData[index].buffer = buffer;
569 mBufferData[index].texture.dirty = true;
570 return NO_ERROR;
571}
572
573status_t Layer::BufferManager::destroyTexture(Texture* tex, EGLDisplay dpy)
574{
575 if (tex->name != -1U) {
576 glDeleteTextures(1, &tex->name);
577 tex->name = -1U;
578 }
579 if (tex->image != EGL_NO_IMAGE_KHR) {
580 eglDestroyImageKHR(dpy, tex->image);
581 tex->image = EGL_NO_IMAGE_KHR;
582 }
583 return NO_ERROR;
584}
585
586status_t Layer::BufferManager::destroy(EGLDisplay dpy)
587{
588 Mutex::Autolock _l(mLock);
589 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
590 destroyTexture(&mBufferData[i].texture, dpy);
591 mBufferData[i].buffer = 0;
592 }
593 destroyTexture(&mFailoverTexture, dpy);
594 return NO_ERROR;
595}
596
597status_t Layer::BufferManager::initEglImage(EGLDisplay dpy,
598 const sp<GraphicBuffer>& buffer)
599{
600 size_t index = mActiveBuffer;
601 Texture& texture(mBufferData[index].texture);
602 status_t err = mTextureManager.initEglImage(&texture, dpy, buffer);
603 // if EGLImage fails, we switch to regular texture mode, and we
604 // free all resources associated with using EGLImages.
605 if (err == NO_ERROR) {
606 mFailover = false;
607 destroyTexture(&mFailoverTexture, dpy);
608 } else {
609 mFailover = true;
610 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
611 destroyTexture(&mBufferData[i].texture, dpy);
612 }
613 }
614 return err;
615}
616
617status_t Layer::BufferManager::loadTexture(
618 const Region& dirty, const GGLSurface& t)
619{
620 return mTextureManager.loadTexture(&mFailoverTexture, dirty, t);
621}
622
623// ---------------------------------------------------------------------------
624
Mathias Agopian9a112062009-04-17 19:36:26 -0700625Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
626 SurfaceID id, const sp<Layer>& owner)
627 : Surface(flinger, id, owner->getIdentity(), owner)
628{
629}
630
631Layer::SurfaceLayer::~SurfaceLayer()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700632{
633}
634
Mathias Agopian3330b202009-10-05 17:07:12 -0700635sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700636{
Mathias Agopian3330b202009-10-05 17:07:12 -0700637 sp<GraphicBuffer> buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700638 sp<Layer> owner(getOwner());
639 if (owner != 0) {
Mathias Agopiand606de62010-05-10 20:06:11 -0700640 buffer = owner->requestBuffer(index, usage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700641 }
642 return buffer;
643}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800644
645// ---------------------------------------------------------------------------
646
647
648}; // namespace android