blob: 4f6bae1dd67f3384b293bfd778b247768e868b00 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
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
17#define LOG_TAG "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <cutils/properties.h>
24
25#include <utils/Errors.h>
26#include <utils/Log.h>
27#include <utils/StopWatch.h>
28
29#include <ui/PixelFormat.h>
30#include <ui/EGLDisplaySurface.h>
31
32#include "clz.h"
33#include "Layer.h"
34#include "LayerBitmap.h"
35#include "SurfaceFlinger.h"
36#include "VRamHeap.h"
37#include "DisplayHardware/DisplayHardware.h"
38
39
40#define DEBUG_RESIZE 0
41
42
43namespace android {
44
45// ---------------------------------------------------------------------------
46
47const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4;
48const char* const Layer::typeID = "Layer";
49
50// ---------------------------------------------------------------------------
51
52Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i)
53 : LayerBaseClient(flinger, display, c, i),
54 mSecure(false),
55 mFrontBufferIndex(1),
56 mNeedsBlending(true),
57 mResizeTransactionDone(false),
58 mTextureName(-1U), mTextureWidth(0), mTextureHeight(0)
59{
60 // no OpenGL operation is possible here, since we might not be
61 // in the OpenGL thread.
62}
63
64Layer::~Layer()
65{
66 client->free(clientIndex());
67 // this should always be called from the OpenGL thread
68 if (mTextureName != -1U) {
69 //glDeleteTextures(1, &mTextureName);
70 deletedTextures.add(mTextureName);
71 }
72}
73
74void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags)
75{
76 LayerBase::initStates(w,h,flags);
77
78 if (flags & ISurfaceComposer::eDestroyBackbuffer)
79 lcblk->flags |= eNoCopyBack;
80}
81
82sp<LayerBaseClient::Surface> Layer::getSurface() const
83{
84 return mSurface;
85}
86
87status_t Layer::setBuffers( Client* client,
88 uint32_t w, uint32_t h,
89 PixelFormat format, uint32_t flags)
90{
91 PixelFormatInfo info;
92 status_t err = getPixelFormatInfo(format, &info);
93 if (err) return err;
94
95 // TODO: if eHardware is explicitely requested, we should fail
96 // on systems where we can't allocate memory that can be used with
97 // DMA engines for instance.
98
99 int memory_type = NATIVE_MEMORY_TYPE_PMEM;
100
101 // pixel-alignment. the final alignment may be bigger because
102 // we always force a 4-byte aligned bpr.
103 uint32_t alignment = 1;
104
105 const uint32_t mask = ISurfaceComposer::eGPU | ISurfaceComposer::eSecure;
106 if ((flags & mask) == ISurfaceComposer::eGPU) {
107 // don't grant GPU memory if GPU is disabled
108 char value[PROPERTY_VALUE_MAX];
109 property_get("debug.egl.hw", value, "1");
110 if (atoi(value) != 0) {
111 flags |= ISurfaceComposer::eHardware;
112 memory_type = NATIVE_MEMORY_TYPE_GPU;
113 // TODO: this value should come from the h/w
114 alignment = 8;
115 }
116 }
117
118 mSecure = (flags & ISurfaceComposer::eSecure) ? true : false;
119 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
120 sp<MemoryDealer> allocators[2];
121 for (int i=0 ; i<2 ; i++) {
122 allocators[i] = client->createAllocator(memory_type);
123 if (allocators[i] == 0)
124 return NO_MEMORY;
125 mBuffers[i].init(allocators[i]);
126 int err = mBuffers[i].setBits(w, h, alignment, format, LayerBitmap::SECURE_BITS);
127 if (err != NO_ERROR)
128 return err;
129 mBuffers[i].clear(); // clear the bits for security
130 mBuffers[i].getInfo(lcblk->surface + i);
131 }
132
133 mSurface = new Surface(clientIndex(),
134 allocators[0]->getMemoryHeap(),
135 allocators[1]->getMemoryHeap(),
136 memory_type, mIdentity);
137
138 return NO_ERROR;
139}
140
141void Layer::reloadTexture(const Region& dirty)
142{
143 if (UNLIKELY(mTextureName == -1U)) {
144 // create the texture name the first time
145 // can't do that in the ctor, because it runs in another thread.
146 mTextureName = createTexture();
147 }
148 const GGLSurface& t(frontBuffer().surface());
149 loadTexture(dirty, mTextureName, t, mTextureWidth, mTextureHeight);
150}
151
152
153void Layer::onDraw(const Region& clip) const
154{
155 if (UNLIKELY(mTextureName == -1LU)) {
156 //LOGW("Layer %p doesn't have a texture", this);
157 // the texture has not been created yet, this Layer has
158 // in fact never been drawn into. this happens frequently with
159 // SurfaceView.
160 clearWithOpenGL(clip);
161 return;
162 }
163
164 const DisplayHardware& hw(graphicPlane(0).displayHardware());
165 const LayerBitmap& front(frontBuffer());
166 const GGLSurface& t(front.surface());
167
168 status_t err = NO_ERROR;
169 const int can_use_copybit = canUseCopybit();
170 if (can_use_copybit) {
171 // StopWatch watch("copybit");
172 const State& s(drawingState());
173
174 copybit_image_t dst;
175 hw.getDisplaySurface(&dst);
176 const copybit_rect_t& drect
177 = reinterpret_cast<const copybit_rect_t&>(mTransformedBounds);
178
179 copybit_image_t src;
180 front.getBitmapSurface(&src);
181 copybit_rect_t srect = { 0, 0, t.width, t.height };
182
183 copybit_t* copybit = mFlinger->getBlitEngine();
184 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
185 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
186 copybit->set_parameter(copybit, COPYBIT_DITHER,
187 s.flags & ISurfaceComposer::eLayerDither ?
188 COPYBIT_ENABLE : COPYBIT_DISABLE);
189
190 region_iterator it(clip);
191 err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
192 }
193
194 if (!can_use_copybit || err) {
195 drawWithOpenGL(clip, mTextureName, t);
196 }
197}
198
199status_t Layer::reallocateBuffer(int32_t index, uint32_t w, uint32_t h)
200{
201 LOGD_IF(DEBUG_RESIZE,
202 "reallocateBuffer (layer=%p), "
203 "requested (%dx%d), "
204 "index=%d, (%dx%d), (%dx%d)",
205 this,
206 int(w), int(h),
207 int(index),
208 int(mBuffers[0].width()), int(mBuffers[0].height()),
209 int(mBuffers[1].width()), int(mBuffers[1].height()));
210
211 status_t err = mBuffers[index].resize(w, h);
212 if (err == NO_ERROR) {
213 mBuffers[index].getInfo(lcblk->surface + index);
214 } else {
215 LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s",
216 index, w, h, err, strerror(err));
217 // XXX: what to do, what to do? We could try to free some
218 // hidden surfaces, instead of killing this one?
219 }
220 return err;
221}
222
223uint32_t Layer::doTransaction(uint32_t flags)
224{
225 const Layer::State& front(drawingState());
226 const Layer::State& temp(currentState());
227
228 // the test front.{w|h} != temp.{w|h} is not enough because it is possible
229 // that the size changed back to its previous value before the buffer
230 // was resized (in the eLocked case below), in which case, we still
231 // need to execute the code below so the clients have a chance to be
232 // release. resze() deals with the fact that the size can be the same.
233
234 /*
235 * Various states we could be in...
236
237 resize = state & eResizeRequested;
238 if (backbufferChanged) {
239 if (resize == 0) {
240 // ERROR, the resized buffer doesn't have its resize flag set
241 } else if (resize == mask) {
242 // ERROR one of the buffer has already been resized
243 } else if (resize == mask ^ eResizeRequested) {
244 // ERROR, the resized buffer doesn't have its resize flag set
245 } else if (resize == eResizeRequested) {
246 // OK, Normal case, proceed with resize
247 }
248 } else {
249 if (resize == 0) {
250 // OK, nothing special, do nothing
251 } else if (resize == mask) {
252 // restarted transaction, do nothing
253 } else if (resize == mask ^ eResizeRequested) {
254 // restarted transaction, do nothing
255 } else if (resize == eResizeRequested) {
256 // OK, size reset to previous value, proceed with resize
257 }
258 }
259 */
260
261 // Index of the back buffer
262 const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
263 const uint32_t state = lcblk->swapState;
264 const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state);
265 const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
266 uint32_t resizeFlags = state & eResizeRequested;
267
268 if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) {
269 LOGE( "backbuffer size changed, but both resize flags are not set! "
270 "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), "
271 "index=%d, (%dx%d), (%dx%d)",
272 this, state,
273 int(temp.w), int(temp.h),
274 int(drawingState().w), int(drawingState().h),
275 int(clientBackBufferIndex),
276 int(mBuffers[0].width()), int(mBuffers[0].height()),
277 int(mBuffers[1].width()), int(mBuffers[1].height()));
278 // if we get there we're pretty screwed. the only reasonable
279 // thing to do is to pretend we should do the resize since
280 // backbufferChanged is set (this also will give a chance to
281 // client to get unblocked)
282 resizeFlags = eResizeRequested;
283 }
284
285 if (resizeFlags == eResizeRequested) {
286 // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex
287 // here, would be wrong and misleading because by this point
288 // mFrontBufferIndex has not been updated yet.
289
290 LOGD_IF(DEBUG_RESIZE,
291 "resize (layer=%p), state=%08x, "
292 "requested (%dx%d), "
293 "drawing (%d,%d), "
294 "index=%d, (%dx%d), (%dx%d)",
295 this, state,
296 int(temp.w), int(temp.h),
297 int(drawingState().w), int(drawingState().h),
298 int(clientBackBufferIndex),
299 int(mBuffers[0].width()), int(mBuffers[0].height()),
300 int(mBuffers[1].width()), int(mBuffers[1].height()));
301
302 if (state & eLocked) {
303 // if the buffer is locked, we can't resize anything because
304 // - the backbuffer is currently in use by the user
305 // - the front buffer is being shown
306 // We just act as if the transaction didn't happen and we
307 // reschedule it later...
308 flags |= eRestartTransaction;
309 } else {
310 // This buffer needs to be resized
311 status_t err =
312 resize(clientBackBufferIndex, temp.w, temp.h, "transaction");
313 if (err == NO_ERROR) {
314 const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0;
315 android_atomic_and(~mask, &(lcblk->swapState));
316 // since a buffer became availlable, we can let the client go...
317 mFlinger->scheduleBroadcast(client);
318 mResizeTransactionDone = true;
319
320 // we're being resized and there is a freeze display request,
321 // acquire a freeze lock, so that the screen stays put
322 // until we've redrawn at the new size; this is to avoid
323 // glitches upon orientation changes.
324 if (mFlinger->hasFreezeRequest()) {
325 // if the surface is hidden, don't try to acquire the
326 // freeze lock, since hidden surfaces may never redraw
327 if (!(front.flags & ISurfaceComposer::eLayerHidden)) {
328 mFreezeLock = mFlinger->getFreezeLock();
329 }
330 }
331 }
332 }
333 }
334
335 if (temp.sequence != front.sequence) {
336 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) {
337 // this surface is now hidden, so it shouldn't hold a freeze lock
338 // (it may never redraw, which is fine if it is hidden)
339 mFreezeLock.clear();
340 }
341 }
342
343 return LayerBase::doTransaction(flags);
344}
345
346status_t Layer::resize(
347 int32_t clientBackBufferIndex,
348 uint32_t width, uint32_t height,
349 const char* what)
350{
351 /*
352 * handle resize (backbuffer and frontbuffer reallocation)
353 */
354
355 const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]);
356
357 // if the new (transaction) size is != from the the backbuffer
358 // then we need to reallocate the backbuffer
359 bool backbufferChanged = (clientBackBuffer.width() != width) ||
360 (clientBackBuffer.height() != height);
361
362 LOGD_IF(!backbufferChanged,
363 "(%s) eResizeRequested (layer=%p), but size not changed: "
364 "requested (%dx%d), drawing (%d,%d), current (%d,%d),"
365 "state=%08lx, index=%d, (%dx%d), (%dx%d)",
366 what, this,
367 int(width), int(height),
368 int(drawingState().w), int(drawingState().h),
369 int(currentState().w), int(currentState().h),
370 long(lcblk->swapState),
371 int(clientBackBufferIndex),
372 int(mBuffers[0].width()), int(mBuffers[0].height()),
373 int(mBuffers[1].width()), int(mBuffers[1].height()));
374
375 // this can happen when changing the size back and forth quickly
376 status_t err = NO_ERROR;
377 if (backbufferChanged) {
378 err = reallocateBuffer(clientBackBufferIndex, width, height);
379 }
380 if (UNLIKELY(err != NO_ERROR)) {
381 // couldn't reallocate the surface
382 android_atomic_write(eInvalidSurface, &lcblk->swapState);
383 memset(lcblk->surface+clientBackBufferIndex, 0, sizeof(surface_info_t));
384 }
385 return err;
386}
387
388void Layer::setSizeChanged(uint32_t w, uint32_t h)
389{
390 LOGD_IF(DEBUG_RESIZE,
391 "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)",
392 w, h, mCurrentState.w, mCurrentState.h);
393 android_atomic_or(eResizeRequested, &(lcblk->swapState));
394}
395
396// ----------------------------------------------------------------------------
397// pageflip handling...
398// ----------------------------------------------------------------------------
399
400void Layer::lockPageFlip(bool& recomputeVisibleRegions)
401{
402 uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState));
403 // preemptively block the client, because he might set
404 // eFlipRequested at any time and want to use this buffer
405 // for the next frame. This will be unset below if it
406 // turns out we didn't need it.
407
408 uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested;
409 if (!(state & mask))
410 return;
411
412 if (UNLIKELY(state & eInvalidSurface)) {
413 // if eInvalidSurface is set, this means the surface
414 // became invalid during a transaction (NO_MEMORY for instance)
415 mFlinger->scheduleBroadcast(client);
416 return;
417 }
418
419 if (UNLIKELY(state & eFlipRequested)) {
420 uint32_t oldState;
421 mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions);
422 if (oldState & eNextFlipPending) {
423 // Process another round (we know at least a buffer
424 // is ready for that client).
425 mFlinger->signalEvent();
426 }
427 }
428}
429
430Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions)
431{
432 // atomically swap buffers and (re)set eFlipRequested
433 int32_t oldValue, newValue;
434 layer_cblk_t * const lcblk = this->lcblk;
435 do {
436 oldValue = lcblk->swapState;
437 // get the current value
438
439 LOG_ASSERT(oldValue&eFlipRequested,
440 "eFlipRequested not set, yet we're flipping! (state=0x%08lx)",
441 long(oldValue));
442
443 newValue = (oldValue ^ eIndex);
444 // swap buffers
445
446 newValue &= ~(eFlipRequested | eNextFlipPending);
447 // clear eFlipRequested and eNextFlipPending
448
449 if (oldValue & eNextFlipPending)
450 newValue |= eFlipRequested;
451 // if eNextFlipPending is set (second buffer already has something
452 // in it) we need to reset eFlipRequested because the client
453 // might never do it
454
455 } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
456 *previousSate = oldValue;
457
458 const int32_t index = (newValue & eIndex) ^ 1;
459 mFrontBufferIndex = index;
460
461 // ... post the new front-buffer
462 Region dirty(lcblk->region + index);
463 dirty.andSelf(frontBuffer().bounds());
464
465 //LOGI("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n",
466 // oldValue, newValue, mFrontBufferIndex);
467 //dirty.dump("dirty");
468
469 if (UNLIKELY(oldValue & eResizeRequested)) {
470
471 LOGD_IF(DEBUG_RESIZE,
472 "post (layer=%p), state=%08x, "
473 "index=%d, (%dx%d), (%dx%d)",
474 this, newValue,
475 int(1-index),
476 int(mBuffers[0].width()), int(mBuffers[0].height()),
477 int(mBuffers[1].width()), int(mBuffers[1].height()));
478
479 // here, we just posted the surface and we have resolved
480 // the front/back buffer indices. The client is blocked, so
481 // it cannot start using the new backbuffer.
482
483 // If the backbuffer was resized in THIS round, we actually cannot
484 // resize the frontbuffer because it has *just* been drawn (and we
485 // would have nothing to draw). In this case we just skip the resize
486 // it'll happen after the next page flip or during the next
487 // transaction.
488
489 const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0;
490 if (mResizeTransactionDone && (newValue & mask)) {
491 // Resize the layer's second buffer only if the transaction
492 // happened. It may not have happened yet if eResizeRequested
493 // was set immediately after the "transactionRequested" test,
494 // in which case the drawing state's size would be wrong.
495 mFreezeLock.clear();
496 const Layer::State& s(drawingState());
497 if (resize(1-index, s.w, s.h, "post") == NO_ERROR) {
498 do {
499 oldValue = lcblk->swapState;
500 if ((oldValue & eResizeRequested) == eResizeRequested) {
501 // ugh, another resize was requested since we processed
502 // the first buffer, don't free the client, and let
503 // the next transaction handle everything.
504 break;
505 }
506 newValue = oldValue & ~mask;
507 } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState)));
508 }
509 mResizeTransactionDone = false;
510 recomputeVisibleRegions = true;
511 invalidate = true;
512 }
513 }
514
515 reloadTexture(dirty);
516
517 return dirty;
518}
519
520Point Layer::getPhysicalSize() const
521{
522 const LayerBitmap& front(frontBuffer());
523 return Point(front.width(), front.height());
524}
525
526void Layer::unlockPageFlip(
527 const Transform& planeTransform, Region& outDirtyRegion)
528{
529 Region dirtyRegion(mPostedDirtyRegion);
530 if (!dirtyRegion.isEmpty()) {
531 mPostedDirtyRegion.clear();
532 // The dirty region is given in the layer's coordinate space
533 // transform the dirty region by the surface's transformation
534 // and the global transformation.
535 const Layer::State& s(drawingState());
536 const Transform tr(planeTransform * s.transform);
537 dirtyRegion = tr.transform(dirtyRegion);
538
539 // At this point, the dirty region is in screen space.
540 // Make sure it's constrained by the visible region (which
541 // is in screen space as well).
542 dirtyRegion.andSelf(visibleRegionScreen);
543 outDirtyRegion.orSelf(dirtyRegion);
544
545 // client could be blocked, so signal them so they get a
546 // chance to reevaluate their condition.
547 mFlinger->scheduleBroadcast(client);
548 }
549}
550
551void Layer::finishPageFlip()
552{
553 if (LIKELY(!(lcblk->swapState & eInvalidSurface))) {
554 LOGE_IF(!(lcblk->swapState & eBusy),
555 "layer %p wasn't locked!", this);
556 android_atomic_and(~eBusy, &(lcblk->swapState));
557 }
558 mFlinger->scheduleBroadcast(client);
559}
560
561
562// ---------------------------------------------------------------------------
563
564
565}; // namespace android