diff options
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 196 |
1 files changed, 97 insertions, 99 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4062340..0825ec6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -36,13 +36,14 @@ #include <gui/Surface.h> #include "clz.h" -#include "DisplayHardware/DisplayHardware.h" -#include "DisplayHardware/HWComposer.h" +#include "DisplayDevice.h" #include "GLExtensions.h" #include "Layer.h" #include "SurfaceFlinger.h" #include "SurfaceTextureLayer.h" +#include "DisplayHardware/HWComposer.h" + #define DEBUG_RESIZE 0 namespace android { @@ -63,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, mFormat(PIXEL_FORMAT_NONE), mGLExtensions(GLExtensions::getInstance()), mOpaqueLayer(true), - mNeedsDithering(false), mSecure(false), mProtectedByApp(false) { @@ -71,14 +71,10 @@ Layer::Layer(SurfaceFlinger* flinger, glGenTextures(1, &mTextureName); } -void Layer::onLayerDisplayed() { - if (mFrameLatencyNeeded) { - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - mFrameStats[mFrameLatencyOffset].timestamp = mSurfaceTexture->getTimestamp(); - mFrameStats[mFrameLatencyOffset].set = systemTime(); - mFrameStats[mFrameLatencyOffset].vsync = hw.getRefreshTimestamp(); - mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128; - mFrameLatencyNeeded = false; +void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface* layer) { + if (layer) { + mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd()); } } @@ -117,8 +113,7 @@ void Layer::onFirstRef() Layer::~Layer() { - mFlinger->postMessageAsync( - new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) ); + mFlinger->deleteTextureAsync(mTextureName); } void Layer::onFrameQueued() { @@ -138,14 +133,6 @@ void Layer::setName(const String8& name) { mSurfaceTexture->setName(name); } -void Layer::validateVisibility(const Transform& globalTransform) { - LayerBase::validateVisibility(globalTransform); - - // This optimization allows the SurfaceTexture to bake in - // the rotation so hardware overlays can be used - mSurfaceTexture->setTransformHint(getTransformHint()); -} - sp<ISurface> Layer::createSurface() { class BSurface : public BnSurface, public LayerCleaner { @@ -183,10 +170,8 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, return err; } - // the display's pixel format - const DisplayHardware& hw(graphicPlane(0).displayHardware()); uint32_t const maxSurfaceDims = min( - hw.getMaxTextureSize(), hw.getMaxViewportDims()); + mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); // never allow a surface larger than what our underlying GL implementation // can handle. @@ -195,26 +180,17 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, return BAD_VALUE; } - PixelFormatInfo displayInfo; - getPixelFormatInfo(hw.getFormat(), &displayInfo); - const uint32_t hwFlags = hw.getFlags(); - mFormat = format; - mSecure = (flags & ISurfaceComposer::eSecure) ? true : false; - mProtectedByApp = (flags & ISurfaceComposer::eProtectedByApp) ? true : false; - mOpaqueLayer = (flags & ISurfaceComposer::eOpaque); + mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; + mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; + mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); mCurrentOpacity = getOpacityForFormat(format); mSurfaceTexture->setDefaultBufferSize(w, h); mSurfaceTexture->setDefaultBufferFormat(format); mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); - // we use the red index - int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED); - int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); - mNeedsDithering = layerRedsize > displayRedSize; - return NO_ERROR; } @@ -226,7 +202,8 @@ Rect Layer::computeBufferCrop() const { } else if (mActiveBuffer != NULL){ crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); } else { - crop = Rect(mTransformedBounds.width(), mTransformedBounds.height()); + crop.makeInvalid(); + return crop; } // ... then reduce that in the same proportions as the window crop reduces @@ -259,16 +236,19 @@ Rect Layer::computeBufferCrop() const { return crop; } -void Layer::setGeometry(hwc_layer_t* hwcl) +void Layer::setGeometry( + const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer) { - LayerBaseClient::setGeometry(hwcl); + LayerBaseClient::setGeometry(hw, layer); - hwcl->flags &= ~HWC_SKIP_LAYER; + // enable this layer + layer.setSkip(false); // we can't do alpha-fade with the hwc HAL const State& s(drawingState()); if (s.alpha < 0xFF) { - hwcl->flags = HWC_SKIP_LAYER; + layer.setSkip(true); } /* @@ -276,44 +256,52 @@ void Layer::setGeometry(hwc_layer_t* hwcl) * 1) buffer orientation/flip/mirror * 2) state transformation (window manager) * 3) layer orientation (screen orientation) - * mTransform is already the composition of (2) and (3) * (NOTE: the matrices are multiplied in reverse order) */ const Transform bufferOrientation(mCurrentTransform); - const Transform tr(mTransform * bufferOrientation); + const Transform tr(hw->getTransform() * s.transform * bufferOrientation); // this gives us only the "orientation" component of the transform const uint32_t finalTransform = tr.getOrientation(); // we can only handle simple transformation if (finalTransform & Transform::ROT_INVALID) { - hwcl->flags = HWC_SKIP_LAYER; + layer.setSkip(true); } else { - hwcl->transform = finalTransform; + layer.setTransform(finalTransform); } - - Rect crop = computeBufferCrop(); - hwcl->sourceCrop.left = crop.left; - hwcl->sourceCrop.top = crop.top; - hwcl->sourceCrop.right = crop.right; - hwcl->sourceCrop.bottom = crop.bottom; + layer.setCrop(computeBufferCrop()); } -void Layer::setPerFrameData(hwc_layer_t* hwcl) { +void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer) { const sp<GraphicBuffer>& buffer(mActiveBuffer); - if (buffer == NULL) { - // this can happen if the client never drew into this layer yet, - // or if we ran out of memory. In that case, don't let - // HWC handle it. - hwcl->flags |= HWC_SKIP_LAYER; - hwcl->handle = NULL; - } else { - hwcl->handle = buffer->handle; + // NOTE: buffer can be NULL if the client never drew into this + // layer yet, or if we ran out of memory + layer.setBuffer(buffer); +} + +void Layer::setAcquireFence(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface& layer) { + int fenceFd = -1; + + // TODO: there is a possible optimization here: we only need to set the + // acquire fence the first time a new buffer is acquired on EACH display. + + if (layer.getCompositionType() == HWC_OVERLAY) { + sp<Fence> fence = mSurfaceTexture->getCurrentFence(); + if (fence.get()) { + fenceFd = fence->dup(); + if (fenceFd == -1) { + ALOGW("failed to dup layer fence, skipping sync: %d", errno); + } + } } + layer.setAcquireFenceFd(fenceFd); } -void Layer::onDraw(const Region& clip) const +void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const { ATRACE_CALL(); @@ -335,16 +323,25 @@ void Layer::onDraw(const Region& clip) const const sp<LayerBase>& layer(drawingLayers[i]); if (layer.get() == static_cast<LayerBase const*>(this)) break; - under.orSelf(layer->visibleRegionScreen); + under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); } // if not everything below us is covered, we plug the holes! Region holes(clip.subtract(under)); if (!holes.isEmpty()) { - clearWithOpenGL(holes, 0, 0, 0, 1); + clearWithOpenGL(hw, holes, 0, 0, 0, 1); } return; } + // TODO: replace this with a server-side wait + sp<Fence> fence = mSurfaceTexture->getCurrentFence(); + if (fence.get()) { + status_t err = fence->wait(Fence::TIMEOUT_NEVER); + ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err); + // Go ahead and draw the buffer anyway; no matter what we do the screen + // is probably going to have something visibly wrong. + } + if (!isProtected()) { // TODO: we could be more subtle with isFixedSize() const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize(); @@ -376,7 +373,7 @@ void Layer::onDraw(const Region& clip) const glEnable(GL_TEXTURE_2D); } - drawWithOpenGL(clip); + drawWithOpenGL(hw, clip); glDisable(GL_TEXTURE_EXTERNAL_OES); glDisable(GL_TEXTURE_2D); @@ -514,10 +511,23 @@ bool Layer::onPreComposition() { return mQueuedFrames > 0; } -void Layer::lockPageFlip(bool& recomputeVisibleRegions) +void Layer::onPostComposition() { + if (mFrameLatencyNeeded) { + const HWComposer& hwc = mFlinger->getHwComposer(); + const size_t offset = mFrameLatencyOffset; + mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp(); + mFrameStats[offset].set = systemTime(); + mFrameStats[offset].vsync = hwc.getRefreshTimestamp(); + mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128; + mFrameLatencyNeeded = false; + } +} + +Region Layer::latchBuffer(bool& recomputeVisibleRegions) { ATRACE_CALL(); + Region outDirtyRegion; if (mQueuedFrames > 0) { // if we've already called updateTexImage() without going through @@ -526,8 +536,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) // compositionComplete() call. // we'll trigger an update in onPreComposition(). if (mRefreshPending) { - mPostedDirtyRegion.clear(); - return; + return outDirtyRegion; } // Capture the old state of the layer for comparisons later @@ -624,17 +633,21 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) Reject r(mDrawingState, currentState(), recomputeVisibleRegions); + // XXX: not sure if setTransformHint belongs here + // it should only be needed when the main screen orientation changes + mSurfaceTexture->setTransformHint(getTransformHint()); + if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) { // something happened! recomputeVisibleRegions = true; - return; + return outDirtyRegion; } // update the active buffer mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); if (mActiveBuffer == NULL) { // this can only happen if the very first buffer was rejected. - return; + return outDirtyRegion; } mRefreshPending = true; @@ -672,38 +685,17 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) recomputeVisibleRegions = true; } - // FIXME: mPostedDirtyRegion = dirty & bounds - const Layer::State& front(drawingState()); - mPostedDirtyRegion.set(front.active.w, front.active.h); - glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } -} -void Layer::unlockPageFlip( - const Transform& planeTransform, Region& outDirtyRegion) -{ - ATRACE_CALL(); + // FIXME: postedRegion should be dirty & bounds + const Layer::State& front(drawingState()); + Region dirtyRegion(Rect(front.active.w, front.active.h)); - Region postedRegion(mPostedDirtyRegion); - if (!postedRegion.isEmpty()) { - mPostedDirtyRegion.clear(); - if (!visibleRegionScreen.isEmpty()) { - // The dirty region is given in the layer's coordinate space - // transform the dirty region by the surface's transformation - // and the global transformation. - const Layer::State& s(drawingState()); - const Transform tr(planeTransform * s.transform); - postedRegion = tr.transform(postedRegion); - - // At this point, the dirty region is in screen space. - // Make sure it's constrained by the visible region (which - // is in screen space as well). - postedRegion.andSelf(visibleRegionScreen); - outDirtyRegion.orSelf(postedRegion); - } + // transform the dirty region to window-manager space + outDirtyRegion = (front.transform.transform(dirtyRegion)); } + return outDirtyRegion; } void Layer::dump(String8& result, char* buffer, size_t SIZE) const @@ -736,8 +728,7 @@ void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const { LayerBaseClient::dumpStats(result, buffer, SIZE); const size_t o = mFrameLatencyOffset; - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - const nsecs_t period = hw.getRefreshPeriod(); + const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod(); result.appendFormat("%lld\n", period); for (size_t i=0 ; i<128 ; i++) { const size_t index = (o+i) % 128; @@ -772,7 +763,14 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const uint32_t Layer::getTransformHint() const { uint32_t orientation = 0; if (!mFlinger->mDebugDisableTransformHint) { - orientation = getPlaneOrientation(); + // The transform hint is used to improve performance on the main + // display -- we can only have a single transform hint, it cannot + // apply to all displays. + // This is why we use the default display here. This is not an + // oversight. + sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); + const Transform& planeTransform(hw->getTransform()); + orientation = planeTransform.getOrientation(); if (orientation & Transform::ROT_INVALID) { orientation = 0; } |