Layer.cpp revision 81b0aa696ac954180caec6cb8cc1bb97440e03b5
1/* 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#include <stdlib.h> 18#include <stdint.h> 19#include <sys/types.h> 20 21#include <cutils/properties.h> 22#include <cutils/native_handle.h> 23 24#include <utils/Errors.h> 25#include <utils/Log.h> 26#include <utils/StopWatch.h> 27#include <utils/IMemory.h> 28 29#include <ui/PixelFormat.h> 30#include <ui/Surface.h> 31 32#include "clz.h" 33#include "Layer.h" 34#include "LayerBitmap.h" 35#include "SurfaceFlinger.h" 36#include "DisplayHardware/DisplayHardware.h" 37 38 39#define DEBUG_RESIZE 0 40 41 42namespace android { 43 44// --------------------------------------------------------------------------- 45 46const uint32_t Layer::typeInfo = LayerBaseClient::typeInfo | 4; 47const char* const Layer::typeID = "Layer"; 48 49// --------------------------------------------------------------------------- 50 51Layer::Layer(SurfaceFlinger* flinger, DisplayID display, Client* c, int32_t i) 52 : LayerBaseClient(flinger, display, c, i), 53 mSecure(false), 54 mFrontBufferIndex(1), 55 mNeedsBlending(true), 56 mResizeTransactionDone(false) 57{ 58 // no OpenGL operation is possible here, since we might not be 59 // in the OpenGL thread. 60} 61 62Layer::~Layer() 63{ 64 destroy(); 65 // the actual buffers will be destroyed here 66} 67 68void Layer::destroy() 69{ 70 for (int i=0 ; i<NUM_BUFFERS ; i++) { 71 if (mTextures[i].name != -1U) { 72 // FIXME: this was originally to work-around a bug in the 73 // adreno driver. this should be fixed now. 74 glDeleteTextures(1, &mTextures[i].name); 75 mTextures[i].name = -1U; 76 } 77 if (mTextures[i].image != EGL_NO_IMAGE_KHR) { 78 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); 79 eglDestroyImageKHR(dpy, mTextures[i].image); 80 mTextures[i].image = EGL_NO_IMAGE_KHR; 81 } 82 } 83} 84 85void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) 86{ 87 LayerBase::initStates(w,h,flags); 88 89 if (flags & ISurfaceComposer::eDestroyBackbuffer) 90 lcblk->flags |= eNoCopyBack; 91} 92 93sp<LayerBaseClient::Surface> Layer::createSurface() const 94{ 95 return mSurface; 96} 97 98status_t Layer::ditch() 99{ 100 // the layer is not on screen anymore. free as much resources as possible 101 mSurface.clear(); 102 destroy(); 103 return NO_ERROR; 104} 105 106status_t Layer::setBuffers( Client* client, 107 uint32_t w, uint32_t h, 108 PixelFormat format, uint32_t flags) 109{ 110 PixelFormatInfo info; 111 status_t err = getPixelFormatInfo(format, &info); 112 if (err) return err; 113 114 uint32_t bufferFlags = 0; 115 if (flags & ISurfaceComposer::eGPU) 116 bufferFlags |= Buffer::GPU; 117 118 if (flags & ISurfaceComposer::eSecure) 119 bufferFlags |= Buffer::SECURE; 120 121 122 if (bufferFlags & Buffer::GPU) { 123 // FIXME: this is msm7201A specific, as its GPU only supports 124 // BGRA_8888. 125 if (format == PIXEL_FORMAT_RGBA_8888) { 126 format = PIXEL_FORMAT_BGRA_8888; 127 } 128 } 129 130 mSecure = (bufferFlags & Buffer::SECURE) ? true : false; 131 mNeedsBlending = (info.h_alpha - info.l_alpha) > 0; 132 for (int i=0 ; i<2 ; i++) { 133 err = mBuffers[i].init(lcblk->surface + i, w, h, format, bufferFlags); 134 if (err != NO_ERROR) { 135 return err; 136 } 137 } 138 mSurface = new SurfaceLayer(mFlinger, clientIndex(), this); 139 return NO_ERROR; 140} 141 142void Layer::reloadTexture(const Region& dirty) 143{ 144 const sp<const Buffer>& buffer(frontBuffer().getBuffer()); 145 if (LIKELY(mFlags & DisplayHardware::DIRECT_TEXTURE)) { 146 int index = mFrontBufferIndex; 147 if (LIKELY(!mTextures[index].dirty)) { 148 glBindTexture(GL_TEXTURE_2D, mTextures[index].name); 149 } else { 150 // we need to recreate the texture 151 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); 152 153 // create the new texture name if needed 154 if (UNLIKELY(mTextures[index].name == -1U)) { 155 mTextures[index].name = createTexture(); 156 } else { 157 glBindTexture(GL_TEXTURE_2D, mTextures[index].name); 158 } 159 160 // free the previous image 161 if (mTextures[index].image != EGL_NO_IMAGE_KHR) { 162 eglDestroyImageKHR(dpy, mTextures[index].image); 163 mTextures[index].image = EGL_NO_IMAGE_KHR; 164 } 165 166 // construct an EGL_NATIVE_BUFFER_ANDROID 167 android_native_buffer_t* clientBuf = buffer->getNativeBuffer(); 168 169 // create the new EGLImageKHR 170 const EGLint attrs[] = { 171 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, 172 EGL_NONE, EGL_NONE 173 }; 174 mTextures[index].image = eglCreateImageKHR( 175 dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, 176 (EGLClientBuffer)clientBuf, attrs); 177 178 LOGE_IF(mTextures[index].image == EGL_NO_IMAGE_KHR, 179 "eglCreateImageKHR() failed. err=0x%4x", 180 eglGetError()); 181 182 if (mTextures[index].image != EGL_NO_IMAGE_KHR) { 183 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, 184 (GLeglImageOES)mTextures[index].image); 185 GLint error = glGetError(); 186 if (UNLIKELY(error != GL_NO_ERROR)) { 187 // this failed, for instance, because we don't support 188 // NPOT. 189 // FIXME: do something! 190 mFlags &= ~DisplayHardware::DIRECT_TEXTURE; 191 } else { 192 // Everything went okay! 193 mTextures[index].dirty = false; 194 } 195 } 196 } 197 } else { 198 GGLSurface t; 199 if (LIKELY(buffer->getBitmapSurface(&t) == NO_ERROR)) { 200 if (UNLIKELY(mTextures[0].name == -1U)) { 201 mTextures[0].name = createTexture(); 202 } 203 loadTexture(dirty, mTextures[0].name, t, 204 mTextures[0].width, mTextures[0].height); 205 } 206 } 207} 208 209 210void Layer::onDraw(const Region& clip) const 211{ 212 const int index = (mFlags & DisplayHardware::DIRECT_TEXTURE) ? 213 mFrontBufferIndex : 0; 214 GLuint textureName = mTextures[index].name; 215 216 if (UNLIKELY(textureName == -1LU)) { 217 LOGW("Layer %p doesn't have a texture", this); 218 // the texture has not been created yet, this Layer has 219 // in fact never been drawn into. this happens frequently with 220 // SurfaceView. 221 clearWithOpenGL(clip); 222 return; 223 } 224 225 GGLSurface t; 226 sp<const Buffer> buffer(frontBuffer().getBuffer()); 227 buffer->getBitmapSurface(&t); 228 drawWithOpenGL(clip, textureName, t); 229} 230 231sp<SurfaceBuffer> Layer::peekBuffer() 232{ 233 /* 234 * This is called from the client's Surface::lock(), after it locked 235 * the surface successfully. We're therefore guaranteed that the 236 * back-buffer is not in use by ourselves. 237 * Of course, we need to validate all this, which is not trivial. 238 * 239 * FIXME: A resize could happen at any time here. What to do about this? 240 * - resize() form post() 241 * - resize() from doTransaction() 242 * 243 * We'll probably need an internal lock for this. 244 * 245 * 246 * TODO: We need to make sure that post() doesn't swap 247 * the buffers under us. 248 */ 249 250 // it's okay to read swapState for the purpose of figuring out the 251 // backbuffer index, which cannot change (since the app has locked it). 252 const uint32_t state = lcblk->swapState; 253 const int32_t backBufferIndex = layer_cblk_t::backBuffer(state); 254 255 // get rid of the EGL image, since we shouldn't need it anymore 256 // (note that we're in a different thread than where it is being used) 257 if (mTextures[backBufferIndex].image != EGL_NO_IMAGE_KHR) { 258 EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay()); 259 eglDestroyImageKHR(dpy, mTextures[backBufferIndex].image); 260 mTextures[backBufferIndex].image = EGL_NO_IMAGE_KHR; 261 } 262 263 LayerBitmap& layerBitmap(mBuffers[backBufferIndex]); 264 sp<SurfaceBuffer> buffer = layerBitmap.allocate(); 265 266 LOGD_IF(DEBUG_RESIZE, 267 "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)", 268 this, backBufferIndex, 269 layerBitmap.getWidth(), 270 layerBitmap.getHeight(), 271 layerBitmap.getBuffer()->getWidth(), 272 layerBitmap.getBuffer()->getHeight()); 273 274 if (UNLIKELY(buffer == 0)) { 275 // XXX: what to do, what to do? 276 } else { 277 // texture is now dirty... 278 mTextures[backBufferIndex].dirty = true; 279 // ... so it the visible region (because we consider the surface's 280 // buffer size for visibility calculations) 281 forceVisibilityTransaction(); 282 mFlinger->setTransactionFlags(eTraversalNeeded); 283 } 284 return buffer; 285} 286 287uint32_t Layer::doTransaction(uint32_t flags) 288{ 289 const Layer::State& front(drawingState()); 290 const Layer::State& temp(currentState()); 291 292 // the test front.{w|h} != temp.{w|h} is not enough because it is possible 293 // that the size changed back to its previous value before the buffer 294 // was resized (in the eLocked case below), in which case, we still 295 // need to execute the code below so the clients have a chance to be 296 // release. resize() deals with the fact that the size can be the same. 297 298 /* 299 * Various states we could be in... 300 301 resize = state & eResizeRequested; 302 if (backbufferChanged) { 303 if (resize == 0) { 304 // ERROR, the resized buffer doesn't have its resize flag set 305 } else if (resize == mask) { 306 // ERROR one of the buffer has already been resized 307 } else if (resize == mask ^ eResizeRequested) { 308 // ERROR, the resized buffer doesn't have its resize flag set 309 } else if (resize == eResizeRequested) { 310 // OK, Normal case, proceed with resize 311 } 312 } else { 313 if (resize == 0) { 314 // OK, nothing special, do nothing 315 } else if (resize == mask) { 316 // restarted transaction, do nothing 317 } else if (resize == mask ^ eResizeRequested) { 318 // restarted transaction, do nothing 319 } else if (resize == eResizeRequested) { 320 // OK, size reset to previous value, proceed with resize 321 } 322 } 323 */ 324 325 // Index of the back buffer 326 const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h); 327 const uint32_t state = lcblk->swapState; 328 const int32_t clientBackBufferIndex = layer_cblk_t::backBuffer(state); 329 const uint32_t mask = clientBackBufferIndex ? eResizeBuffer1 : eResizeBuffer0; 330 uint32_t resizeFlags = state & eResizeRequested; 331 332 if (UNLIKELY(backbufferChanged && (resizeFlags != eResizeRequested))) { 333 LOGE( "backbuffer size changed, but both resize flags are not set! " 334 "(layer=%p), state=%08x, requested (%dx%d), drawing (%d,%d), " 335 "index=%d, (%dx%d), (%dx%d)", 336 this, state, 337 int(temp.w), int(temp.h), 338 int(drawingState().w), int(drawingState().h), 339 int(clientBackBufferIndex), 340 int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), 341 int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); 342 // if we get there we're pretty screwed. the only reasonable 343 // thing to do is to pretend we should do the resize since 344 // backbufferChanged is set (this also will give a chance to 345 // client to get unblocked) 346 resizeFlags = eResizeRequested; 347 } 348 349 if (resizeFlags == eResizeRequested) { 350 // NOTE: asserting that clientBackBufferIndex!=mFrontBufferIndex 351 // here, would be wrong and misleading because by this point 352 // mFrontBufferIndex has not been updated yet. 353 354 LOGD_IF(DEBUG_RESIZE, 355 "resize (layer=%p), state=%08x, " 356 "requested (%dx%d), " 357 "drawing (%d,%d), " 358 "index=%d, (%dx%d), (%dx%d)", 359 this, state, 360 int(temp.w), int(temp.h), 361 int(drawingState().w), int(drawingState().h), 362 int(clientBackBufferIndex), 363 int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), 364 int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); 365 366 if (state & eLocked) { 367 // if the buffer is locked, we can't resize anything because 368 // - the backbuffer is currently in use by the user 369 // - the front buffer is being shown 370 // We just act as if the transaction didn't happen and we 371 // reschedule it later... 372 flags |= eRestartTransaction; 373 } else { 374 // This buffer needs to be resized 375 status_t err = 376 resize(clientBackBufferIndex, temp.w, temp.h, "transaction"); 377 if (err == NO_ERROR) { 378 const uint32_t mask = clientBackBufferIndex ? 379 eResizeBuffer1 : eResizeBuffer0; 380 android_atomic_and(~mask, &(lcblk->swapState)); 381 // since a buffer became available, we can let the client go... 382 mFlinger->scheduleBroadcast(client); 383 mResizeTransactionDone = true; 384 385 // we're being resized and there is a freeze display request, 386 // acquire a freeze lock, so that the screen stays put 387 // until we've redrawn at the new size; this is to avoid 388 // glitches upon orientation changes. 389 if (mFlinger->hasFreezeRequest()) { 390 // if the surface is hidden, don't try to acquire the 391 // freeze lock, since hidden surfaces may never redraw 392 if (!(front.flags & ISurfaceComposer::eLayerHidden)) { 393 mFreezeLock = mFlinger->getFreezeLock(); 394 } 395 } 396 } 397 } 398 } 399 400 if (temp.sequence != front.sequence) { 401 if (temp.flags & ISurfaceComposer::eLayerHidden || temp.alpha == 0) { 402 // this surface is now hidden, so it shouldn't hold a freeze lock 403 // (it may never redraw, which is fine if it is hidden) 404 mFreezeLock.clear(); 405 } 406 } 407 408 return LayerBase::doTransaction(flags); 409} 410 411status_t Layer::resize( 412 int32_t clientBackBufferIndex, 413 uint32_t width, uint32_t height, 414 const char* what) 415{ 416 /* 417 * handle resize (backbuffer and frontbuffer reallocation) 418 * this is called from post() or from doTransaction() 419 */ 420 421 const LayerBitmap& clientBackBuffer(mBuffers[clientBackBufferIndex]); 422 423 // if the new (transaction) size is != from the the backbuffer 424 // then we need to reallocate the backbuffer 425 bool backbufferChanged = (clientBackBuffer.getWidth() != width) || 426 (clientBackBuffer.getHeight() != height); 427 428 LOGD_IF(!backbufferChanged, 429 "(%s) eResizeRequested (layer=%p), but size not changed: " 430 "requested (%dx%d), drawing (%d,%d), current (%d,%d)," 431 "state=%08lx, index=%d, (%dx%d), (%dx%d)", 432 what, this, 433 int(width), int(height), 434 int(drawingState().w), int(drawingState().h), 435 int(currentState().w), int(currentState().h), 436 long(lcblk->swapState), 437 int(clientBackBufferIndex), 438 int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), 439 int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); 440 441 // this can happen when changing the size back and forth quickly 442 status_t err = NO_ERROR; 443 if (backbufferChanged) { 444 445 LOGD_IF(DEBUG_RESIZE, 446 "resize (layer=%p), requested (%dx%d), " 447 "index=%d, (%dx%d), (%dx%d)", 448 this, int(width), int(height), int(clientBackBufferIndex), 449 int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), 450 int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); 451 452 err = mBuffers[clientBackBufferIndex].setSize(width, height); 453 if (UNLIKELY(err != NO_ERROR)) { 454 // This really should never happen 455 LOGE("resizing buffer %d to (%u,%u) failed [%08x] %s", 456 clientBackBufferIndex, width, height, err, strerror(err)); 457 // couldn't reallocate the surface 458 android_atomic_write(eInvalidSurface, &lcblk->swapState); 459 } 460 } 461 return err; 462} 463 464void Layer::setSizeChanged(uint32_t w, uint32_t h) 465{ 466 LOGD_IF(DEBUG_RESIZE, 467 "setSizeChanged w=%d, h=%d (old: w=%d, h=%d)", 468 w, h, mCurrentState.w, mCurrentState.h); 469 android_atomic_or(eResizeRequested, &(lcblk->swapState)); 470} 471 472// ---------------------------------------------------------------------------- 473// pageflip handling... 474// ---------------------------------------------------------------------------- 475 476void Layer::lockPageFlip(bool& recomputeVisibleRegions) 477{ 478 uint32_t state = android_atomic_or(eBusy, &(lcblk->swapState)); 479 // preemptively block the client, because he might set 480 // eFlipRequested at any time and want to use this buffer 481 // for the next frame. This will be unset below if it 482 // turns out we didn't need it. 483 484 uint32_t mask = eInvalidSurface | eFlipRequested | eResizeRequested; 485 if (!(state & mask)) 486 return; 487 488 if (UNLIKELY(state & eInvalidSurface)) { 489 // if eInvalidSurface is set, this means the surface 490 // became invalid during a transaction (NO_MEMORY for instance) 491 mFlinger->scheduleBroadcast(client); 492 return; 493 } 494 495 if (UNLIKELY(state & eFlipRequested)) { 496 uint32_t oldState; 497 mPostedDirtyRegion = post(&oldState, recomputeVisibleRegions); 498 if (oldState & eNextFlipPending) { 499 // Process another round (we know at least a buffer 500 // is ready for that client). 501 mFlinger->signalEvent(); 502 } 503 } 504} 505 506Region Layer::post(uint32_t* previousSate, bool& recomputeVisibleRegions) 507{ 508 // atomically swap buffers and (re)set eFlipRequested 509 int32_t oldValue, newValue; 510 layer_cblk_t * const lcblk = this->lcblk; 511 do { 512 oldValue = lcblk->swapState; 513 // get the current value 514 515 LOG_ASSERT(oldValue&eFlipRequested, 516 "eFlipRequested not set, yet we're flipping! (state=0x%08lx)", 517 long(oldValue)); 518 519 newValue = (oldValue ^ eIndex); 520 // swap buffers 521 522 newValue &= ~(eFlipRequested | eNextFlipPending); 523 // clear eFlipRequested and eNextFlipPending 524 525 if (oldValue & eNextFlipPending) 526 newValue |= eFlipRequested; 527 // if eNextFlipPending is set (second buffer already has something 528 // in it) we need to reset eFlipRequested because the client 529 // might never do it 530 531 } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); 532 *previousSate = oldValue; 533 534 const int32_t index = (newValue & eIndex) ^ 1; 535 mFrontBufferIndex = index; 536 537 /* NOTE: it's safe to set this flag here because this is only touched 538 * from LayerBitmap::allocate(), which by construction cannot happen 539 * while we're in post(). 540 */ 541 lcblk->surface[index].flags &= ~surface_info_t::eBufferDirty; 542 543 // ... post the new front-buffer 544 Region dirty(lcblk->region + index); 545 dirty.andSelf(frontBuffer().getBounds()); 546 547 //LOGD("Did post oldValue=%08lx, newValue=%08lx, mFrontBufferIndex=%u\n", 548 // oldValue, newValue, mFrontBufferIndex); 549 //dirty.dump("dirty"); 550 551 if (UNLIKELY(oldValue & eResizeRequested)) { 552 553 LOGD_IF(DEBUG_RESIZE, 554 "post (layer=%p), state=%08x, " 555 "index=%d, (%dx%d), (%dx%d)", 556 this, newValue, 557 int(1-index), 558 int(mBuffers[0].getWidth()), int(mBuffers[0].getHeight()), 559 int(mBuffers[1].getWidth()), int(mBuffers[1].getHeight())); 560 561 // here, we just posted the surface and we have resolved 562 // the front/back buffer indices. The client is blocked, so 563 // it cannot start using the new backbuffer. 564 565 // If the backbuffer was resized in THIS round, we actually cannot 566 // resize the frontbuffer because it has *just* been drawn (and we 567 // would have nothing to draw). In this case we just skip the resize 568 // it'll happen after the next page flip or during the next 569 // transaction. 570 571 const uint32_t mask = (1-index) ? eResizeBuffer1 : eResizeBuffer0; 572 if (mResizeTransactionDone && (newValue & mask)) { 573 // Resize the layer's second buffer only if the transaction 574 // happened. It may not have happened yet if eResizeRequested 575 // was set immediately after the "transactionRequested" test, 576 // in which case the drawing state's size would be wrong. 577 mFreezeLock.clear(); 578 const Layer::State& s(drawingState()); 579 if (resize(1-index, s.w, s.h, "post") == NO_ERROR) { 580 do { 581 oldValue = lcblk->swapState; 582 if ((oldValue & eResizeRequested) == eResizeRequested) { 583 // ugh, another resize was requested since we processed 584 // the first buffer, don't free the client, and let 585 // the next transaction handle everything. 586 break; 587 } 588 newValue = oldValue & ~mask; 589 } while(android_atomic_cmpxchg(oldValue, newValue, &(lcblk->swapState))); 590 } 591 mResizeTransactionDone = false; 592 recomputeVisibleRegions = true; 593 this->contentDirty = true; 594 } 595 } 596 597 reloadTexture(dirty); 598 599 return dirty; 600} 601 602Point Layer::getPhysicalSize() const 603{ 604 sp<const Buffer> front(frontBuffer().getBuffer()); 605 return Point(front->getWidth(), front->getHeight()); 606} 607 608void Layer::unlockPageFlip( 609 const Transform& planeTransform, Region& outDirtyRegion) 610{ 611 Region dirtyRegion(mPostedDirtyRegion); 612 if (!dirtyRegion.isEmpty()) { 613 mPostedDirtyRegion.clear(); 614 // The dirty region is given in the layer's coordinate space 615 // transform the dirty region by the surface's transformation 616 // and the global transformation. 617 const Layer::State& s(drawingState()); 618 const Transform tr(planeTransform * s.transform); 619 dirtyRegion = tr.transform(dirtyRegion); 620 621 // At this point, the dirty region is in screen space. 622 // Make sure it's constrained by the visible region (which 623 // is in screen space as well). 624 dirtyRegion.andSelf(visibleRegionScreen); 625 outDirtyRegion.orSelf(dirtyRegion); 626 627 // client could be blocked, so signal them so they get a 628 // chance to reevaluate their condition. 629 mFlinger->scheduleBroadcast(client); 630 } 631} 632 633void Layer::finishPageFlip() 634{ 635 if (LIKELY(!(lcblk->swapState & eInvalidSurface))) { 636 LOGE_IF(!(lcblk->swapState & eBusy), 637 "layer %p wasn't locked!", this); 638 android_atomic_and(~eBusy, &(lcblk->swapState)); 639 } 640 mFlinger->scheduleBroadcast(client); 641} 642 643// --------------------------------------------------------------------------- 644 645Layer::SurfaceLayer::SurfaceLayer(const sp<SurfaceFlinger>& flinger, 646 SurfaceID id, const sp<Layer>& owner) 647 : Surface(flinger, id, owner->getIdentity(), owner) 648{ 649} 650 651Layer::SurfaceLayer::~SurfaceLayer() 652{ 653} 654 655sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer() 656{ 657 sp<SurfaceBuffer> buffer = 0; 658 sp<Layer> owner(getOwner()); 659 if (owner != 0) { 660 buffer = owner->peekBuffer(); 661 } 662 return buffer; 663} 664 665// --------------------------------------------------------------------------- 666 667 668}; // namespace android 669