blob: e6658fa7cec21c02da43f2016f5b8686006f5384 [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
Mathias Agopian179169e2010-05-06 20:21:45 -0700279 // in fact never been drawn into. This happens frequently with
280 // SurfaceView because the WindowManager can't know when the client
281 // has drawn the first time.
282
283 // If there is nothing under us, we paint the screen in black, otherwise
284 // we just skip this update.
285
286 // figure out if there is something below us
287 Region under;
288 const SurfaceFlinger::LayerVector& drawingLayers(mFlinger->mDrawingState.layersSortedByZ);
289 const size_t count = drawingLayers.size();
290 for (size_t i=0 ; i<count ; ++i) {
291 const sp<LayerBase>& layer(drawingLayers[i]);
292 if (layer.get() == static_cast<LayerBase const*>(this))
293 break;
294 under.orSelf(layer->visibleRegionScreen);
295 }
296 // if not everything below us is covered, we plug the holes!
297 Region holes(clip.subtract(under));
298 if (!holes.isEmpty()) {
299 clearWithOpenGL(holes);
300 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800301 return;
302 }
Mathias Agopian1fed11c2009-06-23 18:08:22 -0700303 drawWithOpenGL(clip, mTextures[index]);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800304}
305
Mathias Agopian3330b202009-10-05 17:07:12 -0700306sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800307{
Mathias Agopian3330b202009-10-05 17:07:12 -0700308 sp<GraphicBuffer> buffer;
Mathias Agopian48d819a2009-09-10 19:41:18 -0700309
310 // this ensures our client doesn't go away while we're accessing
311 // the shared area.
312 sp<Client> ourClient(client.promote());
313 if (ourClient == 0) {
314 // oops, the client is already gone
315 return buffer;
316 }
317
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700318 /*
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700319 * This is called from the client's Surface::dequeue(). This can happen
320 * at any time, especially while we're in the middle of using the
321 * buffer 'index' as our front buffer.
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700322 *
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700323 * Make sure the buffer we're resizing is not the front buffer and has been
324 * dequeued. Once this condition is asserted, we are guaranteed that this
325 * buffer cannot become the front buffer under our feet, since we're called
326 * from Surface::dequeue()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700327 */
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700328 status_t err = lcblk->assertReallocate(index);
329 LOGE_IF(err, "assertReallocate(%d) failed (%s)", index, strerror(-err));
Mathias Agopian48d819a2009-09-10 19:41:18 -0700330 if (err != NO_ERROR) {
331 // the surface may have died
332 return buffer;
333 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800334
Mathias Agopian48d819a2009-09-10 19:41:18 -0700335 uint32_t w, h;
336 { // scope for the lock
337 Mutex::Autolock _l(mLock);
338 w = mWidth;
339 h = mHeight;
340 buffer = mBuffers[index];
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700341
342 // destroy() could have been called before we get here, we log it
343 // because it's uncommon, and the code below should handle it
344 LOGW_IF(buffer==0,
345 "mBuffers[%d] is null (mWidth=%d, mHeight=%d)",
346 index, w, h);
347
Mathias Agopian48d819a2009-09-10 19:41:18 -0700348 mBuffers[index].clear();
349 }
350
Mathias Agopian3330b202009-10-05 17:07:12 -0700351 const uint32_t effectiveUsage = getEffectiveUsage(usage);
Mathias Agopian6d9f6982009-09-17 19:19:08 -0700352 if (buffer!=0 && buffer->getStrongCount() == 1) {
Mathias Agopian3330b202009-10-05 17:07:12 -0700353 err = buffer->reallocate(w, h, mFormat, effectiveUsage);
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700354 } else {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700355 // here we have to reallocate a new buffer because we could have a
356 // client in our process with a reference to it (eg: status bar),
357 // and we can't release the handle under its feet.
358 buffer.clear();
Mathias Agopian3330b202009-10-05 17:07:12 -0700359 buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700360 err = buffer->initCheck();
361 }
362
363 if (err || buffer->handle == 0) {
364 LOGE_IF(err || buffer->handle == 0,
365 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d failed (%s)",
366 this, index, w, h, strerror(-err));
367 } else {
368 LOGD_IF(DEBUG_RESIZE,
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700369 "Layer::requestBuffer(this=%p), index=%d, w=%d, h=%d, handle=%p",
370 this, index, w, h, buffer->handle);
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700371 }
372
373 if (err == NO_ERROR && buffer->handle != 0) {
Mathias Agopian48d819a2009-09-10 19:41:18 -0700374 Mutex::Autolock _l(mLock);
375 if (mWidth && mHeight) {
376 // and we have new buffer
377 mBuffers[index] = buffer;
378 // texture is now dirty...
379 mTextures[index].dirty = true;
380 } else {
381 // oops we got killed while we were allocating the buffer
382 buffer.clear();
383 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700384 }
385 return buffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800386}
387
Mathias Agopian3330b202009-10-05 17:07:12 -0700388uint32_t Layer::getEffectiveUsage(uint32_t usage) const
389{
390 /*
391 * buffers used for software rendering, but h/w composition
392 * are allocated with SW_READ_OFTEN | SW_WRITE_OFTEN | HW_TEXTURE
393 *
394 * buffers used for h/w rendering and h/w composition
395 * are allocated with HW_RENDER | HW_TEXTURE
396 *
397 * buffers used with h/w rendering and either NPOT or no egl_image_ext
398 * are allocated with SW_READ_RARELY | HW_RENDER
399 *
400 */
401
402 if (mSecure) {
403 // secure buffer, don't store it into the GPU
404 usage = GraphicBuffer::USAGE_SW_READ_OFTEN |
405 GraphicBuffer::USAGE_SW_WRITE_OFTEN;
406 } else {
407 // it's allowed to modify the usage flags here, but generally
408 // the requested flags should be honored.
Mathias Agopiana4b740e2009-10-05 18:20:39 -0700409 if (mNoEGLImageForSwBuffers) {
410 if (usage & GraphicBuffer::USAGE_HW_MASK) {
411 // request EGLImage for h/w buffers only
412 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
413 }
414 } else {
415 // request EGLImage for all buffers
416 usage |= GraphicBuffer::USAGE_HW_TEXTURE;
417 }
Mathias Agopian3330b202009-10-05 17:07:12 -0700418 }
419 return usage;
420}
421
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800422uint32_t Layer::doTransaction(uint32_t flags)
423{
424 const Layer::State& front(drawingState());
425 const Layer::State& temp(currentState());
426
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700427 if ((front.requested_w != temp.requested_w) ||
428 (front.requested_h != temp.requested_h)) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700429 // the size changed, we need to ask our client to request a new buffer
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800430 LOGD_IF(DEBUG_RESIZE,
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700431 "resize (layer=%p), requested (%dx%d), "
432 "drawing (%d,%d), (%dx%d), (%dx%d)",
Mathias Agopian7e4a5872009-09-29 22:39:22 -0700433 this,
434 int(temp.requested_w), int(temp.requested_h),
435 int(front.requested_w), int(front.requested_h),
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700436 int(mBuffers[0]->getWidth()), int(mBuffers[0]->getHeight()),
437 int(mBuffers[1]->getWidth()), int(mBuffers[1]->getHeight()));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800438
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700439 // we're being resized and there is a freeze display request,
440 // acquire a freeze lock, so that the screen stays put
441 // until we've redrawn at the new size; this is to avoid
442 // glitches upon orientation changes.
443 if (mFlinger->hasFreezeRequest()) {
444 // if the surface is hidden, don't try to acquire the
445 // freeze lock, since hidden surfaces may never redraw
446 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
447 mFreezeLock = mFlinger->getFreezeLock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800448 }
449 }
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700450
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700451 // this will make sure LayerBase::doTransaction doesn't update
452 // the drawing state's size
453 Layer::State& editDraw(mDrawingState);
454 editDraw.requested_w = temp.requested_w;
455 editDraw.requested_h = temp.requested_h;
456
Mathias Agopian6656dbc2009-09-30 12:48:47 -0700457 // record the new size, form this point on, when the client request a
458 // buffer, it'll get the new size.
459 setDrawingSize(temp.requested_w, temp.requested_h);
460
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700461 // all buffers need reallocation
462 lcblk->reallocate();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800463 }
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700464
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800465 if (temp.sequence != front.sequence) {
466 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
467 // this surface is now hidden, so it shouldn't hold a freeze lock
468 // (it may never redraw, which is fine if it is hidden)
469 mFreezeLock.clear();
470 }
471 }
472
473 return LayerBase::doTransaction(flags);
474}
475
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700476void Layer::setDrawingSize(uint32_t w, uint32_t h) {
477 Mutex::Autolock _l(mLock);
478 mWidth = w;
479 mHeight = h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800480}
481
482// ----------------------------------------------------------------------------
483// pageflip handling...
484// ----------------------------------------------------------------------------
485
486void Layer::lockPageFlip(bool& recomputeVisibleRegions)
487{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700488 ssize_t buf = lcblk->retireAndLock();
489 if (buf < NO_ERROR) {
490 //LOGW("nothing to retire (%s)", strerror(-buf));
491 // NOTE: here the buffer is locked because we will used
492 // for composition later in the loop
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800493 return;
494 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700495
496 // ouch, this really should never happen
497 if (uint32_t(buf)>=NUM_BUFFERS) {
498 LOGE("retireAndLock() buffer index (%d) out of range", buf);
499 mPostedDirtyRegion.clear();
500 return;
501 }
502
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700503 // we retired a buffer, which becomes the new front buffer
504 mFrontBufferIndex = buf;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800505
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700506 // get the dirty region
Mathias Agopian3330b202009-10-05 17:07:12 -0700507 sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700508 if (newFrontBuffer != NULL) {
509 // compute the posted region
510 const Region dirty(lcblk->getDirtyRegion(buf));
511 mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700512
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700513 // update the layer size and release freeze-lock
514 const Layer::State& front(drawingState());
515 if (newFrontBuffer->getWidth() == front.requested_w &&
516 newFrontBuffer->getHeight() == front.requested_h)
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700517 {
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700518 if ((front.w != front.requested_w) ||
519 (front.h != front.requested_h))
520 {
521 // Here we pretend the transaction happened by updating the
522 // current and drawing states. Drawing state is only accessed
523 // in this thread, no need to have it locked
524 Layer::State& editDraw(mDrawingState);
525 editDraw.w = editDraw.requested_w;
526 editDraw.h = editDraw.requested_h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700527
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700528 // We also need to update the current state so that we don't
529 // end-up doing too much work during the next transaction.
530 // NOTE: We actually don't need hold the transaction lock here
531 // because State::w and State::h are only accessed from
532 // this thread
533 Layer::State& editTemp(currentState());
534 editTemp.w = editDraw.w;
535 editTemp.h = editDraw.h;
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700536
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700537 // recompute visible region
538 recomputeVisibleRegions = true;
539 }
540
541 // we now have the correct size, unfreeze the screen
542 mFreezeLock.clear();
Mathias Agopiandf3e0b92009-09-30 14:07:22 -0700543 }
Mathias Agopiand343e3d2010-03-15 18:15:20 -0700544 } else {
545 // this should not happen unless we ran out of memory while
546 // allocating the buffer. we're hoping that things will get back
547 // to normal the next time the app tries to draw into this buffer.
548 // meanwhile, pretend the screen didn't update.
549 mPostedDirtyRegion.clear();
Mathias Agopiancaa600c2009-09-16 18:27:24 -0700550 }
551
Mathias Agopiane7005012009-10-07 16:44:10 -0700552 if (lcblk->getQueuedCount()) {
553 // signal an event if we have more buffers waiting
554 mFlinger->signalEvent();
555 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800556
Mathias Agopian245e4d72010-04-21 15:24:11 -0700557 /* a buffer was posted, so we need to call reloadTexture(), which
558 * will update our internal data structures (eg: EGLImageKHR or
559 * texture names). we need to do this even if mPostedDirtyRegion is
560 * empty -- it's orthogonal to the fact that a new buffer was posted,
561 * for instance, a degenerate case could be that the user did an empty
562 * update but repainted the buffer with appropriate content (after a
563 * resize for instance).
564 */
565 reloadTexture( mPostedDirtyRegion );
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800566}
567
568void Layer::unlockPageFlip(
569 const Transform& planeTransform, Region& outDirtyRegion)
570{
571 Region dirtyRegion(mPostedDirtyRegion);
572 if (!dirtyRegion.isEmpty()) {
573 mPostedDirtyRegion.clear();
574 // The dirty region is given in the layer's coordinate space
575 // transform the dirty region by the surface's transformation
576 // and the global transformation.
577 const Layer::State& s(drawingState());
578 const Transform tr(planeTransform * s.transform);
579 dirtyRegion = tr.transform(dirtyRegion);
580
581 // At this point, the dirty region is in screen space.
582 // Make sure it's constrained by the visible region (which
583 // is in screen space as well).
584 dirtyRegion.andSelf(visibleRegionScreen);
585 outDirtyRegion.orSelf(dirtyRegion);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800586 }
Mathias Agopianc61de172009-11-30 11:15:41 -0800587 if (visibleRegionScreen.isEmpty()) {
588 // an invisible layer should not hold a freeze-lock
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700589 // (because it may never be updated and therefore never release it)
Mathias Agopianc61de172009-11-30 11:15:41 -0800590 mFreezeLock.clear();
591 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800592}
593
594void Layer::finishPageFlip()
595{
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700596 status_t err = lcblk->unlock( mFrontBufferIndex );
597 LOGE_IF(err!=NO_ERROR,
598 "layer %p, buffer=%d wasn't locked!",
599 this, mFrontBufferIndex);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800600}
601
Mathias Agopian1b5e1022010-04-20 17:55:49 -0700602
603void Layer::dump(String8& result, char* buffer, size_t SIZE) const
604{
605 LayerBaseClient::dump(result, buffer, SIZE);
606
607 SharedBufferStack::Statistics stats = lcblk->getStats();
608 result.append( lcblk->dump(" ") );
609 sp<const GraphicBuffer> buf0(getBuffer(0));
610 sp<const GraphicBuffer> buf1(getBuffer(1));
611 uint32_t w0=0, h0=0, s0=0;
612 uint32_t w1=0, h1=0, s1=0;
613 if (buf0 != 0) {
614 w0 = buf0->getWidth();
615 h0 = buf0->getHeight();
616 s0 = buf0->getStride();
617 }
618 if (buf1 != 0) {
619 w1 = buf1->getWidth();
620 h1 = buf1->getHeight();
621 s1 = buf1->getStride();
622 }
623 snprintf(buffer, SIZE,
624 " "
625 "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
626 " freezeLock=%p, dq-q-time=%u us\n",
627 pixelFormat(),
628 w0, h0, s0, w1, h1, s1,
629 getFreezeLock().get(), stats.totalTime);
630
631 result.append(buffer);
632}
633
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700634// ---------------------------------------------------------------------------
635
Mathias Agopian9a112062009-04-17 19:36:26 -0700636Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger,
637 SurfaceID id, const sp<Layer>& owner)
638 : Surface(flinger, id, owner->getIdentity(), owner)
639{
640}
641
642Layer::SurfaceLayer::~SurfaceLayer()
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700643{
644}
645
Mathias Agopian3330b202009-10-05 17:07:12 -0700646sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700647{
Mathias Agopian3330b202009-10-05 17:07:12 -0700648 sp<GraphicBuffer> buffer;
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700649 sp<Layer> owner(getOwner());
650 if (owner != 0) {
Mathias Agopiancbb288b2009-09-07 16:32:45 -0700651 LOGE_IF(uint32_t(index)>=NUM_BUFFERS,
652 "getBuffer() index (%d) out of range", index);
653 if (uint32_t(index) < NUM_BUFFERS) {
654 buffer = owner->requestBuffer(index, usage);
655 }
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700656 }
657 return buffer;
658}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800659
660// ---------------------------------------------------------------------------
661
662
663}; // namespace android