blob: 566428f52ae6af71d45c0aa80e79dbdb158757f1 [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,
51 const sp<Client>& c, int32_t i)
Mathias Agopian48d819a2009-09-10 19:41:18 -070052 : LayerBaseClient(flinger, display, c, i),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080053 mSecure(false),
Mathias Agopiana4b740e2009-10-05 18:20:39 -070054 mNoEGLImageForSwBuffers(false),
Mathias Agopian401c2572009-09-23 19:16:27 -070055 mNeedsBlending(true),
56 mNeedsDithering(false)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080057{
58 // no OpenGL operation is possible here, since we might not be
59 // in the OpenGL thread.
Mathias Agopiancbb288b2009-09-07 16:32:45 -070060 mFrontBufferIndex = lcblk->getFrontBuffer();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080061}
62
63Layer::~Layer()
64{
Mathias Agopian0aa758d2009-04-22 15:23:34 -070065 destroy();
66 // the actual buffers will be destroyed here
Mathias Agopian48d819a2009-09-10 19:41:18 -070067}
Mathias Agopiancbb288b2009-09-07 16:32:45 -070068
Mathias Agopian0aa758d2009-04-22 15:23:34 -070069void Layer::destroy()
70{
Mathias Agopiancbb288b2009-09-07 16:32:45 -070071 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
Mathias Agopian076b1cc2009-04-10 14:24:30 -070072 if (mTextures[i].name != -1U) {
Mathias Agopian550b79f2009-04-22 15:49:28 -070073 glDeleteTextures(1, &mTextures[i].name);
Mathias Agopian0aa758d2009-04-22 15:23:34 -070074 mTextures[i].name = -1U;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070075 }
76 if (mTextures[i].image != EGL_NO_IMAGE_KHR) {
77 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
78 eglDestroyImageKHR(dpy, mTextures[i].image);
Mathias Agopian0aa758d2009-04-22 15:23:34 -070079 mTextures[i].image = EGL_NO_IMAGE_KHR;
Mathias Agopian076b1cc2009-04-10 14:24:30 -070080 }
Mathias Agopian48d819a2009-09-10 19:41:18 -070081 Mutex::Autolock _l(mLock);
Mathias Agopiancbb288b2009-09-07 16:32:45 -070082 mBuffers[i].clear();
Mathias Agopian48d819a2009-09-10 19:41:18 -070083 mWidth = mHeight = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080084 }
Mathias Agopian8c0a3d72009-09-23 16:44:00 -070085 mSurface.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080086}
87
Mathias Agopian076b1cc2009-04-10 14:24:30 -070088sp<LayerBaseClient::Surface> Layer::createSurface() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080089{
90 return mSurface;
91}
92
Mathias Agopian9a112062009-04-17 19:36:26 -070093status_t Layer::ditch()
94{
Mathias Agopian0aa758d2009-04-22 15:23:34 -070095 // the layer is not on screen anymore. free as much resources as possible
Mathias Agopianf5430db2009-12-11 00:56:10 -080096 mFreezeLock.clear();
Mathias Agopian8c0a3d72009-09-23 16:44:00 -070097 destroy();
Mathias Agopian9a112062009-04-17 19:36:26 -070098 return NO_ERROR;
99}
100
Mathias Agopianf9d93272009-06-19 17:00:27 -0700101status_t Layer::setBuffers( uint32_t w, uint32_t h,
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800102 PixelFormat format, uint32_t flags)
103{
Mathias Agopian401c2572009-09-23 19:16:27 -0700104 // this surfaces pixel format
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800105 PixelFormatInfo info;
106 status_t err = getPixelFormatInfo(format, &info);
107 if (err) return err;
108
Mathias Agopian401c2572009-09-23 19:16:27 -0700109 // the display's pixel format
110 const DisplayHardware& hw(graphicPlane(0).displayHardware());
Mathias Agopianca99fb82010-04-14 16:43:44 -0700111 uint32_t const maxSurfaceDims = min(
112 hw.getMaxTextureSize(), hw.getMaxViewportDims());
113
114 // never allow a surface larger than what our underlying GL implementation
115 // can handle.
116 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
117 return BAD_VALUE;
118 }
119
Mathias Agopian401c2572009-09-23 19:16:27 -0700120 PixelFormatInfo displayInfo;
121 getPixelFormatInfo(hw.getFormat(), &displayInfo);
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700122 const uint32_t hwFlags = hw.getFlags();
123
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700124 mFormat = format;
Mathias Agopianca99fb82010-04-14 16:43:44 -0700125 mWidth = w;
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700126 mHeight = h;
Mathias Agopian3330b202009-10-05 17:07:12 -0700127 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800128 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700129 mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS);
Mathias Agopianca99fb82010-04-14 16:43:44 -0700130
Mathias Agopian401c2572009-09-23 19:16:27 -0700131 // we use the red index
132 int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
133 int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
134 mNeedsDithering = layerRedsize > displayRedSize;
135
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700136 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700137 mBuffers[i] = new GraphicBuffer();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800138 }
Mathias Agopian9a112062009-04-17 19:36:26 -0700139 mSurface = new SurfaceLayer(mFlinger, clientIndex(), this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800140 return NO_ERROR;
141}
142
143void Layer::reloadTexture(const Region& dirty)
144{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700145 Mutex::Autolock _l(mLock);
Mathias Agopian9ec430a2009-10-06 19:00:57 -0700146 sp<GraphicBuffer> buffer(getFrontBufferLocked());
Mathias Agopian8f03b472009-12-10 15:52:29 -0800147 if (buffer == NULL) {
148 // this situation can happen if we ran out of memory for instance.
149 // not much we can do. continue to use whatever texture was bound
150 // to this context.
151 return;
152 }
153
154 const int index = mFrontBufferIndex;
Mathias Agopian57720c32009-10-21 16:27:21 -0700155
156 // create the new texture name if needed
157 if (UNLIKELY(mTextures[index].name == -1U)) {
158 mTextures[index].name = createTexture();
159 mTextures[index].width = 0;
160 mTextures[index].height = 0;
161 }
162
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700163#ifdef EGL_ANDROID_image_native_buffer
Mathias Agopian57720c32009-10-21 16:27:21 -0700164 if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
165 if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
166 if (mTextures[index].dirty) {
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800167 if (initializeEglImage(buffer, &mTextures[index]) != NO_ERROR) {
168 // not sure what we can do here...
169 mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
170 goto slowpath;
171 }
Mathias Agopian57720c32009-10-21 16:27:21 -0700172 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700173 } else {
Mathias Agopian57720c32009-10-21 16:27:21 -0700174 if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
175 mHybridBuffer->height != buffer->height)) {
176 mHybridBuffer.clear();
177 mHybridBuffer = new GraphicBuffer(
178 buffer->width, buffer->height, buffer->format,
179 GraphicBuffer::USAGE_SW_WRITE_OFTEN |
180 GraphicBuffer::USAGE_HW_TEXTURE);
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800181 if (initializeEglImage(
182 mHybridBuffer, &mTextures[0]) != NO_ERROR) {
183 // not sure what we can do here...
184 mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
185 mHybridBuffer.clear();
186 goto slowpath;
187 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700188 }
189
Mathias Agopian57720c32009-10-21 16:27:21 -0700190 GGLSurface t;
191 status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
192 LOGE_IF(res, "error %d (%s) locking buffer %p",
193 res, strerror(res), buffer.get());
194 if (res == NO_ERROR) {
195 Texture* const texture(&mTextures[0]);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700196
Mathias Agopian57720c32009-10-21 16:27:21 -0700197 glBindTexture(GL_TEXTURE_2D, texture->name);
198
199 sp<GraphicBuffer> buf(mHybridBuffer);
200 void* vaddr;
201 res = buf->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN, &vaddr);
202 if (res == NO_ERROR) {
203 int bpp = 0;
204 switch (t.format) {
Mathias Agopian54ed4f62010-02-16 17:33:37 -0800205 case HAL_PIXEL_FORMAT_RGB_565:
206 case HAL_PIXEL_FORMAT_RGBA_4444:
Mathias Agopian57720c32009-10-21 16:27:21 -0700207 bpp = 2;
208 break;
Mathias Agopian54ed4f62010-02-16 17:33:37 -0800209 case HAL_PIXEL_FORMAT_RGBA_8888:
210 case HAL_PIXEL_FORMAT_RGBX_8888:
Mathias Agopian57720c32009-10-21 16:27:21 -0700211 bpp = 4;
212 break;
Mathias Agopian57720c32009-10-21 16:27:21 -0700213 default:
Mathias Agopian54ed4f62010-02-16 17:33:37 -0800214 if (isSupportedYuvFormat(t.format)) {
215 // just show the Y plane of YUV buffers
216 bpp = 1;
217 break;
218 }
Mathias Agopian57720c32009-10-21 16:27:21 -0700219 // oops, we don't handle this format!
220 LOGE("layer %p, texture=%d, using format %d, which is not "
221 "supported by the GL", this, texture->name, t.format);
222 }
223 if (bpp) {
224 const Rect bounds(dirty.getBounds());
225 size_t src_stride = t.stride;
226 size_t dst_stride = buf->stride;
227 if (src_stride == dst_stride &&
228 bounds.width() == t.width &&
229 bounds.height() == t.height)
230 {
231 memcpy(vaddr, t.data, t.height * t.stride * bpp);
232 } else {
233 GLubyte const * src = t.data +
234 (bounds.left + bounds.top * src_stride) * bpp;
235 GLubyte * dst = (GLubyte *)vaddr +
236 (bounds.left + bounds.top * dst_stride) * bpp;
237 const size_t length = bounds.width() * bpp;
238 size_t h = bounds.height();
239 src_stride *= bpp;
240 dst_stride *= bpp;
241 while (h--) {
242 memcpy(dst, src, length);
243 dst += dst_stride;
244 src += src_stride;
245 }
246 }
247 }
248 buf->unlock();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700249 }
Mathias Agopian57720c32009-10-21 16:27:21 -0700250 buffer->unlock();
251 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700252 }
Mathias Agopian54ba51d2009-10-26 20:12:37 -0700253 } else
254#endif
255 {
Mathias Agopianfcfeb4b2010-03-08 11:14:20 -0800256slowpath:
Mathias Agopian57720c32009-10-21 16:27:21 -0700257 for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700258 mTextures[i].image = EGL_NO_IMAGE_KHR;
Mathias Agopian57720c32009-10-21 16:27:21 -0700259 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700260 GGLSurface t;
Mathias Agopian3330b202009-10-05 17:07:12 -0700261 status_t res = buffer->lock(&t, GRALLOC_USAGE_SW_READ_OFTEN);
Mathias Agopian0926f502009-05-04 14:17:04 -0700262 LOGE_IF(res, "error %d (%s) locking buffer %p",
263 res, strerror(res), buffer.get());
264 if (res == NO_ERROR) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700265 loadTexture(&mTextures[0], dirty, t);
Mathias Agopian0926f502009-05-04 14:17:04 -0700266 buffer->unlock();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700267 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800268 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800269}
270
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800271void Layer::onDraw(const Region& clip) const
272{
Mathias Agopian3330b202009-10-05 17:07:12 -0700273 int index = mFrontBufferIndex;
274 if (mTextures[index].image == EGL_NO_IMAGE_KHR)
275 index = 0;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700276 GLuint textureName = mTextures[index].name;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700277 if (UNLIKELY(textureName == -1LU)) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800278 // the texture has not been created yet, this Layer has
279 // in fact never been drawn into. this happens frequently with
280 // SurfaceView.
281 clearWithOpenGL(clip);
282 return;
283 }
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700284 drawWithOpenGL(clip, mTextures[index]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800285}
286
Mathias Agopian3330b202009-10-05 17:07:12 -0700287sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800288{
Mathias Agopian3330b202009-10-05 17:07:12 -0700289 sp<GraphicBuffer> buffer;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700290
291 // this ensures our client doesn't go away while we're accessing
292 // the shared area.
293 sp<Client> ourClient(client.promote());
294 if (ourClient == 0) {
295 // oops, the client is already gone
296 return buffer;
297 }
298
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700299 /*
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700300 * This is called from the client's Surface::dequeue(). This can happen
301 * at any time, especially while we're in the middle of using the
302 * buffer 'index' as our front buffer.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700303 *
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700304 * Make sure the buffer we're resizing is not the front buffer and has been
305 * dequeued. Once this condition is asserted, we are guaranteed that this
306 * buffer cannot become the front buffer under our feet, since we're called
307 * from Surface::dequeue()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700308 */
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700309 status_t err = lcblk->assertReallocate(index);
310 LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
Mathias Agopian48d819a2009-09-10 19:41:18 -0700311 if (err != NO_ERROR) {
312 // the surface may have died
313 return buffer;
314 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800315
Mathias Agopian48d819a2009-09-10 19:41:18 -0700316 uint32_t w, h;
317 { // scope for the lock
318 Mutex::Autolock _l(mLock);
319 w = mWidth;
320 h = mHeight;
321 buffer = mBuffers[index];
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700322
323 // destroy() could have been called before we get here, we log it
324 // because it's uncommon, and the code below should handle it
325 LOGW_IF(buffer==0,
326 "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
327 index, w, h);
328
Mathias Agopian48d819a2009-09-10 19:41:18 -0700329 mBuffers[index].clear();
330 }
331
Mathias Agopian3330b202009-10-05 17:07:12 -0700332 const uint32_t effectiveUsage = getEffectiveUsage(usage);
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700333 if (buffer!=0 && buffer->getStrongCount() == 1) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700334 err = buffer->reallocate(w, h, mFormat, effectiveUsage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700335 } else {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700336 // here we have to reallocate a new buffer because we could have a
337 // client in our process with a reference to it (eg: status bar),
338 // and we can't release the handle under its feet.
339 buffer.clear();
Mathias Agopian3330b202009-10-05 17:07:12 -0700340 buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700341 err = buffer->initCheck();
342 }
343
344 if (err || buffer->handle == 0) {
345 LOGE_IF(err || buffer->handle == 0,
346 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
347 this, index, w, h, strerror(-err));
348 } else {
349 LOGD_IF(DEBUG_RESIZE,
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700350 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
351 this, index, w, h, buffer->handle);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700352 }
353
354 if (err == NO_ERROR && buffer->handle != 0) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700355 Mutex::Autolock _l(mLock);
356 if (mWidth && mHeight) {
357 // and we have new buffer
358 mBuffers[index] = buffer;
359 // texture is now dirty...
360 mTextures[index].dirty = true;
361 } else {
362 // oops we got killed while we were allocating the buffer
363 buffer.clear();
364 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700365 }
366 return buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800367}
368
Mathias Agopian3330b202009-10-05 17:07:12 -0700369uint32_t Layer::getEffectiveUsage(uint32_t usage) const
370{
371 /*
372 * buffers used for software rendering, but h/w composition
373 * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
374 *
375 * buffers used for h/w rendering and h/w composition
376 * are allocated with HW_RENDER | HW_TEXTURE
377 *
378 * buffers used with h/w rendering and either NPOT or no egl_image_ext
379 * are allocated with SW_READ_RARELY | HW_RENDER
380 *
381 */
382
383 if (mSecure) {
384 // secure buffer, don't store it into the GPU
385 usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
386 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
387 } else {
388 // it's allowed to modify the usage flags here, but generally
389 // the requested flags should be honored.
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700390 if (mNoEGLImageForSwBuffers) {
391 if (usage & GraphicBuffer::USAGE_HW_MASK) {
392 // request EGLImage for h/w buffers only
393 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
394 }
395 } else {
396 // request EGLImage for all buffers
397 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
398 }
Mathias Agopian3330b202009-10-05 17:07:12 -0700399 }
400 return usage;
401}
402
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800403uint32_t Layer::doTransaction(uint32_t flags)
404{
405 const Layer::State& front(drawingState());
406 const Layer::State& temp(currentState());
407
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700408 if ((front.requested_w != temp.requested_w) ||
409 (front.requested_h != temp.requested_h)) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700410 // the size changed, we need to ask our client to request a new buffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800411 LOGD_IF(DEBUG_RESIZE,
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700412 "resize (layer=%p), requested (%dx%d), "
413 "drawing (%d,%d), (%dx%d), (%dx%d)",
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700414 this,
415 int(temp.requested_w), int(temp.requested_h),
416 int(front.requested_w), int(front.requested_h),
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700417 int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
418 int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800419
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700420 // we're being resized and there is a freeze display request,
421 // acquire a freeze lock, so that the screen stays put
422 // until we've redrawn at the new size; this is to avoid
423 // glitches upon orientation changes.
424 if (mFlinger->hasFreezeRequest()) {
425 // if the surface is hidden, don't try to acquire the
426 // freeze lock, since hidden surfaces may never redraw
427 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
428 mFreezeLock = mFlinger->getFreezeLock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800429 }
430 }
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700431
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700432 // this will make sure LayerBase::doTransaction doesn't update
433 // the drawing state's size
434 Layer::State& editDraw(mDrawingState);
435 editDraw.requested_w = temp.requested_w;
436 editDraw.requested_h = temp.requested_h;
437
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700438 // record the new size, form this point on, when the client request a
439 // buffer, it'll get the new size.
440 setDrawingSize(temp.requested_w, temp.requested_h);
441
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700442 // all buffers need reallocation
443 lcblk->reallocate();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800444 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700445
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800446 if (temp.sequence != front.sequence) {
447 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
448 // this surface is now hidden, so it shouldn't hold a freeze lock
449 // (it may never redraw, which is fine if it is hidden)
450 mFreezeLock.clear();
451 }
452 }
453
454 return LayerBase::doTransaction(flags);
455}
456
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700457void Layer::setDrawingSize(uint32_t w, uint32_t h) {
458 Mutex::Autolock _l(mLock);
459 mWidth = w;
460 mHeight = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800461}
462
463// ----------------------------------------------------------------------------
464// pageflip handling...
465// ----------------------------------------------------------------------------
466
467void Layer::lockPageFlip(bool& recomputeVisibleRegions)
468{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700469 ssize_t buf = lcblk->retireAndLock();
470 if (buf < NO_ERROR) {
471 //LOGW("nothing to retire (%s)", strerror(-buf));
472 // NOTE: here the buffer is locked because we will used
473 // for composition later in the loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800474 return;
475 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700476
477 // ouch, this really should never happen
478 if (uint32_t(buf)>=NUM_BUFFERS) {
479 LOGE("retireAndLock() buffer index (%d) out of range", buf);
480 mPostedDirtyRegion.clear();
481 return;
482 }
483
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700484 // we retired a buffer, which becomes the new front buffer
485 mFrontBufferIndex = buf;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800486
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700487 // get the dirty region
Mathias Agopian3330b202009-10-05 17:07:12 -0700488 sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700489 if (newFrontBuffer != NULL) {
490 // compute the posted region
491 const Region dirty(lcblk->getDirtyRegion(buf));
492 mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700493
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700494 // update the layer size and release freeze-lock
495 const Layer::State& front(drawingState());
496 if (newFrontBuffer->getWidth() == front.requested_w &&
497 newFrontBuffer->getHeight() == front.requested_h)
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700498 {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700499 if ((front.w != front.requested_w) ||
500 (front.h != front.requested_h))
501 {
502 // Here we pretend the transaction happened by updating the
503 // current and drawing states. Drawing state is only accessed
504 // in this thread, no need to have it locked
505 Layer::State& editDraw(mDrawingState);
506 editDraw.w = editDraw.requested_w;
507 editDraw.h = editDraw.requested_h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700508
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700509 // We also need to update the current state so that we don't
510 // end-up doing too much work during the next transaction.
511 // NOTE: We actually don't need hold the transaction lock here
512 // because State::w and State::h are only accessed from
513 // this thread
514 Layer::State& editTemp(currentState());
515 editTemp.w = editDraw.w;
516 editTemp.h = editDraw.h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700517
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700518 // recompute visible region
519 recomputeVisibleRegions = true;
520 }
521
522 // we now have the correct size, unfreeze the screen
523 mFreezeLock.clear();
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700524 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700525 } else {
526 // this should not happen unless we ran out of memory while
527 // allocating the buffer. we're hoping that things will get back
528 // to normal the next time the app tries to draw into this buffer.
529 // meanwhile, pretend the screen didn't update.
530 mPostedDirtyRegion.clear();
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700531 }
532
Mathias Agopiane7005012009-10-07 16:44:10 -0700533 if (lcblk->getQueuedCount()) {
534 // signal an event if we have more buffers waiting
535 mFlinger->signalEvent();
536 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800537
Mathias Agopian245e4d72010-04-21 15:24:11 -0700538 /* a buffer was posted, so we need to call reloadTexture(), which
539 * will update our internal data structures (eg: EGLImageKHR or
540 * texture names). we need to do this even if mPostedDirtyRegion is
541 * empty -- it's orthogonal to the fact that a new buffer was posted,
542 * for instance, a degenerate case could be that the user did an empty
543 * update but repainted the buffer with appropriate content (after a
544 * resize for instance).
545 */
546 reloadTexture( mPostedDirtyRegion );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800547}
548
549void Layer::unlockPageFlip(
550 const Transform& planeTransform, Region& outDirtyRegion)
551{
552 Region dirtyRegion(mPostedDirtyRegion);
553 if (!dirtyRegion.isEmpty()) {
554 mPostedDirtyRegion.clear();
555 // The dirty region is given in the layer's coordinate space
556 // transform the dirty region by the surface's transformation
557 // and the global transformation.
558 const Layer::State& s(drawingState());
559 const Transform tr(planeTransform * s.transform);
560 dirtyRegion = tr.transform(dirtyRegion);
561
562 // At this point, the dirty region is in screen space.
563 // Make sure it's constrained by the visible region (which
564 // is in screen space as well).
565 dirtyRegion.andSelf(visibleRegionScreen);
566 outDirtyRegion.orSelf(dirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800567 }
Mathias Agopianc61de172009-11-30 11:15:41 -0800568 if (visibleRegionScreen.isEmpty()) {
569 // an invisible layer should not hold a freeze-lock
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700570 // (because it may never be updated and therefore never release it)
Mathias Agopianc61de172009-11-30 11:15:41 -0800571 mFreezeLock.clear();
572 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800573}
574
575void Layer::finishPageFlip()
576{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700577 status_t err = lcblk->unlock( mFrontBufferIndex );
578 LOGE_IF(err!=NO_ERROR,
579 "layer %p, buffer=%d wasn't locked!",
580 this, mFrontBufferIndex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800581}
582
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700583
584void Layer::dump(String8& result, char* buffer, size_t SIZE) const
585{
586 LayerBaseClient::dump(result, buffer, SIZE);
587
588 SharedBufferStack::Statistics stats = lcblk->getStats();
589 result.append( lcblk->dump(" ") );
590 sp<const GraphicBuffer> buf0(getBuffer(0));
591 sp<const GraphicBuffer> buf1(getBuffer(1));
592 uint32_t w0=0, h0=0, s0=0;
593 uint32_t w1=0, h1=0, s1=0;
594 if (buf0 != 0) {
595 w0 = buf0->getWidth();
596 h0 = buf0->getHeight();
597 s0 = buf0->getStride();
598 }
599 if (buf1 != 0) {
600 w1 = buf1->getWidth();
601 h1 = buf1->getHeight();
602 s1 = buf1->getStride();
603 }
604 snprintf(buffer, SIZE,
605 " "
606 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
607 " freezeLock=%p, dq-q-time=%u us\n",
608 pixelFormat(),
609 w0, h0, s0, w1, h1, s1,
610 getFreezeLock().get(), stats.totalTime);
611
612 result.append(buffer);
613}
614
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700615// ---------------------------------------------------------------------------
616
Mathias Agopian9a112062009-04-17 19:36:26 -0700617Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
618 SurfaceID id, const sp<Layer>& owner)
619 : Surface(flinger, id, owner->getIdentity(), owner)
620{
621}
622
623Layer::SurfaceLayer::~SurfaceLayer()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700624{
625}
626
Mathias Agopian3330b202009-10-05 17:07:12 -0700627sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700628{
Mathias Agopian3330b202009-10-05 17:07:12 -0700629 sp<GraphicBuffer> buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700630 sp<Layer> owner(getOwner());
631 if (owner != 0) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700632 LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
633 "getBuffer() index (%d) out of range", index);
634 if (uint32_t(index) < NUM_BUFFERS) {
635 buffer = owner->requestBuffer(index, usage);
636 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700637 }
638 return buffer;
639}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800640
641// ---------------------------------------------------------------------------
642
643
644}; // namespace android