Layer.cpp revision 1681d95989271f3a9ac0dbb93d10e4a29f2b4444
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#define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19#include <stdlib.h> 20#include <stdint.h> 21#include <sys/types.h> 22#include <math.h> 23 24#include <cutils/compiler.h> 25#include <cutils/native_handle.h> 26#include <cutils/properties.h> 27 28#include <utils/Errors.h> 29#include <utils/Log.h> 30#include <utils/NativeHandle.h> 31#include <utils/StopWatch.h> 32#include <utils/Trace.h> 33 34#include <ui/GraphicBuffer.h> 35#include <ui/PixelFormat.h> 36 37#include <gui/Surface.h> 38 39#include "clz.h" 40#include "Colorizer.h" 41#include "DisplayDevice.h" 42#include "Layer.h" 43#include "MonitoredProducer.h" 44#include "SurfaceFlinger.h" 45 46#include "DisplayHardware/HWComposer.h" 47 48#include "RenderEngine/RenderEngine.h" 49 50#define DEBUG_RESIZE 0 51 52namespace android { 53 54// --------------------------------------------------------------------------- 55 56int32_t Layer::sSequence = 1; 57 58Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, 59 const String8& name, uint32_t w, uint32_t h, uint32_t flags) 60 : contentDirty(false), 61 sequence(uint32_t(android_atomic_inc(&sSequence))), 62 mFlinger(flinger), 63 mTextureName(-1U), 64 mPremultipliedAlpha(true), 65 mName("unnamed"), 66 mDebug(false), 67 mFormat(PIXEL_FORMAT_NONE), 68 mTransactionFlags(0), 69 mQueuedFrames(0), 70 mSidebandStreamChanged(false), 71 mCurrentTransform(0), 72 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), 73 mCurrentOpacity(true), 74 mRefreshPending(false), 75 mFrameLatencyNeeded(false), 76 mFiltering(false), 77 mNeedsFiltering(false), 78 mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2), 79 mSecure(false), 80 mProtectedByApp(false), 81 mHasSurface(false), 82 mClientRef(client) 83{ 84 mCurrentCrop.makeInvalid(); 85 mFlinger->getRenderEngine().genTextures(1, &mTextureName); 86 mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); 87 88 uint32_t layerFlags = 0; 89 if (flags & ISurfaceComposerClient::eHidden) 90 layerFlags |= layer_state_t::eLayerHidden; 91 if (flags & ISurfaceComposerClient::eOpaque) 92 layerFlags |= layer_state_t::eLayerOpaque; 93 94 if (flags & ISurfaceComposerClient::eNonPremultiplied) 95 mPremultipliedAlpha = false; 96 97 mName = name; 98 99 mCurrentState.active.w = w; 100 mCurrentState.active.h = h; 101 mCurrentState.active.crop.makeInvalid(); 102 mCurrentState.z = 0; 103 mCurrentState.alpha = 0xFF; 104 mCurrentState.layerStack = 0; 105 mCurrentState.flags = layerFlags; 106 mCurrentState.sequence = 0; 107 mCurrentState.transform.set(0, 0); 108 mCurrentState.requested = mCurrentState.active; 109 110 // drawing state & current state are identical 111 mDrawingState = mCurrentState; 112 113 nsecs_t displayPeriod = 114 flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); 115 mFrameTracker.setDisplayRefreshPeriod(displayPeriod); 116} 117 118void Layer::onFirstRef() { 119 // Creates a custom BufferQueue for SurfaceFlingerConsumer to use 120 sp<IGraphicBufferProducer> producer; 121 sp<IGraphicBufferConsumer> consumer; 122 BufferQueue::createBufferQueue(&producer, &consumer); 123 mProducer = new MonitoredProducer(producer, mFlinger); 124 mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName); 125 mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); 126 mSurfaceFlingerConsumer->setContentsChangedListener(this); 127 mSurfaceFlingerConsumer->setName(mName); 128 129#ifdef TARGET_DISABLE_TRIPLE_BUFFERING 130#warning "disabling triple buffering" 131 mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); 132#else 133 mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); 134#endif 135 136 const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); 137 updateTransformHint(hw); 138} 139 140Layer::~Layer() { 141 sp<Client> c(mClientRef.promote()); 142 if (c != 0) { 143 c->detachLayer(this); 144 } 145 mFlinger->deleteTextureAsync(mTextureName); 146 mFrameTracker.logAndResetStats(mName); 147} 148 149// --------------------------------------------------------------------------- 150// callbacks 151// --------------------------------------------------------------------------- 152 153void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */, 154 HWComposer::HWCLayerInterface* layer) { 155 if (layer) { 156 layer->onDisplayed(); 157 mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); 158 } 159} 160 161void Layer::onFrameAvailable() { 162 android_atomic_inc(&mQueuedFrames); 163 mFlinger->signalLayerUpdate(); 164} 165 166void Layer::onSidebandStreamChanged() { 167 if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { 168 // mSidebandStreamChanged was false 169 mFlinger->signalLayerUpdate(); 170 } 171} 172 173// called with SurfaceFlinger::mStateLock from the drawing thread after 174// the layer has been remove from the current state list (and just before 175// it's removed from the drawing state list) 176void Layer::onRemoved() { 177 mSurfaceFlingerConsumer->abandon(); 178} 179 180// --------------------------------------------------------------------------- 181// set-up 182// --------------------------------------------------------------------------- 183 184const String8& Layer::getName() const { 185 return mName; 186} 187 188status_t Layer::setBuffers( uint32_t w, uint32_t h, 189 PixelFormat format, uint32_t flags) 190{ 191 uint32_t const maxSurfaceDims = min( 192 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); 193 194 // never allow a surface larger than what our underlying GL implementation 195 // can handle. 196 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { 197 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); 198 return BAD_VALUE; 199 } 200 201 mFormat = format; 202 203 mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; 204 mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; 205 mCurrentOpacity = getOpacityForFormat(format); 206 207 mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); 208 mSurfaceFlingerConsumer->setDefaultBufferFormat(format); 209 mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); 210 211 return NO_ERROR; 212} 213 214sp<IBinder> Layer::getHandle() { 215 Mutex::Autolock _l(mLock); 216 217 LOG_ALWAYS_FATAL_IF(mHasSurface, 218 "Layer::getHandle() has already been called"); 219 220 mHasSurface = true; 221 222 /* 223 * The layer handle is just a BBinder object passed to the client 224 * (remote process) -- we don't keep any reference on our side such that 225 * the dtor is called when the remote side let go of its reference. 226 * 227 * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for 228 * this layer when the handle is destroyed. 229 */ 230 231 class Handle : public BBinder, public LayerCleaner { 232 wp<const Layer> mOwner; 233 public: 234 Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer) 235 : LayerCleaner(flinger, layer), mOwner(layer) { 236 } 237 }; 238 239 return new Handle(mFlinger, this); 240} 241 242sp<IGraphicBufferProducer> Layer::getProducer() const { 243 return mProducer; 244} 245 246// --------------------------------------------------------------------------- 247// h/w composer set-up 248// --------------------------------------------------------------------------- 249 250Rect Layer::getContentCrop() const { 251 // this is the crop rectangle that applies to the buffer 252 // itself (as opposed to the window) 253 Rect crop; 254 if (!mCurrentCrop.isEmpty()) { 255 // if the buffer crop is defined, we use that 256 crop = mCurrentCrop; 257 } else if (mActiveBuffer != NULL) { 258 // otherwise we use the whole buffer 259 crop = mActiveBuffer->getBounds(); 260 } else { 261 // if we don't have a buffer yet, we use an empty/invalid crop 262 crop.makeInvalid(); 263 } 264 return crop; 265} 266 267static Rect reduce(const Rect& win, const Region& exclude) { 268 if (CC_LIKELY(exclude.isEmpty())) { 269 return win; 270 } 271 if (exclude.isRect()) { 272 return win.reduce(exclude.getBounds()); 273 } 274 return Region(win).subtract(exclude).getBounds(); 275} 276 277Rect Layer::computeBounds() const { 278 const Layer::State& s(getDrawingState()); 279 Rect win(s.active.w, s.active.h); 280 if (!s.active.crop.isEmpty()) { 281 win.intersect(s.active.crop, &win); 282 } 283 // subtract the transparent region and snap to the bounds 284 return reduce(win, s.activeTransparentRegion); 285} 286 287FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { 288 // the content crop is the area of the content that gets scaled to the 289 // layer's size. 290 FloatRect crop(getContentCrop()); 291 292 // the active.crop is the area of the window that gets cropped, but not 293 // scaled in any ways. 294 const State& s(getDrawingState()); 295 296 // apply the projection's clipping to the window crop in 297 // layerstack space, and convert-back to layer space. 298 // if there are no window scaling involved, this operation will map to full 299 // pixels in the buffer. 300 // FIXME: the 3 lines below can produce slightly incorrect clipping when we have 301 // a viewport clipping and a window transform. we should use floating point to fix this. 302 303 Rect activeCrop(s.active.w, s.active.h); 304 if (!s.active.crop.isEmpty()) { 305 activeCrop = s.active.crop; 306 } 307 308 activeCrop = s.transform.transform(activeCrop); 309 activeCrop.intersect(hw->getViewport(), &activeCrop); 310 activeCrop = s.transform.inverse().transform(activeCrop); 311 312 // paranoia: make sure the window-crop is constrained in the 313 // window's bounds 314 activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); 315 316 // subtract the transparent region and snap to the bounds 317 activeCrop = reduce(activeCrop, s.activeTransparentRegion); 318 319 if (!activeCrop.isEmpty()) { 320 // Transform the window crop to match the buffer coordinate system, 321 // which means using the inverse of the current transform set on the 322 // SurfaceFlingerConsumer. 323 uint32_t invTransform = mCurrentTransform; 324 int winWidth = s.active.w; 325 int winHeight = s.active.h; 326 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 327 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | 328 NATIVE_WINDOW_TRANSFORM_FLIP_H; 329 winWidth = s.active.h; 330 winHeight = s.active.w; 331 } 332 const Rect winCrop = activeCrop.transform( 333 invTransform, s.active.w, s.active.h); 334 335 // below, crop is intersected with winCrop expressed in crop's coordinate space 336 float xScale = crop.getWidth() / float(winWidth); 337 float yScale = crop.getHeight() / float(winHeight); 338 339 float insetL = winCrop.left * xScale; 340 float insetT = winCrop.top * yScale; 341 float insetR = (winWidth - winCrop.right ) * xScale; 342 float insetB = (winHeight - winCrop.bottom) * yScale; 343 344 crop.left += insetL; 345 crop.top += insetT; 346 crop.right -= insetR; 347 crop.bottom -= insetB; 348 } 349 return crop; 350} 351 352void Layer::setGeometry( 353 const sp<const DisplayDevice>& hw, 354 HWComposer::HWCLayerInterface& layer) 355{ 356 layer.setDefaultState(); 357 358 // enable this layer 359 layer.setSkip(false); 360 361 if (isSecure() && !hw->isSecure()) { 362 layer.setSkip(true); 363 } 364 365 // this gives us only the "orientation" component of the transform 366 const State& s(getDrawingState()); 367 if (!isOpaque(s) || s.alpha != 0xFF) { 368 layer.setBlending(mPremultipliedAlpha ? 369 HWC_BLENDING_PREMULT : 370 HWC_BLENDING_COVERAGE); 371 } 372 373 // apply the layer's transform, followed by the display's global transform 374 // here we're guaranteed that the layer's transform preserves rects 375 Rect frame(s.transform.transform(computeBounds())); 376 frame.intersect(hw->getViewport(), &frame); 377 const Transform& tr(hw->getTransform()); 378 layer.setFrame(tr.transform(frame)); 379 layer.setCrop(computeCrop(hw)); 380 layer.setPlaneAlpha(s.alpha); 381 382 /* 383 * Transformations are applied in this order: 384 * 1) buffer orientation/flip/mirror 385 * 2) state transformation (window manager) 386 * 3) layer orientation (screen orientation) 387 * (NOTE: the matrices are multiplied in reverse order) 388 */ 389 390 const Transform bufferOrientation(mCurrentTransform); 391 Transform transform(tr * s.transform * bufferOrientation); 392 393 if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { 394 /* 395 * the code below applies the display's inverse transform to the buffer 396 */ 397 uint32_t invTransform = hw->getOrientationTransform(); 398 // calculate the inverse transform 399 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { 400 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | 401 NATIVE_WINDOW_TRANSFORM_FLIP_H; 402 } 403 // and apply to the current transform 404 transform = transform * Transform(invTransform); 405 } 406 407 // this gives us only the "orientation" component of the transform 408 const uint32_t orientation = transform.getOrientation(); 409 if (orientation & Transform::ROT_INVALID) { 410 // we can only handle simple transformation 411 layer.setSkip(true); 412 } else { 413 layer.setTransform(orientation); 414 } 415} 416 417void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, 418 HWComposer::HWCLayerInterface& layer) { 419 // we have to set the visible region on every frame because 420 // we currently free it during onLayerDisplayed(), which is called 421 // after HWComposer::commit() -- every frame. 422 // Apply this display's projection's viewport to the visible region 423 // before giving it to the HWC HAL. 424 const Transform& tr = hw->getTransform(); 425 Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); 426 layer.setVisibleRegionScreen(visible); 427 428 if (mSidebandStream.get()) { 429 layer.setSidebandStream(mSidebandStream); 430 } else { 431 // NOTE: buffer can be NULL if the client never drew into this 432 // layer yet, or if we ran out of memory 433 layer.setBuffer(mActiveBuffer); 434 } 435} 436 437void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */, 438 HWComposer::HWCLayerInterface& layer) { 439 int fenceFd = -1; 440 441 // TODO: there is a possible optimization here: we only need to set the 442 // acquire fence the first time a new buffer is acquired on EACH display. 443 444 if (layer.getCompositionType() == HWC_OVERLAY) { 445 sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence(); 446 if (fence->isValid()) { 447 fenceFd = fence->dup(); 448 if (fenceFd == -1) { 449 ALOGW("failed to dup layer fence, skipping sync: %d", errno); 450 } 451 } 452 } 453 layer.setAcquireFenceFd(fenceFd); 454} 455 456// --------------------------------------------------------------------------- 457// drawing... 458// --------------------------------------------------------------------------- 459 460void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const { 461 onDraw(hw, clip, false); 462} 463 464void Layer::draw(const sp<const DisplayDevice>& hw, 465 bool useIdentityTransform) const { 466 onDraw(hw, Region(hw->bounds()), useIdentityTransform); 467} 468 469void Layer::draw(const sp<const DisplayDevice>& hw) const { 470 onDraw(hw, Region(hw->bounds()), false); 471} 472 473void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, 474 bool useIdentityTransform) const 475{ 476 ATRACE_CALL(); 477 478 if (CC_UNLIKELY(mActiveBuffer == 0)) { 479 // the texture has not been created yet, this Layer has 480 // in fact never been drawn into. This happens frequently with 481 // SurfaceView because the WindowManager can't know when the client 482 // has drawn the first time. 483 484 // If there is nothing under us, we paint the screen in black, otherwise 485 // we just skip this update. 486 487 // figure out if there is something below us 488 Region under; 489 const SurfaceFlinger::LayerVector& drawingLayers( 490 mFlinger->mDrawingState.layersSortedByZ); 491 const size_t count = drawingLayers.size(); 492 for (size_t i=0 ; i<count ; ++i) { 493 const sp<Layer>& layer(drawingLayers[i]); 494 if (layer.get() == static_cast<Layer const*>(this)) 495 break; 496 under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); 497 } 498 // if not everything below us is covered, we plug the holes! 499 Region holes(clip.subtract(under)); 500 if (!holes.isEmpty()) { 501 clearWithOpenGL(hw, holes, 0, 0, 0, 1); 502 } 503 return; 504 } 505 506 // Bind the current buffer to the GL texture, and wait for it to be 507 // ready for us to draw into. 508 status_t err = mSurfaceFlingerConsumer->bindTextureImage(); 509 if (err != NO_ERROR) { 510 ALOGW("onDraw: bindTextureImage failed (err=%d)", err); 511 // Go ahead and draw the buffer anyway; no matter what we do the screen 512 // is probably going to have something visibly wrong. 513 } 514 515 bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure()); 516 517 RenderEngine& engine(mFlinger->getRenderEngine()); 518 519 if (!blackOutLayer) { 520 // TODO: we could be more subtle with isFixedSize() 521 const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize(); 522 523 // Query the texture matrix given our current filtering mode. 524 float textureMatrix[16]; 525 mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); 526 mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); 527 528 if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { 529 530 /* 531 * the code below applies the display's inverse transform to the texture transform 532 */ 533 534 // create a 4x4 transform matrix from the display transform flags 535 const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1); 536 const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1); 537 const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1); 538 539 mat4 tr; 540 uint32_t transform = hw->getOrientationTransform(); 541 if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) 542 tr = tr * rot90; 543 if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) 544 tr = tr * flipH; 545 if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) 546 tr = tr * flipV; 547 548 // calculate the inverse 549 tr = inverse(tr); 550 551 // and finally apply it to the original texture matrix 552 const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr); 553 memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix)); 554 } 555 556 // Set things up for texturing. 557 mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); 558 mTexture.setFiltering(useFiltering); 559 mTexture.setMatrix(textureMatrix); 560 561 engine.setupLayerTexturing(mTexture); 562 } else { 563 engine.setupLayerBlackedOut(); 564 } 565 drawWithOpenGL(hw, clip, useIdentityTransform); 566 engine.disableTexturing(); 567} 568 569 570void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, 571 const Region& /* clip */, float red, float green, float blue, 572 float alpha) const 573{ 574 RenderEngine& engine(mFlinger->getRenderEngine()); 575 computeGeometry(hw, mMesh, false); 576 engine.setupFillWithColor(red, green, blue, alpha); 577 engine.drawMesh(mMesh); 578} 579 580void Layer::clearWithOpenGL( 581 const sp<const DisplayDevice>& hw, const Region& clip) const { 582 clearWithOpenGL(hw, clip, 0,0,0,0); 583} 584 585void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, 586 const Region& /* clip */, bool useIdentityTransform) const { 587 const uint32_t fbHeight = hw->getHeight(); 588 const State& s(getDrawingState()); 589 590 computeGeometry(hw, mMesh, useIdentityTransform); 591 592 /* 593 * NOTE: the way we compute the texture coordinates here produces 594 * different results than when we take the HWC path -- in the later case 595 * the "source crop" is rounded to texel boundaries. 596 * This can produce significantly different results when the texture 597 * is scaled by a large amount. 598 * 599 * The GL code below is more logical (imho), and the difference with 600 * HWC is due to a limitation of the HWC API to integers -- a question 601 * is suspend is whether we should ignore this problem or revert to 602 * GL composition when a buffer scaling is applied (maybe with some 603 * minimal value)? Or, we could make GL behave like HWC -- but this feel 604 * like more of a hack. 605 */ 606 const Rect win(computeBounds()); 607 608 float left = float(win.left) / float(s.active.w); 609 float top = float(win.top) / float(s.active.h); 610 float right = float(win.right) / float(s.active.w); 611 float bottom = float(win.bottom) / float(s.active.h); 612 613 // TODO: we probably want to generate the texture coords with the mesh 614 // here we assume that we only have 4 vertices 615 Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>()); 616 texCoords[0] = vec2(left, 1.0f - top); 617 texCoords[1] = vec2(left, 1.0f - bottom); 618 texCoords[2] = vec2(right, 1.0f - bottom); 619 texCoords[3] = vec2(right, 1.0f - top); 620 621 RenderEngine& engine(mFlinger->getRenderEngine()); 622 engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha); 623 engine.drawMesh(mMesh); 624 engine.disableBlending(); 625} 626 627uint32_t Layer::getProducerStickyTransform() const { 628 int producerStickyTransform = 0; 629 int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform); 630 if (ret != OK) { 631 ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__, 632 strerror(-ret), ret); 633 return 0; 634 } 635 return static_cast<uint32_t>(producerStickyTransform); 636} 637 638void Layer::setFiltering(bool filtering) { 639 mFiltering = filtering; 640} 641 642bool Layer::getFiltering() const { 643 return mFiltering; 644} 645 646// As documented in libhardware header, formats in the range 647// 0x100 - 0x1FF are specific to the HAL implementation, and 648// are known to have no alpha channel 649// TODO: move definition for device-specific range into 650// hardware.h, instead of using hard-coded values here. 651#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF) 652 653bool Layer::getOpacityForFormat(uint32_t format) { 654 if (HARDWARE_IS_DEVICE_FORMAT(format)) { 655 return true; 656 } 657 switch (format) { 658 case HAL_PIXEL_FORMAT_RGBA_8888: 659 case HAL_PIXEL_FORMAT_BGRA_8888: 660 case HAL_PIXEL_FORMAT_sRGB_A_8888: 661 return false; 662 } 663 // in all other case, we have no blending (also for unknown formats) 664 return true; 665} 666 667// ---------------------------------------------------------------------------- 668// local state 669// ---------------------------------------------------------------------------- 670 671void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, 672 bool useIdentityTransform) const 673{ 674 const Layer::State& s(getDrawingState()); 675 const Transform tr(useIdentityTransform ? 676 hw->getTransform() : hw->getTransform() * s.transform); 677 const uint32_t hw_h = hw->getHeight(); 678 Rect win(s.active.w, s.active.h); 679 if (!s.active.crop.isEmpty()) { 680 win.intersect(s.active.crop, &win); 681 } 682 // subtract the transparent region and snap to the bounds 683 win = reduce(win, s.activeTransparentRegion); 684 685 Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); 686 position[0] = tr.transform(win.left, win.top); 687 position[1] = tr.transform(win.left, win.bottom); 688 position[2] = tr.transform(win.right, win.bottom); 689 position[3] = tr.transform(win.right, win.top); 690 for (size_t i=0 ; i<4 ; i++) { 691 position[i].y = hw_h - position[i].y; 692 } 693} 694 695bool Layer::isOpaque(const Layer::State& s) const 696{ 697 // if we don't have a buffer yet, we're translucent regardless of the 698 // layer's opaque flag. 699 if (mActiveBuffer == 0) { 700 return false; 701 } 702 703 // if the layer has the opaque flag, then we're always opaque, 704 // otherwise we use the current buffer's format. 705 return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity; 706} 707 708bool Layer::isProtected() const 709{ 710 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer); 711 return (activeBuffer != 0) && 712 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); 713} 714 715bool Layer::isFixedSize() const { 716 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; 717} 718 719bool Layer::isCropped() const { 720 return !mCurrentCrop.isEmpty(); 721} 722 723bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const { 724 return mNeedsFiltering || hw->needsFiltering(); 725} 726 727void Layer::setVisibleRegion(const Region& visibleRegion) { 728 // always called from main thread 729 this->visibleRegion = visibleRegion; 730} 731 732void Layer::setCoveredRegion(const Region& coveredRegion) { 733 // always called from main thread 734 this->coveredRegion = coveredRegion; 735} 736 737void Layer::setVisibleNonTransparentRegion(const Region& 738 setVisibleNonTransparentRegion) { 739 // always called from main thread 740 this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; 741} 742 743// ---------------------------------------------------------------------------- 744// transaction 745// ---------------------------------------------------------------------------- 746 747uint32_t Layer::doTransaction(uint32_t flags) { 748 ATRACE_CALL(); 749 750 const Layer::State& s(getDrawingState()); 751 const Layer::State& c(getCurrentState()); 752 753 const bool sizeChanged = (c.requested.w != s.requested.w) || 754 (c.requested.h != s.requested.h); 755 756 if (sizeChanged) { 757 // the size changed, we need to ask our client to request a new buffer 758 ALOGD_IF(DEBUG_RESIZE, 759 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" 760 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" 761 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n" 762 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" 763 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n", 764 this, getName().string(), mCurrentTransform, mCurrentScalingMode, 765 c.active.w, c.active.h, 766 c.active.crop.left, 767 c.active.crop.top, 768 c.active.crop.right, 769 c.active.crop.bottom, 770 c.active.crop.getWidth(), 771 c.active.crop.getHeight(), 772 c.requested.w, c.requested.h, 773 c.requested.crop.left, 774 c.requested.crop.top, 775 c.requested.crop.right, 776 c.requested.crop.bottom, 777 c.requested.crop.getWidth(), 778 c.requested.crop.getHeight(), 779 s.active.w, s.active.h, 780 s.active.crop.left, 781 s.active.crop.top, 782 s.active.crop.right, 783 s.active.crop.bottom, 784 s.active.crop.getWidth(), 785 s.active.crop.getHeight(), 786 s.requested.w, s.requested.h, 787 s.requested.crop.left, 788 s.requested.crop.top, 789 s.requested.crop.right, 790 s.requested.crop.bottom, 791 s.requested.crop.getWidth(), 792 s.requested.crop.getHeight()); 793 794 // record the new size, form this point on, when the client request 795 // a buffer, it'll get the new size. 796 mSurfaceFlingerConsumer->setDefaultBufferSize( 797 c.requested.w, c.requested.h); 798 } 799 800 if (!isFixedSize()) { 801 802 const bool resizePending = (c.requested.w != c.active.w) || 803 (c.requested.h != c.active.h); 804 805 if (resizePending) { 806 // don't let Layer::doTransaction update the drawing state 807 // if we have a pending resize, unless we are in fixed-size mode. 808 // the drawing state will be updated only once we receive a buffer 809 // with the correct size. 810 // 811 // in particular, we want to make sure the clip (which is part 812 // of the geometry state) is latched together with the size but is 813 // latched immediately when no resizing is involved. 814 815 flags |= eDontUpdateGeometryState; 816 } 817 } 818 819 // always set active to requested, unless we're asked not to 820 // this is used by Layer, which special cases resizes. 821 if (flags & eDontUpdateGeometryState) { 822 } else { 823 Layer::State& editCurrentState(getCurrentState()); 824 editCurrentState.active = c.requested; 825 } 826 827 if (s.active != c.active) { 828 // invalidate and recompute the visible regions if needed 829 flags |= Layer::eVisibleRegion; 830 } 831 832 if (c.sequence != s.sequence) { 833 // invalidate and recompute the visible regions if needed 834 flags |= eVisibleRegion; 835 this->contentDirty = true; 836 837 // we may use linear filtering, if the matrix scales us 838 const uint8_t type = c.transform.getType(); 839 mNeedsFiltering = (!c.transform.preserveRects() || 840 (type >= Transform::SCALE)); 841 } 842 843 // Commit the transaction 844 commitTransaction(); 845 return flags; 846} 847 848void Layer::commitTransaction() { 849 mDrawingState = mCurrentState; 850} 851 852uint32_t Layer::getTransactionFlags(uint32_t flags) { 853 return android_atomic_and(~flags, &mTransactionFlags) & flags; 854} 855 856uint32_t Layer::setTransactionFlags(uint32_t flags) { 857 return android_atomic_or(flags, &mTransactionFlags); 858} 859 860bool Layer::setPosition(float x, float y) { 861 if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) 862 return false; 863 mCurrentState.sequence++; 864 mCurrentState.transform.set(x, y); 865 setTransactionFlags(eTransactionNeeded); 866 return true; 867} 868bool Layer::setLayer(uint32_t z) { 869 if (mCurrentState.z == z) 870 return false; 871 mCurrentState.sequence++; 872 mCurrentState.z = z; 873 setTransactionFlags(eTransactionNeeded); 874 return true; 875} 876bool Layer::setSize(uint32_t w, uint32_t h) { 877 if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) 878 return false; 879 mCurrentState.requested.w = w; 880 mCurrentState.requested.h = h; 881 setTransactionFlags(eTransactionNeeded); 882 return true; 883} 884bool Layer::setAlpha(uint8_t alpha) { 885 if (mCurrentState.alpha == alpha) 886 return false; 887 mCurrentState.sequence++; 888 mCurrentState.alpha = alpha; 889 setTransactionFlags(eTransactionNeeded); 890 return true; 891} 892bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { 893 mCurrentState.sequence++; 894 mCurrentState.transform.set( 895 matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy); 896 setTransactionFlags(eTransactionNeeded); 897 return true; 898} 899bool Layer::setTransparentRegionHint(const Region& transparent) { 900 mCurrentState.requestedTransparentRegion = transparent; 901 setTransactionFlags(eTransactionNeeded); 902 return true; 903} 904bool Layer::setFlags(uint8_t flags, uint8_t mask) { 905 const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); 906 if (mCurrentState.flags == newFlags) 907 return false; 908 mCurrentState.sequence++; 909 mCurrentState.flags = newFlags; 910 setTransactionFlags(eTransactionNeeded); 911 return true; 912} 913bool Layer::setCrop(const Rect& crop) { 914 if (mCurrentState.requested.crop == crop) 915 return false; 916 mCurrentState.sequence++; 917 mCurrentState.requested.crop = crop; 918 setTransactionFlags(eTransactionNeeded); 919 return true; 920} 921 922bool Layer::setLayerStack(uint32_t layerStack) { 923 if (mCurrentState.layerStack == layerStack) 924 return false; 925 mCurrentState.sequence++; 926 mCurrentState.layerStack = layerStack; 927 setTransactionFlags(eTransactionNeeded); 928 return true; 929} 930 931// ---------------------------------------------------------------------------- 932// pageflip handling... 933// ---------------------------------------------------------------------------- 934 935bool Layer::onPreComposition() { 936 mRefreshPending = false; 937 return mQueuedFrames > 0 || mSidebandStreamChanged; 938} 939 940void Layer::onPostComposition() { 941 if (mFrameLatencyNeeded) { 942 nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); 943 mFrameTracker.setDesiredPresentTime(desiredPresentTime); 944 945 sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence(); 946 if (frameReadyFence->isValid()) { 947 mFrameTracker.setFrameReadyFence(frameReadyFence); 948 } else { 949 // There was no fence for this frame, so assume that it was ready 950 // to be presented at the desired present time. 951 mFrameTracker.setFrameReadyTime(desiredPresentTime); 952 } 953 954 const HWComposer& hwc = mFlinger->getHwComposer(); 955 sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); 956 if (presentFence->isValid()) { 957 mFrameTracker.setActualPresentFence(presentFence); 958 } else { 959 // The HWC doesn't support present fences, so use the refresh 960 // timestamp instead. 961 nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); 962 mFrameTracker.setActualPresentTime(presentTime); 963 } 964 965 mFrameTracker.advanceFrame(); 966 mFrameLatencyNeeded = false; 967 } 968} 969 970bool Layer::isVisible() const { 971 const Layer::State& s(mDrawingState); 972 return !(s.flags & layer_state_t::eLayerHidden) && s.alpha 973 && (mActiveBuffer != NULL || mSidebandStream != NULL); 974} 975 976Region Layer::latchBuffer(bool& recomputeVisibleRegions) 977{ 978 ATRACE_CALL(); 979 980 if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { 981 // mSidebandStreamChanged was true 982 mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); 983 } 984 985 Region outDirtyRegion; 986 if (mQueuedFrames > 0) { 987 988 // if we've already called updateTexImage() without going through 989 // a composition step, we have to skip this layer at this point 990 // because we cannot call updateTeximage() without a corresponding 991 // compositionComplete() call. 992 // we'll trigger an update in onPreComposition(). 993 if (mRefreshPending) { 994 return outDirtyRegion; 995 } 996 997 // Capture the old state of the layer for comparisons later 998 const State& s(getDrawingState()); 999 const bool oldOpacity = isOpaque(s); 1000 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; 1001 1002 struct Reject : public SurfaceFlingerConsumer::BufferRejecter { 1003 Layer::State& front; 1004 Layer::State& current; 1005 bool& recomputeVisibleRegions; 1006 bool stickyTransformSet; 1007 Reject(Layer::State& front, Layer::State& current, 1008 bool& recomputeVisibleRegions, bool stickySet) 1009 : front(front), current(current), 1010 recomputeVisibleRegions(recomputeVisibleRegions), 1011 stickyTransformSet(stickySet) { 1012 } 1013 1014 virtual bool reject(const sp<GraphicBuffer>& buf, 1015 const IGraphicBufferConsumer::BufferItem& item) { 1016 if (buf == NULL) { 1017 return false; 1018 } 1019 1020 uint32_t bufWidth = buf->getWidth(); 1021 uint32_t bufHeight = buf->getHeight(); 1022 1023 // check that we received a buffer of the right size 1024 // (Take the buffer's orientation into account) 1025 if (item.mTransform & Transform::ROT_90) { 1026 swap(bufWidth, bufHeight); 1027 } 1028 1029 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; 1030 if (front.active != front.requested) { 1031 1032 if (isFixedSize || 1033 (bufWidth == front.requested.w && 1034 bufHeight == front.requested.h)) 1035 { 1036 // Here we pretend the transaction happened by updating the 1037 // current and drawing states. Drawing state is only accessed 1038 // in this thread, no need to have it locked 1039 front.active = front.requested; 1040 1041 // We also need to update the current state so that 1042 // we don't end-up overwriting the drawing state with 1043 // this stale current state during the next transaction 1044 // 1045 // NOTE: We don't need to hold the transaction lock here 1046 // because State::active is only accessed from this thread. 1047 current.active = front.active; 1048 1049 // recompute visible region 1050 recomputeVisibleRegions = true; 1051 } 1052 1053 ALOGD_IF(DEBUG_RESIZE, 1054 "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n" 1055 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" 1056 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n", 1057 bufWidth, bufHeight, item.mTransform, item.mScalingMode, 1058 front.active.w, front.active.h, 1059 front.active.crop.left, 1060 front.active.crop.top, 1061 front.active.crop.right, 1062 front.active.crop.bottom, 1063 front.active.crop.getWidth(), 1064 front.active.crop.getHeight(), 1065 front.requested.w, front.requested.h, 1066 front.requested.crop.left, 1067 front.requested.crop.top, 1068 front.requested.crop.right, 1069 front.requested.crop.bottom, 1070 front.requested.crop.getWidth(), 1071 front.requested.crop.getHeight()); 1072 } 1073 1074 if (!isFixedSize && !stickyTransformSet) { 1075 if (front.active.w != bufWidth || 1076 front.active.h != bufHeight) { 1077 // reject this buffer 1078 ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}", 1079 bufWidth, bufHeight, front.active.w, front.active.h); 1080 return true; 1081 } 1082 } 1083 1084 // if the transparent region has changed (this test is 1085 // conservative, but that's fine, worst case we're doing 1086 // a bit of extra work), we latch the new one and we 1087 // trigger a visible-region recompute. 1088 if (!front.activeTransparentRegion.isTriviallyEqual( 1089 front.requestedTransparentRegion)) { 1090 front.activeTransparentRegion = front.requestedTransparentRegion; 1091 1092 // We also need to update the current state so that 1093 // we don't end-up overwriting the drawing state with 1094 // this stale current state during the next transaction 1095 // 1096 // NOTE: We don't need to hold the transaction lock here 1097 // because State::active is only accessed from this thread. 1098 current.activeTransparentRegion = front.activeTransparentRegion; 1099 1100 // recompute visible region 1101 recomputeVisibleRegions = true; 1102 } 1103 1104 return false; 1105 } 1106 }; 1107 1108 Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions, 1109 getProducerStickyTransform() != 0); 1110 1111 status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r, 1112 mFlinger->mPrimaryDispSync); 1113 if (updateResult == BufferQueue::PRESENT_LATER) { 1114 // Producer doesn't want buffer to be displayed yet. Signal a 1115 // layer update so we check again at the next opportunity. 1116 mFlinger->signalLayerUpdate(); 1117 return outDirtyRegion; 1118 } 1119 1120 // Decrement the queued-frames count. Signal another event if we 1121 // have more frames pending. 1122 if (android_atomic_dec(&mQueuedFrames) > 1) { 1123 mFlinger->signalLayerUpdate(); 1124 } 1125 1126 if (updateResult != NO_ERROR) { 1127 // something happened! 1128 recomputeVisibleRegions = true; 1129 return outDirtyRegion; 1130 } 1131 1132 // update the active buffer 1133 mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(); 1134 if (mActiveBuffer == NULL) { 1135 // this can only happen if the very first buffer was rejected. 1136 return outDirtyRegion; 1137 } 1138 1139 mRefreshPending = true; 1140 mFrameLatencyNeeded = true; 1141 if (oldActiveBuffer == NULL) { 1142 // the first time we receive a buffer, we need to trigger a 1143 // geometry invalidation. 1144 recomputeVisibleRegions = true; 1145 } 1146 1147 Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); 1148 const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); 1149 const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); 1150 if ((crop != mCurrentCrop) || 1151 (transform != mCurrentTransform) || 1152 (scalingMode != mCurrentScalingMode)) 1153 { 1154 mCurrentCrop = crop; 1155 mCurrentTransform = transform; 1156 mCurrentScalingMode = scalingMode; 1157 recomputeVisibleRegions = true; 1158 } 1159 1160 if (oldActiveBuffer != NULL) { 1161 uint32_t bufWidth = mActiveBuffer->getWidth(); 1162 uint32_t bufHeight = mActiveBuffer->getHeight(); 1163 if (bufWidth != uint32_t(oldActiveBuffer->width) || 1164 bufHeight != uint32_t(oldActiveBuffer->height)) { 1165 recomputeVisibleRegions = true; 1166 } 1167 } 1168 1169 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); 1170 if (oldOpacity != isOpaque(s)) { 1171 recomputeVisibleRegions = true; 1172 } 1173 1174 // FIXME: postedRegion should be dirty & bounds 1175 Region dirtyRegion(Rect(s.active.w, s.active.h)); 1176 1177 // transform the dirty region to window-manager space 1178 outDirtyRegion = (s.transform.transform(dirtyRegion)); 1179 } 1180 return outDirtyRegion; 1181} 1182 1183uint32_t Layer::getEffectiveUsage(uint32_t usage) const 1184{ 1185 // TODO: should we do something special if mSecure is set? 1186 if (mProtectedByApp) { 1187 // need a hardware-protected path to external video sink 1188 usage |= GraphicBuffer::USAGE_PROTECTED; 1189 } 1190 usage |= GraphicBuffer::USAGE_HW_COMPOSER; 1191 return usage; 1192} 1193 1194void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { 1195 uint32_t orientation = 0; 1196 if (!mFlinger->mDebugDisableTransformHint) { 1197 // The transform hint is used to improve performance, but we can 1198 // only have a single transform hint, it cannot 1199 // apply to all displays. 1200 const Transform& planeTransform(hw->getTransform()); 1201 orientation = planeTransform.getOrientation(); 1202 if (orientation & Transform::ROT_INVALID) { 1203 orientation = 0; 1204 } 1205 } 1206 mSurfaceFlingerConsumer->setTransformHint(orientation); 1207} 1208 1209// ---------------------------------------------------------------------------- 1210// debugging 1211// ---------------------------------------------------------------------------- 1212 1213void Layer::dump(String8& result, Colorizer& colorizer) const 1214{ 1215 const Layer::State& s(getDrawingState()); 1216 1217 colorizer.colorize(result, Colorizer::GREEN); 1218 result.appendFormat( 1219 "+ %s %p (%s)\n", 1220 getTypeId(), this, getName().string()); 1221 colorizer.reset(result); 1222 1223 s.activeTransparentRegion.dump(result, "transparentRegion"); 1224 visibleRegion.dump(result, "visibleRegion"); 1225 sp<Client> client(mClientRef.promote()); 1226 1227 result.appendFormat( " " 1228 "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " 1229 "isOpaque=%1d, invalidate=%1d, " 1230 "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n" 1231 " client=%p\n", 1232 s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, 1233 s.active.crop.left, s.active.crop.top, 1234 s.active.crop.right, s.active.crop.bottom, 1235 isOpaque(s), contentDirty, 1236 s.alpha, s.flags, 1237 s.transform[0][0], s.transform[0][1], 1238 s.transform[1][0], s.transform[1][1], 1239 client.get()); 1240 1241 sp<const GraphicBuffer> buf0(mActiveBuffer); 1242 uint32_t w0=0, h0=0, s0=0, f0=0; 1243 if (buf0 != 0) { 1244 w0 = buf0->getWidth(); 1245 h0 = buf0->getHeight(); 1246 s0 = buf0->getStride(); 1247 f0 = buf0->format; 1248 } 1249 result.appendFormat( 1250 " " 1251 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X]," 1252 " queued-frames=%d, mRefreshPending=%d\n", 1253 mFormat, w0, h0, s0,f0, 1254 mQueuedFrames, mRefreshPending); 1255 1256 if (mSurfaceFlingerConsumer != 0) { 1257 mSurfaceFlingerConsumer->dump(result, " "); 1258 } 1259} 1260 1261void Layer::dumpFrameStats(String8& result) const { 1262 mFrameTracker.dumpStats(result); 1263} 1264 1265void Layer::clearFrameStats() { 1266 mFrameTracker.clearStats(); 1267} 1268 1269void Layer::logFrameStats() { 1270 mFrameTracker.logAndResetStats(mName); 1271} 1272 1273void Layer::getFrameStats(FrameStats* outStats) const { 1274 mFrameTracker.getStats(outStats); 1275} 1276 1277// --------------------------------------------------------------------------- 1278 1279Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, 1280 const sp<Layer>& layer) 1281 : mFlinger(flinger), mLayer(layer) { 1282} 1283 1284Layer::LayerCleaner::~LayerCleaner() { 1285 // destroy client resources 1286 mFlinger->onLayerDestroyed(mLayer); 1287} 1288 1289// --------------------------------------------------------------------------- 1290}; // namespace android 1291 1292#if defined(__gl_h_) 1293#error "don't include gl/gl.h in this file" 1294#endif 1295 1296#if defined(__gl2_h_) 1297#error "don't include gl2/gl2.h in this file" 1298#endif 1299