2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 #include <sys/types.h>
24 #include <cutils/compiler.h>
25 #include <cutils/native_handle.h>
26 #include <cutils/properties.h>
28 #include <utils/Errors.h>
29 #include <utils/Log.h>
30 #include <utils/StopWatch.h>
31 #include <utils/Trace.h>
33 #include <ui/GraphicBuffer.h>
34 #include <ui/PixelFormat.h>
36 #include <gui/Surface.h>
39 #include "DisplayDevice.h"
40 #include "GLExtensions.h"
42 #include "SurfaceFlinger.h"
43 #include "SurfaceTextureLayer.h"
45 #include "DisplayHardware/HWComposer.h"
47 #define DEBUG_RESIZE 0
51 // ---------------------------------------------------------------------------
53 Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client)
54 : LayerBaseClient(flinger, client),
58 mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
59 mCurrentOpacity(true),
60 mRefreshPending(false),
61 mFrameLatencyNeeded(false),
62 mFrameLatencyOffset(0),
63 mFormat(PIXEL_FORMAT_NONE),
64 mGLExtensions(GLExtensions::getInstance()),
67 mProtectedByApp(false)
69 mCurrentCrop.makeInvalid();
70 glGenTextures(1, &mTextureName);
73 void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw,
74 HWComposer::HWCLayerInterface* layer) {
75 LayerBaseClient::onLayerDisplayed(hw, layer);
77 mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd());
81 void Layer::onFirstRef()
83 LayerBaseClient::onFirstRef();
85 struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener {
86 FrameQueuedListener(Layer* layer) : mLayer(layer) { }
89 virtual void onFrameAvailable() {
90 sp<Layer> that(mLayer.promote());
92 that->onFrameQueued();
97 // Creates a custom BufferQueue for SurfaceTexture to use
98 sp<BufferQueue> bq = new SurfaceTextureLayer();
99 mSurfaceTexture = new SurfaceTexture(mTextureName, true,
100 GL_TEXTURE_EXTERNAL_OES, false, bq);
102 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
103 mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
104 mSurfaceTexture->setSynchronousMode(true);
106 #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
107 #warning "disabling triple buffering"
108 mSurfaceTexture->setDefaultMaxBufferCount(2);
110 mSurfaceTexture->setDefaultMaxBufferCount(3);
113 updateTransformHint();
118 mFlinger->deleteTextureAsync(mTextureName);
121 void Layer::onFrameQueued() {
122 android_atomic_inc(&mQueuedFrames);
123 mFlinger->signalLayerUpdate();
126 // called with SurfaceFlinger::mStateLock as soon as the layer is entered
127 // in the purgatory list
128 void Layer::onRemoved()
130 mSurfaceTexture->abandon();
133 void Layer::setName(const String8& name) {
134 LayerBase::setName(name);
135 mSurfaceTexture->setName(name);
138 sp<ISurface> Layer::createSurface()
140 class BSurface : public BnSurface, public LayerCleaner {
141 wp<const Layer> mOwner;
142 virtual sp<ISurfaceTexture> getSurfaceTexture() const {
143 sp<ISurfaceTexture> res;
144 sp<const Layer> that( mOwner.promote() );
146 res = that->mSurfaceTexture->getBufferQueue();
151 BSurface(const sp<SurfaceFlinger>& flinger,
152 const sp<Layer>& layer)
153 : LayerCleaner(flinger, layer), mOwner(layer) { }
155 sp<ISurface> sur(new BSurface(mFlinger, this));
159 wp<IBinder> Layer::getSurfaceTextureBinder() const
161 return mSurfaceTexture->getBufferQueue()->asBinder();
164 status_t Layer::setBuffers( uint32_t w, uint32_t h,
165 PixelFormat format, uint32_t flags)
167 // this surfaces pixel format
168 PixelFormatInfo info;
169 status_t err = getPixelFormatInfo(format, &info);
171 ALOGE("unsupported pixelformat %d", format);
175 uint32_t const maxSurfaceDims = min(
176 mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
178 // never allow a surface larger than what our underlying GL implementation
180 if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
181 ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
187 mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
188 mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
189 mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
190 mCurrentOpacity = getOpacityForFormat(format);
192 mSurfaceTexture->setDefaultBufferSize(w, h);
193 mSurfaceTexture->setDefaultBufferFormat(format);
194 mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0));
199 Rect Layer::computeBufferCrop() const {
200 // Start with the SurfaceTexture's buffer crop...
202 if (!mCurrentCrop.isEmpty()) {
204 } else if (mActiveBuffer != NULL){
205 crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
211 // ... then reduce that in the same proportions as the window crop reduces
213 const State& s(drawingState());
214 if (!s.active.crop.isEmpty()) {
215 // Transform the window crop to match the buffer coordinate system,
216 // which means using the inverse of the current transform set on the
218 uint32_t invTransform = mCurrentTransform;
219 int winWidth = s.active.w;
220 int winHeight = s.active.h;
221 if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
222 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
223 NATIVE_WINDOW_TRANSFORM_FLIP_H;
224 winWidth = s.active.h;
225 winHeight = s.active.w;
227 Rect winCrop = s.active.crop.transform(invTransform,
228 s.active.w, s.active.h);
230 float xScale = float(crop.width()) / float(winWidth);
231 float yScale = float(crop.height()) / float(winHeight);
232 crop.left += int(ceilf(float(winCrop.left) * xScale));
233 crop.top += int(ceilf(float(winCrop.top) * yScale));
234 crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale));
235 crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale));
241 void Layer::setGeometry(
242 const sp<const DisplayDevice>& hw,
243 HWComposer::HWCLayerInterface& layer)
245 LayerBaseClient::setGeometry(hw, layer);
248 layer.setSkip(false);
250 // we can't do alpha-fade with the hwc HAL
251 const State& s(drawingState());
252 if (s.alpha < 0xFF) {
257 * Transformations are applied in this order:
258 * 1) buffer orientation/flip/mirror
259 * 2) state transformation (window manager)
260 * 3) layer orientation (screen orientation)
261 * (NOTE: the matrices are multiplied in reverse order)
264 const Transform bufferOrientation(mCurrentTransform);
265 const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
267 // this gives us only the "orientation" component of the transform
268 const uint32_t finalTransform = tr.getOrientation();
270 // we can only handle simple transformation
271 if (finalTransform & Transform::ROT_INVALID) {
274 layer.setTransform(finalTransform);
276 layer.setCrop(computeBufferCrop());
279 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
280 HWComposer::HWCLayerInterface& layer) {
281 LayerBaseClient::setPerFrameData(hw, layer);
282 // NOTE: buffer can be NULL if the client never drew into this
283 // layer yet, or if we ran out of memory
284 layer.setBuffer(mActiveBuffer);
287 void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
288 HWComposer::HWCLayerInterface& layer) {
291 // TODO: there is a possible optimization here: we only need to set the
292 // acquire fence the first time a new buffer is acquired on EACH display.
294 if (layer.getCompositionType() == HWC_OVERLAY) {
295 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
297 fenceFd = fence->dup();
299 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
303 layer.setAcquireFenceFd(fenceFd);
306 void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
310 if (CC_UNLIKELY(mActiveBuffer == 0)) {
311 // the texture has not been created yet, this Layer has
312 // in fact never been drawn into. This happens frequently with
313 // SurfaceView because the WindowManager can't know when the client
314 // has drawn the first time.
316 // If there is nothing under us, we paint the screen in black, otherwise
317 // we just skip this update.
319 // figure out if there is something below us
321 const SurfaceFlinger::LayerVector& drawingLayers(
322 mFlinger->mDrawingState.layersSortedByZ);
323 const size_t count = drawingLayers.size();
324 for (size_t i=0 ; i<count ; ++i) {
325 const sp<LayerBase>& layer(drawingLayers[i]);
326 if (layer.get() == static_cast<LayerBase const*>(this))
328 under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
330 // if not everything below us is covered, we plug the holes!
331 Region holes(clip.subtract(under));
332 if (!holes.isEmpty()) {
333 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
338 status_t err = mSurfaceTexture->doGLFenceWait();
340 ALOGE("onDraw: failed waiting for fence: %d", err);
341 // Go ahead and draw the buffer anyway; no matter what we do the screen
342 // is probably going to have something visibly wrong.
345 if (!isProtected()) {
346 // TODO: we could be more subtle with isFixedSize()
347 const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
349 // Query the texture matrix given our current filtering mode.
350 float textureMatrix[16];
351 mSurfaceTexture->setFilteringEnabled(useFiltering);
352 mSurfaceTexture->getTransformMatrix(textureMatrix);
354 // Set things up for texturing.
355 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
356 GLenum filter = GL_NEAREST;
360 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
361 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
362 glMatrixMode(GL_TEXTURE);
363 glLoadMatrixf(textureMatrix);
364 glMatrixMode(GL_MODELVIEW);
365 glDisable(GL_TEXTURE_2D);
366 glEnable(GL_TEXTURE_EXTERNAL_OES);
368 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
369 glMatrixMode(GL_TEXTURE);
371 glMatrixMode(GL_MODELVIEW);
372 glDisable(GL_TEXTURE_EXTERNAL_OES);
373 glEnable(GL_TEXTURE_2D);
376 drawWithOpenGL(hw, clip);
378 glDisable(GL_TEXTURE_EXTERNAL_OES);
379 glDisable(GL_TEXTURE_2D);
382 // As documented in libhardware header, formats in the range
383 // 0x100 - 0x1FF are specific to the HAL implementation, and
384 // are known to have no alpha channel
385 // TODO: move definition for device-specific range into
386 // hardware.h, instead of using hard-coded values here.
387 #define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
389 bool Layer::getOpacityForFormat(uint32_t format)
391 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
394 PixelFormatInfo info;
395 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
396 // in case of error (unknown format), we assume no blending
397 return (err || info.h_alpha <= info.l_alpha);
401 bool Layer::isOpaque() const
403 // if we don't have a buffer yet, we're translucent regardless of the
404 // layer's opaque flag.
405 if (mActiveBuffer == 0) {
409 // if the layer has the opaque flag, then we're always opaque,
410 // otherwise we use the current buffer's format.
411 return mOpaqueLayer || mCurrentOpacity;
414 bool Layer::isProtected() const
416 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
417 return (activeBuffer != 0) &&
418 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
421 uint32_t Layer::doTransaction(uint32_t flags)
425 const Layer::State& front(drawingState());
426 const Layer::State& temp(currentState());
428 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
429 (temp.requested.h != front.requested.h);
432 // the size changed, we need to ask our client to request a new buffer
433 ALOGD_IF(DEBUG_RESIZE,
434 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
435 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
436 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
437 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
438 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
439 this, (const char*) getName(), mCurrentTransform, mCurrentScalingMode,
440 temp.active.w, temp.active.h,
441 temp.active.crop.left,
442 temp.active.crop.top,
443 temp.active.crop.right,
444 temp.active.crop.bottom,
445 temp.active.crop.getWidth(),
446 temp.active.crop.getHeight(),
447 temp.requested.w, temp.requested.h,
448 temp.requested.crop.left,
449 temp.requested.crop.top,
450 temp.requested.crop.right,
451 temp.requested.crop.bottom,
452 temp.requested.crop.getWidth(),
453 temp.requested.crop.getHeight(),
454 front.active.w, front.active.h,
455 front.active.crop.left,
456 front.active.crop.top,
457 front.active.crop.right,
458 front.active.crop.bottom,
459 front.active.crop.getWidth(),
460 front.active.crop.getHeight(),
461 front.requested.w, front.requested.h,
462 front.requested.crop.left,
463 front.requested.crop.top,
464 front.requested.crop.right,
465 front.requested.crop.bottom,
466 front.requested.crop.getWidth(),
467 front.requested.crop.getHeight());
469 // record the new size, form this point on, when the client request
470 // a buffer, it'll get the new size.
471 mSurfaceTexture->setDefaultBufferSize(
472 temp.requested.w, temp.requested.h);
475 if (!isFixedSize()) {
477 const bool resizePending = (temp.requested.w != temp.active.w) ||
478 (temp.requested.h != temp.active.h);
481 // don't let LayerBase::doTransaction update the drawing state
482 // if we have a pending resize, unless we are in fixed-size mode.
483 // the drawing state will be updated only once we receive a buffer
484 // with the correct size.
486 // in particular, we want to make sure the clip (which is part
487 // of the geometry state) is latched together with the size but is
488 // latched immediately when no resizing is involved.
490 flags |= eDontUpdateGeometryState;
494 return LayerBase::doTransaction(flags);
497 bool Layer::isFixedSize() const {
498 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
501 bool Layer::isCropped() const {
502 return !mCurrentCrop.isEmpty();
505 // ----------------------------------------------------------------------------
506 // pageflip handling...
507 // ----------------------------------------------------------------------------
509 bool Layer::onPreComposition() {
510 mRefreshPending = false;
511 return mQueuedFrames > 0;
514 void Layer::onPostComposition() {
515 if (mFrameLatencyNeeded) {
516 const HWComposer& hwc = mFlinger->getHwComposer();
517 const size_t offset = mFrameLatencyOffset;
518 mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
519 mFrameStats[offset].set = systemTime();
520 mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
521 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
522 mFrameLatencyNeeded = false;
526 bool Layer::isVisible() const {
527 return LayerBaseClient::isVisible() && (mActiveBuffer != NULL);
530 Region Layer::latchBuffer(bool& recomputeVisibleRegions)
534 Region outDirtyRegion;
535 if (mQueuedFrames > 0) {
537 // if we've already called updateTexImage() without going through
538 // a composition step, we have to skip this layer at this point
539 // because we cannot call updateTeximage() without a corresponding
540 // compositionComplete() call.
541 // we'll trigger an update in onPreComposition().
542 if (mRefreshPending) {
543 return outDirtyRegion;
546 // Capture the old state of the layer for comparisons later
547 const bool oldOpacity = isOpaque();
548 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
550 // signal another event if we have more frames pending
551 if (android_atomic_dec(&mQueuedFrames) > 1) {
552 mFlinger->signalLayerUpdate();
555 struct Reject : public SurfaceTexture::BufferRejecter {
557 Layer::State& current;
558 bool& recomputeVisibleRegions;
559 Reject(Layer::State& front, Layer::State& current,
560 bool& recomputeVisibleRegions)
561 : front(front), current(current),
562 recomputeVisibleRegions(recomputeVisibleRegions) {
565 virtual bool reject(const sp<GraphicBuffer>& buf,
566 const BufferQueue::BufferItem& item) {
571 uint32_t bufWidth = buf->getWidth();
572 uint32_t bufHeight = buf->getHeight();
574 // check that we received a buffer of the right size
575 // (Take the buffer's orientation into account)
576 if (item.mTransform & Transform::ROT_90) {
577 swap(bufWidth, bufHeight);
581 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
582 if (front.active != front.requested) {
585 (bufWidth == front.requested.w &&
586 bufHeight == front.requested.h))
588 // Here we pretend the transaction happened by updating the
589 // current and drawing states. Drawing state is only accessed
590 // in this thread, no need to have it locked
591 front.active = front.requested;
593 // We also need to update the current state so that
594 // we don't end-up overwriting the drawing state with
595 // this stale current state during the next transaction
597 // NOTE: We don't need to hold the transaction lock here
598 // because State::active is only accessed from this thread.
599 current.active = front.active;
601 // recompute visible region
602 recomputeVisibleRegions = true;
605 ALOGD_IF(DEBUG_RESIZE,
606 "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
607 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
608 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
609 bufWidth, bufHeight, item.mTransform, item.mScalingMode,
610 front.active.w, front.active.h,
611 front.active.crop.left,
612 front.active.crop.top,
613 front.active.crop.right,
614 front.active.crop.bottom,
615 front.active.crop.getWidth(),
616 front.active.crop.getHeight(),
617 front.requested.w, front.requested.h,
618 front.requested.crop.left,
619 front.requested.crop.top,
620 front.requested.crop.right,
621 front.requested.crop.bottom,
622 front.requested.crop.getWidth(),
623 front.requested.crop.getHeight());
627 if (front.active.w != bufWidth ||
628 front.active.h != bufHeight) {
629 // reject this buffer
638 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
640 if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) {
641 // something happened!
642 recomputeVisibleRegions = true;
643 return outDirtyRegion;
646 // update the active buffer
647 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
648 if (mActiveBuffer == NULL) {
649 // this can only happen if the very first buffer was rejected.
650 return outDirtyRegion;
653 mRefreshPending = true;
654 mFrameLatencyNeeded = true;
655 if (oldActiveBuffer == NULL) {
656 // the first time we receive a buffer, we need to trigger a
657 // geometry invalidation.
658 recomputeVisibleRegions = true;
661 Rect crop(mSurfaceTexture->getCurrentCrop());
662 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
663 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
664 if ((crop != mCurrentCrop) ||
665 (transform != mCurrentTransform) ||
666 (scalingMode != mCurrentScalingMode))
669 mCurrentTransform = transform;
670 mCurrentScalingMode = scalingMode;
671 recomputeVisibleRegions = true;
674 if (oldActiveBuffer != NULL) {
675 uint32_t bufWidth = mActiveBuffer->getWidth();
676 uint32_t bufHeight = mActiveBuffer->getHeight();
677 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
678 bufHeight != uint32_t(oldActiveBuffer->height)) {
679 recomputeVisibleRegions = true;
683 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
684 if (oldOpacity != isOpaque()) {
685 recomputeVisibleRegions = true;
688 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
689 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
691 // FIXME: postedRegion should be dirty & bounds
692 const Layer::State& front(drawingState());
693 Region dirtyRegion(Rect(front.active.w, front.active.h));
695 // transform the dirty region to window-manager space
696 outDirtyRegion = (front.transform.transform(dirtyRegion));
698 return outDirtyRegion;
701 void Layer::dump(String8& result, char* buffer, size_t SIZE) const
703 LayerBaseClient::dump(result, buffer, SIZE);
705 sp<const GraphicBuffer> buf0(mActiveBuffer);
706 uint32_t w0=0, h0=0, s0=0, f0=0;
708 w0 = buf0->getWidth();
709 h0 = buf0->getHeight();
710 s0 = buf0->getStride();
713 snprintf(buffer, SIZE,
715 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
716 " queued-frames=%d, mRefreshPending=%d\n",
717 mFormat, w0, h0, s0,f0,
718 mQueuedFrames, mRefreshPending);
720 result.append(buffer);
722 if (mSurfaceTexture != 0) {
723 mSurfaceTexture->dump(result, " ", buffer, SIZE);
727 void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
729 LayerBaseClient::dumpStats(result, buffer, SIZE);
730 const size_t o = mFrameLatencyOffset;
731 const nsecs_t period =
732 mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
733 result.appendFormat("%lld\n", period);
734 for (size_t i=0 ; i<128 ; i++) {
735 const size_t index = (o+i) % 128;
736 const nsecs_t time_app = mFrameStats[index].timestamp;
737 const nsecs_t time_set = mFrameStats[index].set;
738 const nsecs_t time_vsync = mFrameStats[index].vsync;
739 result.appendFormat("%lld\t%lld\t%lld\n",
747 void Layer::clearStats()
749 LayerBaseClient::clearStats();
750 memset(mFrameStats, 0, sizeof(mFrameStats));
753 uint32_t Layer::getEffectiveUsage(uint32_t usage) const
755 // TODO: should we do something special if mSecure is set?
756 if (mProtectedByApp) {
757 // need a hardware-protected path to external video sink
758 usage |= GraphicBuffer::USAGE_PROTECTED;
760 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
764 void Layer::updateTransformHint() const {
765 uint32_t orientation = 0;
766 if (!mFlinger->mDebugDisableTransformHint) {
767 // The transform hint is used to improve performance on the main
768 // display -- we can only have a single transform hint, it cannot
769 // apply to all displays.
770 // This is why we use the default display here. This is not an
772 sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
773 const Transform& planeTransform(hw->getTransform());
774 orientation = planeTransform.getOrientation();
775 if (orientation & Transform::ROT_INVALID) {
779 mSurfaceTexture->setTransformHint(orientation);
782 // ---------------------------------------------------------------------------
785 }; // namespace android