diff options
author | Mathias Agopian <mathias@google.com> | 2013-03-05 17:47:11 -0800 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2013-03-05 19:52:30 -0800 |
commit | 13127d8921356dff794250e04208c3ed60b3a3df (patch) | |
tree | b9026d22b58ef884d8bfb0f7eacf2bc3b08ffa17 /services/surfaceflinger/Layer.cpp | |
parent | 2f73af9212487c81d31d07227fa8a2f4abc77638 (diff) | |
download | frameworks_native-13127d8921356dff794250e04208c3ed60b3a3df.zip frameworks_native-13127d8921356dff794250e04208c3ed60b3a3df.tar.gz frameworks_native-13127d8921356dff794250e04208c3ed60b3a3df.tar.bz2 |
Get rid of LayerBase.
The functionality of LayerBase and Layer is folded
into Layer. There wasn't a need for this abstraction
anymore.
Change-Id: I66511c08cc3d89009ba4deabf47e26cd4cfeaefb
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 683 |
1 files changed, 584 insertions, 99 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6245b6b..44ef0b8 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -19,6 +19,7 @@ #include <stdlib.h> #include <stdint.h> #include <sys/types.h> +#include <math.h> #include <cutils/compiler.h> #include <cutils/native_handle.h> @@ -49,37 +50,39 @@ namespace android { // --------------------------------------------------------------------------- +int32_t Layer::sSequence = 1; + Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client) - : LayerBase(flinger, client), + : contentDirty(false), + sequence(uint32_t(android_atomic_inc(&sSequence))), + mFlinger(flinger), mTextureName(-1U), + mPremultipliedAlpha(true), + mName("unnamed"), + mDebug(false), + mFormat(PIXEL_FORMAT_NONE), + mGLExtensions(GLExtensions::getInstance()), + mOpaqueLayer(true), + mTransactionFlags(0), mQueuedFrames(0), mCurrentTransform(0), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentOpacity(true), mRefreshPending(false), mFrameLatencyNeeded(false), - mFormat(PIXEL_FORMAT_NONE), - mGLExtensions(GLExtensions::getInstance()), - mOpaqueLayer(true), + mFiltering(false), + mNeedsFiltering(false), mSecure(false), - mProtectedByApp(false) + mProtectedByApp(false), + mHasSurface(false), + mClientRef(client) { mCurrentCrop.makeInvalid(); glGenTextures(1, &mTextureName); } -void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface* layer) { - LayerBase::onLayerDisplayed(hw, layer); - if (layer) { - mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd()); - } -} - void Layer::onFirstRef() { - LayerBase::onFirstRef(); - // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<BufferQueue> bq = new SurfaceTextureLayer(); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true, @@ -102,9 +105,25 @@ void Layer::onFirstRef() Layer::~Layer() { + sp<Client> c(mClientRef.promote()); + if (c != 0) { + c->detachLayer(this); + } mFlinger->deleteTextureAsync(mTextureName); } +// --------------------------------------------------------------------------- +// callbacks +// --------------------------------------------------------------------------- + +void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface* layer) { + if (layer) { + layer->onDisplayed(); + mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd()); + } +} + void Layer::onFrameAvailable() { android_atomic_inc(&mQueuedFrames); mFlinger->signalLayerUpdate(); @@ -112,18 +131,83 @@ void Layer::onFrameAvailable() { // called with SurfaceFlinger::mStateLock as soon as the layer is entered // in the purgatory list -void Layer::onRemoved() -{ +void Layer::onRemoved() { mSurfaceFlingerConsumer->abandon(); } +// --------------------------------------------------------------------------- +// set-up +// --------------------------------------------------------------------------- + void Layer::setName(const String8& name) { - LayerBase::setName(name); + mName = name; mSurfaceFlingerConsumer->setName(name); } -sp<ISurface> Layer::createSurface() +String8 Layer::getName() const { + return mName; +} + +void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) +{ + uint32_t layerFlags = 0; + if (flags & ISurfaceComposerClient::eHidden) + layerFlags = layer_state_t::eLayerHidden; + + if (flags & ISurfaceComposerClient::eNonPremultiplied) + mPremultipliedAlpha = false; + + mCurrentState.active.w = w; + mCurrentState.active.h = h; + mCurrentState.active.crop.makeInvalid(); + mCurrentState.z = 0; + mCurrentState.alpha = 0xFF; + mCurrentState.layerStack = 0; + mCurrentState.flags = layerFlags; + mCurrentState.sequence = 0; + mCurrentState.transform.set(0, 0); + mCurrentState.requested = mCurrentState.active; + + // drawing state & current state are identical + mDrawingState = mCurrentState; +} + +status_t Layer::setBuffers( uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags) { + // this surfaces pixel format + PixelFormatInfo info; + status_t err = getPixelFormatInfo(format, &info); + if (err) { + ALOGE("unsupported pixelformat %d", format); + return err; + } + + uint32_t const maxSurfaceDims = min( + mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); + + // never allow a surface larger than what our underlying GL implementation + // can handle. + if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { + ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); + return BAD_VALUE; + } + + mFormat = format; + + mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; + mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; + mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); + mCurrentOpacity = getOpacityForFormat(format); + + mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); + mSurfaceFlingerConsumer->setDefaultBufferFormat(format); + mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + + return NO_ERROR; +} + +sp<ISurface> Layer::createSurface() { /* * This class provides an implementation of BnSurface (the "native" or * "remote" side of the Binder IPC interface ISurface), and mixes in @@ -159,46 +243,27 @@ sp<ISurface> Layer::createSurface() return sur; } -wp<IBinder> Layer::getSurfaceTextureBinder() const -{ +wp<IBinder> Layer::getSurfaceTextureBinder() const { return mSurfaceFlingerConsumer->getBufferQueue()->asBinder(); } -status_t Layer::setBuffers( uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags) +sp<ISurface> Layer::getSurface() { - // this surfaces pixel format - PixelFormatInfo info; - status_t err = getPixelFormatInfo(format, &info); - if (err) { - ALOGE("unsupported pixelformat %d", format); - return err; - } + sp<ISurface> s; + Mutex::Autolock _l(mLock); - uint32_t const maxSurfaceDims = min( - mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims()); + LOG_ALWAYS_FATAL_IF(mHasSurface, + "Layer::getSurface() has already been called"); - // never allow a surface larger than what our underlying GL implementation - // can handle. - if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) { - ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h)); - return BAD_VALUE; - } - - mFormat = format; - - mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; - mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; - mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); - mCurrentOpacity = getOpacityForFormat(format); - - mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); - mSurfaceFlingerConsumer->setDefaultBufferFormat(format); - mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - - return NO_ERROR; + mHasSurface = true; + s = createSurface(); + return s; } +// --------------------------------------------------------------------------- +// h/w composer set-up +// --------------------------------------------------------------------------- + Rect Layer::getContentCrop() const { // this is the crop rectangle that applies to the buffer // itself (as opposed to the window) @@ -220,11 +285,85 @@ uint32_t Layer::getContentTransform() const { return mCurrentTransform; } +Rect Layer::computeBounds() const { + const Layer::State& s(drawingState()); + Rect win(s.active.w, s.active.h); + if (!s.active.crop.isEmpty()) { + win.intersect(s.active.crop, &win); + } + return win; +} + +Rect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { + /* + * The way we compute the crop (aka. texture coordinates when we have a + * Layer) produces a different output from the GL code in + * drawWithOpenGL() due to HWC being limited to integers. The difference + * can be large if getContentTransform() contains a large scale factor. + * See comments in drawWithOpenGL() for more details. + */ + + // the content crop is the area of the content that gets scaled to the + // layer's size. + Rect crop(getContentCrop()); + + // the active.crop is the area of the window that gets cropped, but not + // scaled in any ways. + const State& s(drawingState()); + + // apply the projection's clipping to the window crop in + // layerstack space, and convert-back to layer space. + // if there are no window scaling (or content scaling) involved, + // this operation will map to full pixels in the buffer. + // NOTE: should we revert to GL composition if a scaling is involved + // since it cannot be represented in the HWC API? + Rect activeCrop(s.transform.transform(s.active.crop)); + activeCrop.intersect(hw->getViewport(), &activeCrop); + activeCrop = s.transform.inverse().transform(activeCrop); + + // paranoia: make sure the window-crop is constrained in the + // window's bounds + activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); + + if (!activeCrop.isEmpty()) { + // Transform the window crop to match the buffer coordinate system, + // which means using the inverse of the current transform set on the + // SurfaceFlingerConsumer. + uint32_t invTransform = getContentTransform(); + int winWidth = s.active.w; + int winHeight = s.active.h; + if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | + NATIVE_WINDOW_TRANSFORM_FLIP_H; + winWidth = s.active.h; + winHeight = s.active.w; + } + const Rect winCrop = activeCrop.transform( + invTransform, s.active.w, s.active.h); + + // the code below essentially performs a scaled intersection + // of crop and winCrop + float xScale = float(crop.width()) / float(winWidth); + float yScale = float(crop.height()) / float(winHeight); + + int insetL = int(ceilf( winCrop.left * xScale)); + int insetT = int(ceilf( winCrop.top * yScale)); + int insetR = int(ceilf((winWidth - winCrop.right ) * xScale)); + int insetB = int(ceilf((winHeight - winCrop.bottom) * yScale)); + + crop.left += insetL; + crop.top += insetT; + crop.right -= insetR; + crop.bottom -= insetB; + } + return crop; +} + void Layer::setGeometry( const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer) { - LayerBase::setGeometry(hw, layer); + layer.setDefaultState(); // enable this layer layer.setSkip(false); @@ -233,7 +372,21 @@ void Layer::setGeometry( layer.setSkip(true); } + // this gives us only the "orientation" component of the transform const State& s(drawingState()); + if (!isOpaque() || s.alpha != 0xFF) { + layer.setBlending(mPremultipliedAlpha ? + HWC_BLENDING_PREMULT : + HWC_BLENDING_COVERAGE); + } + + // apply the layer's transform, followed by the display's global transform + // here we're guaranteed that the layer's transform preserves rects + Rect frame(s.transform.transform(computeBounds())); + frame.intersect(hw->getViewport(), &frame); + const Transform& tr(hw->getTransform()); + layer.setFrame(tr.transform(frame)); + layer.setCrop(computeCrop(hw)); layer.setPlaneAlpha(s.alpha); /* @@ -245,22 +398,29 @@ void Layer::setGeometry( */ const Transform bufferOrientation(mCurrentTransform); - const Transform tr(hw->getTransform() * s.transform * bufferOrientation); + const Transform transform(tr * 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) { + const uint32_t orientation = transform.getOrientation(); + if (orientation & Transform::ROT_INVALID) { + // we can only handle simple transformation layer.setSkip(true); } else { - layer.setTransform(finalTransform); + layer.setTransform(orientation); } } void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer) { - LayerBase::setPerFrameData(hw, layer); + // we have to set the visible region on every frame because + // we currently free it during onLayerDisplayed(), which is called + // after HWComposer::commit() -- every frame. + // Apply this display's projection's viewport to the visible region + // before giving it to the HWC HAL. + const Transform& tr = hw->getTransform(); + Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); + layer.setVisibleRegionScreen(visible); + // NOTE: buffer can be NULL if the client never drew into this // layer yet, or if we ran out of memory layer.setBuffer(mActiveBuffer); @@ -285,6 +445,18 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& hw, layer.setAcquireFenceFd(fenceFd); } +// --------------------------------------------------------------------------- +// drawing... +// --------------------------------------------------------------------------- + +void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const { + onDraw(hw, clip); +} + +void Layer::draw(const sp<const DisplayDevice>& hw) { + onDraw( hw, Region(hw->bounds()) ); +} + void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const { ATRACE_CALL(); @@ -304,8 +476,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const mFlinger->mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); for (size_t i=0 ; i<count ; ++i) { - const sp<LayerBase>& layer(drawingLayers[i]); - if (layer.get() == static_cast<LayerBase const*>(this)) + const sp<Layer>& layer(drawingLayers[i]); + if (layer.get() == static_cast<Layer const*>(this)) break; under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); } @@ -365,6 +537,119 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const glDisable(GL_TEXTURE_2D); } + +void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip, + GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) const +{ + const uint32_t fbHeight = hw->getHeight(); + glColor4f(red,green,blue,alpha); + + glDisable(GL_TEXTURE_EXTERNAL_OES); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + LayerMesh mesh; + computeGeometry(hw, &mesh); + + glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); + glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); +} + +void Layer::clearWithOpenGL( + const sp<const DisplayDevice>& hw, const Region& clip) const { + clearWithOpenGL(hw, clip, 0,0,0,0); +} + +void Layer::drawWithOpenGL( + const sp<const DisplayDevice>& hw, const Region& clip) const { + const uint32_t fbHeight = hw->getHeight(); + const State& s(drawingState()); + + GLenum src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA; + if (CC_UNLIKELY(s.alpha < 0xFF)) { + const GLfloat alpha = s.alpha * (1.0f/255.0f); + if (mPremultipliedAlpha) { + glColor4f(alpha, alpha, alpha, alpha); + } else { + glColor4f(1, 1, 1, alpha); + } + glEnable(GL_BLEND); + glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } else { + glColor4f(1, 1, 1, 1); + glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + if (!isOpaque()) { + glEnable(GL_BLEND); + glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA); + } else { + glDisable(GL_BLEND); + } + } + + LayerMesh mesh; + computeGeometry(hw, &mesh); + + // TODO: we probably want to generate the texture coords with the mesh + // here we assume that we only have 4 vertices + + struct TexCoords { + GLfloat u; + GLfloat v; + }; + + + /* + * NOTE: the way we compute the texture coordinates here produces + * different results than when we take the HWC path -- in the later case + * the "source crop" is rounded to texel boundaries. + * This can produce significantly different results when the texture + * is scaled by a large amount. + * + * The GL code below is more logical (imho), and the difference with + * HWC is due to a limitation of the HWC API to integers -- a question + * is suspend is wether we should ignore this problem or revert to + * GL composition when a buffer scaling is applied (maybe with some + * minimal value)? Or, we could make GL behave like HWC -- but this feel + * like more of a hack. + */ + const Rect win(computeBounds()); + + GLfloat left = GLfloat(win.left) / GLfloat(s.active.w); + GLfloat top = GLfloat(win.top) / GLfloat(s.active.h); + GLfloat right = GLfloat(win.right) / GLfloat(s.active.w); + GLfloat bottom = GLfloat(win.bottom) / GLfloat(s.active.h); + + TexCoords texCoords[4]; + texCoords[0].u = left; + texCoords[0].v = top; + texCoords[1].u = left; + texCoords[1].v = bottom; + texCoords[2].u = right; + texCoords[2].v = bottom; + texCoords[3].u = right; + texCoords[3].v = top; + for (int i = 0; i < 4; i++) { + texCoords[i].v = 1.0f - texCoords[i].v; + } + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); + glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); + glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisable(GL_BLEND); +} + +void Layer::setFiltering(bool filtering) { + mFiltering = filtering; +} + +bool Layer::getFiltering() const { + return mFiltering; +} + // As documented in libhardware header, formats in the range // 0x100 - 0x1FF are specific to the HAL implementation, and // are known to have no alpha channel @@ -383,6 +668,29 @@ bool Layer::getOpacityForFormat(uint32_t format) return (err || info.h_alpha <= info.l_alpha); } +// ---------------------------------------------------------------------------- +// local state +// ---------------------------------------------------------------------------- + +void Layer::computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const +{ + const Layer::State& s(drawingState()); + const Transform tr(hw->getTransform() * s.transform); + const uint32_t hw_h = hw->getHeight(); + Rect win(s.active.w, s.active.h); + if (!s.active.crop.isEmpty()) { + win.intersect(s.active.crop, &win); + } + if (mesh) { + tr.transform(mesh->mVertices[0], win.left, win.top); + tr.transform(mesh->mVertices[1], win.left, win.bottom); + tr.transform(mesh->mVertices[2], win.right, win.bottom); + tr.transform(mesh->mVertices[3], win.right, win.top); + for (size_t i=0 ; i<4 ; i++) { + mesh->mVertices[i][1] = hw_h - mesh->mVertices[i][1]; + } + } +} bool Layer::isOpaque() const { @@ -404,8 +712,39 @@ bool Layer::isProtected() const (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); } -uint32_t Layer::doTransaction(uint32_t flags) -{ +bool Layer::isFixedSize() const { + return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; +} + +bool Layer::isCropped() const { + return !mCurrentCrop.isEmpty(); +} + +bool Layer::needsFiltering(const sp<const DisplayDevice>& hw) const { + return mNeedsFiltering || hw->needsFiltering(); +} + +void Layer::setVisibleRegion(const Region& visibleRegion) { + // always called from main thread + this->visibleRegion = visibleRegion; +} + +void Layer::setCoveredRegion(const Region& coveredRegion) { + // always called from main thread + this->coveredRegion = coveredRegion; +} + +void Layer::setVisibleNonTransparentRegion(const Region& + setVisibleNonTransparentRegion) { + // always called from main thread + this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; +} + +// ---------------------------------------------------------------------------- +// transaction +// ---------------------------------------------------------------------------- + +uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); const Layer::State& front(drawingState()); @@ -464,7 +803,7 @@ uint32_t Layer::doTransaction(uint32_t flags) (temp.requested.h != temp.active.h); if (resizePending) { - // don't let LayerBase::doTransaction update the drawing state + // don't let Layer::doTransaction update the drawing state // if we have a pending resize, unless we are in fixed-size mode. // the drawing state will be updated only once we receive a buffer // with the correct size. @@ -477,15 +816,117 @@ uint32_t Layer::doTransaction(uint32_t flags) } } - return LayerBase::doTransaction(flags); + // always set active to requested, unless we're asked not to + // this is used by Layer, which special cases resizes. + if (flags & eDontUpdateGeometryState) { + } else { + Layer::State& editTemp(currentState()); + editTemp.active = temp.requested; + } + + if (front.active != temp.active) { + // invalidate and recompute the visible regions if needed + flags |= Layer::eVisibleRegion; + } + + if (temp.sequence != front.sequence) { + // invalidate and recompute the visible regions if needed + flags |= eVisibleRegion; + this->contentDirty = true; + + // we may use linear filtering, if the matrix scales us + const uint8_t type = temp.transform.getType(); + mNeedsFiltering = (!temp.transform.preserveRects() || + (type >= Transform::SCALE)); + } + + // Commit the transaction + commitTransaction(); + return flags; } -bool Layer::isFixedSize() const { - return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; +void Layer::commitTransaction() { + mDrawingState = mCurrentState; } -bool Layer::isCropped() const { - return !mCurrentCrop.isEmpty(); +uint32_t Layer::getTransactionFlags(uint32_t flags) { + return android_atomic_and(~flags, &mTransactionFlags) & flags; +} + +uint32_t Layer::setTransactionFlags(uint32_t flags) { + return android_atomic_or(flags, &mTransactionFlags); +} + +bool Layer::setPosition(float x, float y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) + return false; + mCurrentState.sequence++; + mCurrentState.transform.set(x, y); + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setLayer(uint32_t z) { + if (mCurrentState.z == z) + return false; + mCurrentState.sequence++; + mCurrentState.z = z; + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setSize(uint32_t w, uint32_t h) { + if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) + return false; + mCurrentState.requested.w = w; + mCurrentState.requested.h = h; + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setAlpha(uint8_t alpha) { + if (mCurrentState.alpha == alpha) + return false; + mCurrentState.sequence++; + mCurrentState.alpha = alpha; + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { + mCurrentState.sequence++; + mCurrentState.transform.set( + matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy); + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setTransparentRegionHint(const Region& transparent) { + mCurrentState.sequence++; + mCurrentState.transparentRegion = transparent; + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setFlags(uint8_t flags, uint8_t mask) { + const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); + if (mCurrentState.flags == newFlags) + return false; + mCurrentState.sequence++; + mCurrentState.flags = newFlags; + setTransactionFlags(eTransactionNeeded); + return true; +} +bool Layer::setCrop(const Rect& crop) { + if (mCurrentState.requested.crop == crop) + return false; + mCurrentState.sequence++; + mCurrentState.requested.crop = crop; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool Layer::setLayerStack(uint32_t layerStack) { + if (mCurrentState.layerStack == layerStack) + return false; + mCurrentState.sequence++; + mCurrentState.layerStack = layerStack; + setTransactionFlags(eTransactionNeeded); + return true; } // ---------------------------------------------------------------------------- @@ -528,7 +969,9 @@ void Layer::onPostComposition() { } bool Layer::isVisible() const { - return LayerBase::isVisible() && (mActiveBuffer != NULL); + const Layer::State& s(mDrawingState); + return !(s.flags & layer_state_t::eLayerHidden) && s.alpha + && (mActiveBuffer != NULL); } Region Layer::latchBuffer(bool& recomputeVisibleRegions) @@ -702,9 +1145,64 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return outDirtyRegion; } +uint32_t Layer::getEffectiveUsage(uint32_t usage) const +{ + // TODO: should we do something special if mSecure is set? + if (mProtectedByApp) { + // need a hardware-protected path to external video sink + usage |= GraphicBuffer::USAGE_PROTECTED; + } + usage |= GraphicBuffer::USAGE_HW_COMPOSER; + return usage; +} + +void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { + uint32_t orientation = 0; + if (!mFlinger->mDebugDisableTransformHint) { + // The transform hint is used to improve performance, but we can + // only have a single transform hint, it cannot + // apply to all displays. + const Transform& planeTransform(hw->getTransform()); + orientation = planeTransform.getOrientation(); + if (orientation & Transform::ROT_INVALID) { + orientation = 0; + } + } + mSurfaceFlingerConsumer->setTransformHint(orientation); +} + +// ---------------------------------------------------------------------------- +// debugging +// ---------------------------------------------------------------------------- + void Layer::dump(String8& result, char* buffer, size_t SIZE) const { - LayerBase::dump(result, buffer, SIZE); + const Layer::State& s(drawingState()); + + snprintf(buffer, SIZE, + "+ %s %p (%s)\n", + getTypeId(), this, getName().string()); + result.append(buffer); + + s.transparentRegion.dump(result, "transparentRegion"); + visibleRegion.dump(result, "visibleRegion"); + sp<Client> client(mClientRef.promote()); + + snprintf(buffer, SIZE, + " " + "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " + "isOpaque=%1d, invalidate=%1d, " + "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n" + " client=%p\n", + s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, + s.active.crop.left, s.active.crop.top, + s.active.crop.right, s.active.crop.bottom, + isOpaque(), contentDirty, + s.alpha, s.flags, + s.transform[0][0], s.transform[0][1], + s.transform[1][0], s.transform[1][1], + client.get()); + result.append(buffer); sp<const GraphicBuffer> buf0(mActiveBuffer); uint32_t w0=0, h0=0, s0=0, f0=0; @@ -728,42 +1226,29 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const } } -void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const -{ - LayerBase::dumpStats(result, buffer, SIZE); + +void Layer::shortDump(String8& result, char* scratch, size_t size) const { + Layer::dump(result, scratch, size); +} + +void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const { mFrameTracker.dump(result); } -void Layer::clearStats() -{ - LayerBase::clearStats(); +void Layer::clearStats() { mFrameTracker.clear(); } -uint32_t Layer::getEffectiveUsage(uint32_t usage) const -{ - // TODO: should we do something special if mSecure is set? - if (mProtectedByApp) { - // need a hardware-protected path to external video sink - usage |= GraphicBuffer::USAGE_PROTECTED; - } - usage |= GraphicBuffer::USAGE_HW_COMPOSER; - return usage; +// --------------------------------------------------------------------------- + +Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, + const sp<Layer>& layer) + : mFlinger(flinger), mLayer(layer) { } -void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const { - uint32_t orientation = 0; - if (!mFlinger->mDebugDisableTransformHint) { - // The transform hint is used to improve performance, but we can - // only have a single transform hint, it cannot - // apply to all displays. - const Transform& planeTransform(hw->getTransform()); - orientation = planeTransform.getOrientation(); - if (orientation & Transform::ROT_INVALID) { - orientation = 0; - } - } - mSurfaceFlingerConsumer->setTransformHint(orientation); +Layer::LayerCleaner::~LayerCleaner() { + // destroy client resources + mFlinger->onLayerDestroyed(mLayer); } // --------------------------------------------------------------------------- |