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) {
256 if (isSecure() && !hw->isSecure()) {
261 * Transformations are applied in this order:
262 * 1) buffer orientation/flip/mirror
263 * 2) state transformation (window manager)
264 * 3) layer orientation (screen orientation)
265 * (NOTE: the matrices are multiplied in reverse order)
268 const Transform bufferOrientation(mCurrentTransform);
269 const Transform tr(hw->getTransform() * s.transform * bufferOrientation);
271 // this gives us only the "orientation" component of the transform
272 const uint32_t finalTransform = tr.getOrientation();
274 // we can only handle simple transformation
275 if (finalTransform & Transform::ROT_INVALID) {
278 layer.setTransform(finalTransform);
280 layer.setCrop(computeBufferCrop());
283 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
284 HWComposer::HWCLayerInterface& layer) {
285 LayerBaseClient::setPerFrameData(hw, layer);
286 // NOTE: buffer can be NULL if the client never drew into this
287 // layer yet, or if we ran out of memory
288 layer.setBuffer(mActiveBuffer);
291 void Layer::setAcquireFence(const sp<const DisplayDevice>& hw,
292 HWComposer::HWCLayerInterface& layer) {
295 // TODO: there is a possible optimization here: we only need to set the
296 // acquire fence the first time a new buffer is acquired on EACH display.
298 if (layer.getCompositionType() == HWC_OVERLAY) {
299 sp<Fence> fence = mSurfaceTexture->getCurrentFence();
301 fenceFd = fence->dup();
303 ALOGW("failed to dup layer fence, skipping sync: %d", errno);
307 layer.setAcquireFenceFd(fenceFd);
310 void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const
314 if (CC_UNLIKELY(mActiveBuffer == 0)) {
315 // the texture has not been created yet, this Layer has
316 // in fact never been drawn into. This happens frequently with
317 // SurfaceView because the WindowManager can't know when the client
318 // has drawn the first time.
320 // If there is nothing under us, we paint the screen in black, otherwise
321 // we just skip this update.
323 // figure out if there is something below us
325 const SurfaceFlinger::LayerVector& drawingLayers(
326 mFlinger->mDrawingState.layersSortedByZ);
327 const size_t count = drawingLayers.size();
328 for (size_t i=0 ; i<count ; ++i) {
329 const sp<LayerBase>& layer(drawingLayers[i]);
330 if (layer.get() == static_cast<LayerBase const*>(this))
332 under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
334 // if not everything below us is covered, we plug the holes!
335 Region holes(clip.subtract(under));
336 if (!holes.isEmpty()) {
337 clearWithOpenGL(hw, holes, 0, 0, 0, 1);
342 status_t err = mSurfaceTexture->doGLFenceWait();
344 ALOGE("onDraw: failed waiting for fence: %d", err);
345 // Go ahead and draw the buffer anyway; no matter what we do the screen
346 // is probably going to have something visibly wrong.
349 bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());
351 if (!blackOutLayer) {
352 // TODO: we could be more subtle with isFixedSize()
353 const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
355 // Query the texture matrix given our current filtering mode.
356 float textureMatrix[16];
357 mSurfaceTexture->setFilteringEnabled(useFiltering);
358 mSurfaceTexture->getTransformMatrix(textureMatrix);
360 // Set things up for texturing.
361 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName);
362 GLenum filter = GL_NEAREST;
366 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, filter);
367 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, filter);
368 glMatrixMode(GL_TEXTURE);
369 glLoadMatrixf(textureMatrix);
370 glMatrixMode(GL_MODELVIEW);
371 glDisable(GL_TEXTURE_2D);
372 glEnable(GL_TEXTURE_EXTERNAL_OES);
374 glBindTexture(GL_TEXTURE_2D, mFlinger->getProtectedTexName());
375 glMatrixMode(GL_TEXTURE);
377 glMatrixMode(GL_MODELVIEW);
378 glDisable(GL_TEXTURE_EXTERNAL_OES);
379 glEnable(GL_TEXTURE_2D);
382 drawWithOpenGL(hw, clip);
384 glDisable(GL_TEXTURE_EXTERNAL_OES);
385 glDisable(GL_TEXTURE_2D);
388 // As documented in libhardware header, formats in the range
389 // 0x100 - 0x1FF are specific to the HAL implementation, and
390 // are known to have no alpha channel
391 // TODO: move definition for device-specific range into
392 // hardware.h, instead of using hard-coded values here.
393 #define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
395 bool Layer::getOpacityForFormat(uint32_t format)
397 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
400 PixelFormatInfo info;
401 status_t err = getPixelFormatInfo(PixelFormat(format), &info);
402 // in case of error (unknown format), we assume no blending
403 return (err || info.h_alpha <= info.l_alpha);
407 bool Layer::isOpaque() const
409 // if we don't have a buffer yet, we're translucent regardless of the
410 // layer's opaque flag.
411 if (mActiveBuffer == 0) {
415 // if the layer has the opaque flag, then we're always opaque,
416 // otherwise we use the current buffer's format.
417 return mOpaqueLayer || mCurrentOpacity;
420 bool Layer::isProtected() const
422 const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
423 return (activeBuffer != 0) &&
424 (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
427 uint32_t Layer::doTransaction(uint32_t flags)
431 const Layer::State& front(drawingState());
432 const Layer::State& temp(currentState());
434 const bool sizeChanged = (temp.requested.w != front.requested.w) ||
435 (temp.requested.h != front.requested.h);
438 // the size changed, we need to ask our client to request a new buffer
439 ALOGD_IF(DEBUG_RESIZE,
440 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
441 " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
442 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
443 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
444 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
445 this, (const char*) getName(), mCurrentTransform, mCurrentScalingMode,
446 temp.active.w, temp.active.h,
447 temp.active.crop.left,
448 temp.active.crop.top,
449 temp.active.crop.right,
450 temp.active.crop.bottom,
451 temp.active.crop.getWidth(),
452 temp.active.crop.getHeight(),
453 temp.requested.w, temp.requested.h,
454 temp.requested.crop.left,
455 temp.requested.crop.top,
456 temp.requested.crop.right,
457 temp.requested.crop.bottom,
458 temp.requested.crop.getWidth(),
459 temp.requested.crop.getHeight(),
460 front.active.w, front.active.h,
461 front.active.crop.left,
462 front.active.crop.top,
463 front.active.crop.right,
464 front.active.crop.bottom,
465 front.active.crop.getWidth(),
466 front.active.crop.getHeight(),
467 front.requested.w, front.requested.h,
468 front.requested.crop.left,
469 front.requested.crop.top,
470 front.requested.crop.right,
471 front.requested.crop.bottom,
472 front.requested.crop.getWidth(),
473 front.requested.crop.getHeight());
475 // record the new size, form this point on, when the client request
476 // a buffer, it'll get the new size.
477 mSurfaceTexture->setDefaultBufferSize(
478 temp.requested.w, temp.requested.h);
481 if (!isFixedSize()) {
483 const bool resizePending = (temp.requested.w != temp.active.w) ||
484 (temp.requested.h != temp.active.h);
487 // don't let LayerBase::doTransaction update the drawing state
488 // if we have a pending resize, unless we are in fixed-size mode.
489 // the drawing state will be updated only once we receive a buffer
490 // with the correct size.
492 // in particular, we want to make sure the clip (which is part
493 // of the geometry state) is latched together with the size but is
494 // latched immediately when no resizing is involved.
496 flags |= eDontUpdateGeometryState;
500 return LayerBase::doTransaction(flags);
503 bool Layer::isFixedSize() const {
504 return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
507 bool Layer::isCropped() const {
508 return !mCurrentCrop.isEmpty();
511 // ----------------------------------------------------------------------------
512 // pageflip handling...
513 // ----------------------------------------------------------------------------
515 bool Layer::onPreComposition() {
516 mRefreshPending = false;
517 return mQueuedFrames > 0;
520 void Layer::onPostComposition() {
521 if (mFrameLatencyNeeded) {
522 const HWComposer& hwc = mFlinger->getHwComposer();
523 const size_t offset = mFrameLatencyOffset;
524 mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
525 mFrameStats[offset].set = systemTime();
526 mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
527 mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
528 mFrameLatencyNeeded = false;
532 bool Layer::isVisible() const {
533 return LayerBaseClient::isVisible() && (mActiveBuffer != NULL);
536 Region Layer::latchBuffer(bool& recomputeVisibleRegions)
540 Region outDirtyRegion;
541 if (mQueuedFrames > 0) {
543 // if we've already called updateTexImage() without going through
544 // a composition step, we have to skip this layer at this point
545 // because we cannot call updateTeximage() without a corresponding
546 // compositionComplete() call.
547 // we'll trigger an update in onPreComposition().
548 if (mRefreshPending) {
549 return outDirtyRegion;
552 // Capture the old state of the layer for comparisons later
553 const bool oldOpacity = isOpaque();
554 sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
556 // signal another event if we have more frames pending
557 if (android_atomic_dec(&mQueuedFrames) > 1) {
558 mFlinger->signalLayerUpdate();
561 struct Reject : public SurfaceTexture::BufferRejecter {
563 Layer::State& current;
564 bool& recomputeVisibleRegions;
565 Reject(Layer::State& front, Layer::State& current,
566 bool& recomputeVisibleRegions)
567 : front(front), current(current),
568 recomputeVisibleRegions(recomputeVisibleRegions) {
571 virtual bool reject(const sp<GraphicBuffer>& buf,
572 const BufferQueue::BufferItem& item) {
577 uint32_t bufWidth = buf->getWidth();
578 uint32_t bufHeight = buf->getHeight();
580 // check that we received a buffer of the right size
581 // (Take the buffer's orientation into account)
582 if (item.mTransform & Transform::ROT_90) {
583 swap(bufWidth, bufHeight);
587 bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
588 if (front.active != front.requested) {
591 (bufWidth == front.requested.w &&
592 bufHeight == front.requested.h))
594 // Here we pretend the transaction happened by updating the
595 // current and drawing states. Drawing state is only accessed
596 // in this thread, no need to have it locked
597 front.active = front.requested;
599 // We also need to update the current state so that
600 // we don't end-up overwriting the drawing state with
601 // this stale current state during the next transaction
603 // NOTE: We don't need to hold the transaction lock here
604 // because State::active is only accessed from this thread.
605 current.active = front.active;
607 // recompute visible region
608 recomputeVisibleRegions = true;
611 ALOGD_IF(DEBUG_RESIZE,
612 "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
613 " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
614 " requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
615 bufWidth, bufHeight, item.mTransform, item.mScalingMode,
616 front.active.w, front.active.h,
617 front.active.crop.left,
618 front.active.crop.top,
619 front.active.crop.right,
620 front.active.crop.bottom,
621 front.active.crop.getWidth(),
622 front.active.crop.getHeight(),
623 front.requested.w, front.requested.h,
624 front.requested.crop.left,
625 front.requested.crop.top,
626 front.requested.crop.right,
627 front.requested.crop.bottom,
628 front.requested.crop.getWidth(),
629 front.requested.crop.getHeight());
633 if (front.active.w != bufWidth ||
634 front.active.h != bufHeight) {
635 // reject this buffer
644 Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
646 if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) {
647 // something happened!
648 recomputeVisibleRegions = true;
649 return outDirtyRegion;
652 // update the active buffer
653 mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
654 if (mActiveBuffer == NULL) {
655 // this can only happen if the very first buffer was rejected.
656 return outDirtyRegion;
659 mRefreshPending = true;
660 mFrameLatencyNeeded = true;
661 if (oldActiveBuffer == NULL) {
662 // the first time we receive a buffer, we need to trigger a
663 // geometry invalidation.
664 recomputeVisibleRegions = true;
667 Rect crop(mSurfaceTexture->getCurrentCrop());
668 const uint32_t transform(mSurfaceTexture->getCurrentTransform());
669 const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
670 if ((crop != mCurrentCrop) ||
671 (transform != mCurrentTransform) ||
672 (scalingMode != mCurrentScalingMode))
675 mCurrentTransform = transform;
676 mCurrentScalingMode = scalingMode;
677 recomputeVisibleRegions = true;
680 if (oldActiveBuffer != NULL) {
681 uint32_t bufWidth = mActiveBuffer->getWidth();
682 uint32_t bufHeight = mActiveBuffer->getHeight();
683 if (bufWidth != uint32_t(oldActiveBuffer->width) ||
684 bufHeight != uint32_t(oldActiveBuffer->height)) {
685 recomputeVisibleRegions = true;
689 mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
690 if (oldOpacity != isOpaque()) {
691 recomputeVisibleRegions = true;
694 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
695 glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
697 // FIXME: postedRegion should be dirty & bounds
698 const Layer::State& front(drawingState());
699 Region dirtyRegion(Rect(front.active.w, front.active.h));
701 // transform the dirty region to window-manager space
702 outDirtyRegion = (front.transform.transform(dirtyRegion));
704 return outDirtyRegion;
707 void Layer::dump(String8& result, char* buffer, size_t SIZE) const
709 LayerBaseClient::dump(result, buffer, SIZE);
711 sp<const GraphicBuffer> buf0(mActiveBuffer);
712 uint32_t w0=0, h0=0, s0=0, f0=0;
714 w0 = buf0->getWidth();
715 h0 = buf0->getHeight();
716 s0 = buf0->getStride();
719 snprintf(buffer, SIZE,
721 "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
722 " queued-frames=%d, mRefreshPending=%d\n",
723 mFormat, w0, h0, s0,f0,
724 mQueuedFrames, mRefreshPending);
726 result.append(buffer);
728 if (mSurfaceTexture != 0) {
729 mSurfaceTexture->dump(result, " ", buffer, SIZE);
733 void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
735 LayerBaseClient::dumpStats(result, buffer, SIZE);
736 const size_t o = mFrameLatencyOffset;
737 const nsecs_t period =
738 mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
739 result.appendFormat("%lld\n", period);
740 for (size_t i=0 ; i<128 ; i++) {
741 const size_t index = (o+i) % 128;
742 const nsecs_t time_app = mFrameStats[index].timestamp;
743 const nsecs_t time_set = mFrameStats[index].set;
744 const nsecs_t time_vsync = mFrameStats[index].vsync;
745 result.appendFormat("%lld\t%lld\t%lld\n",
753 void Layer::clearStats()
755 LayerBaseClient::clearStats();
756 memset(mFrameStats, 0, sizeof(mFrameStats));
759 uint32_t Layer::getEffectiveUsage(uint32_t usage) const
761 // TODO: should we do something special if mSecure is set?
762 if (mProtectedByApp) {
763 // need a hardware-protected path to external video sink
764 usage |= GraphicBuffer::USAGE_PROTECTED;
766 usage |= GraphicBuffer::USAGE_HW_COMPOSER;
770 void Layer::updateTransformHint() const {
771 uint32_t orientation = 0;
772 if (!mFlinger->mDebugDisableTransformHint) {
773 // The transform hint is used to improve performance on the main
774 // display -- we can only have a single transform hint, it cannot
775 // apply to all displays.
776 // This is why we use the default display here. This is not an
778 sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
779 const Transform& planeTransform(hw->getTransform());
780 orientation = planeTransform.getOrientation();
781 if (orientation & Transform::ROT_INVALID) {
785 mSurfaceTexture->setTransformHint(orientation);
788 // ---------------------------------------------------------------------------
791 }; // namespace android