diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 4f6cf85f6..5ff8154e7 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -7,7 +7,6 @@ LOCAL_SRC_FILES:= \ EventThread.cpp \ FrameTracker.cpp \ Layer.cpp \ - LayerBase.cpp \ LayerDim.cpp \ DisplayHardware/FramebufferSurface.cpp \ DisplayHardware/HWComposer.cpp \ diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 287b33097..0575e352d 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -23,7 +23,6 @@ #include "Client.h" #include "Layer.h" -#include "LayerBase.h" #include "SurfaceFlinger.h" namespace android { @@ -43,7 +42,7 @@ Client::~Client() { const size_t count = mLayers.size(); for (size_t i=0 ; i layer(mLayers.valueAt(i).promote()); + sp layer(mLayers.valueAt(i).promote()); if (layer != 0) { mFlinger->removeLayer(layer); } @@ -54,13 +53,13 @@ status_t Client::initCheck() const { return NO_ERROR; } -void Client::attachLayer(const sp& handle, const sp& layer) +void Client::attachLayer(const sp& handle, const sp& layer) { Mutex::Autolock _l(mLock); mLayers.add(handle, layer); } -void Client::detachLayer(const LayerBase* layer) +void Client::detachLayer(const Layer* layer) { Mutex::Autolock _l(mLock); // we do a linear search here, because this doesn't happen often @@ -72,11 +71,11 @@ void Client::detachLayer(const LayerBase* layer) } } } -sp Client::getLayerUser(const sp& handle) const +sp Client::getLayerUser(const sp& handle) const { Mutex::Autolock _l(mLock); - sp lbc; - wp layer(mLayers.valueFor(handle)); + sp lbc; + wp layer(mLayers.valueFor(handle)); if (layer != 0) { lbc = layer.promote(); ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get()); diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 43f8fb753..4f34b8659 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -30,7 +30,7 @@ namespace android { // --------------------------------------------------------------------------- -class LayerBase; +class Layer; class SurfaceFlinger; // --------------------------------------------------------------------------- @@ -44,11 +44,11 @@ public: status_t initCheck() const; // protected by SurfaceFlinger::mStateLock - void attachLayer(const sp& handle, const sp& layer); + void attachLayer(const sp& handle, const sp& layer); - void detachLayer(const LayerBase* layer); + void detachLayer(const Layer* layer); - sp getLayerUser(const sp& handle) const; + sp getLayerUser(const sp& handle) const; private: // ISurfaceComposerClient interface @@ -66,7 +66,7 @@ private: sp mFlinger; // protected by mLock - DefaultKeyedVector< wp, wp > mLayers; + DefaultKeyedVector< wp, wp > mLayers; // thread-safe mutable Mutex mLock; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index ed2768c9c..2bbe49cde 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -42,7 +42,7 @@ #include "DisplayDevice.h" #include "GLExtensions.h" #include "SurfaceFlinger.h" -#include "LayerBase.h" +#include "Layer.h" // ---------------------------------------------------------------------------- using namespace android; @@ -282,19 +282,19 @@ void DisplayDevice::setViewportAndProjection(const sp& hw) // ---------------------------------------------------------------------------- -void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp >& layers) { +void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp >& layers) { mVisibleLayersSortedByZ = layers; mSecureLayerVisible = false; size_t count = layers.size(); for (size_t i=0 ; i& layer(layers[i]); + const sp& layer(layers[i]); if (layer->isSecure()) { mSecureLayerVisible = true; } } } -const Vector< sp >& DisplayDevice::getVisibleLayersSortedByZ() const { +const Vector< sp >& DisplayDevice::getVisibleLayersSortedByZ() const { return mVisibleLayersSortedByZ; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 91f34db93..f67101705 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -38,7 +38,7 @@ namespace android { class DisplayInfo; class FramebufferSurface; -class LayerBase; +class Layer; class SurfaceFlinger; class HWComposer; @@ -99,8 +99,8 @@ public: EGLSurface getEGLSurface() const; - void setVisibleLayersSortedByZ(const Vector< sp >& layers); - const Vector< sp >& getVisibleLayersSortedByZ() const; + void setVisibleLayersSortedByZ(const Vector< sp >& layers); + const Vector< sp >& getVisibleLayersSortedByZ() const; bool getSecureLayerVisible() const; Region getDirtyRegion(bool repaintEverything) const; @@ -186,7 +186,7 @@ private: */ // list of visible layers on that display - Vector< sp > mVisibleLayersSortedByZ; + Vector< sp > mVisibleLayersSortedByZ; // Whether we have a visible secure layer on this display bool mSecureLayerVisible; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 11f65f624..bb567e270 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -41,7 +41,6 @@ #include #include "Layer.h" // needed only for debugging -#include "LayerBase.h" #include "HWComposer.h" #include "SurfaceFlinger.h" #include @@ -925,7 +924,7 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { for (size_t i=0 ; i >& visibleLayersSortedByZ = + const Vector< sp >& visibleLayersSortedByZ = mFlinger->getLayerSortedByZForHwcDisplay(i); if (disp.connected) { @@ -949,13 +948,11 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { String8 name("unknown"); if (i < visibleLayersSortedByZ.size()) { - const sp& layer(visibleLayersSortedByZ[i]); - if (layer->getLayer() != NULL) { - const sp& buffer( - layer->getLayer()->getActiveBuffer()); - if (buffer != NULL) { - format = buffer->getPixelFormat(); - } + const sp& layer(visibleLayersSortedByZ[i]); + const sp& buffer( + layer->getActiveBuffer()); + if (buffer != NULL) { + format = buffer->getPixelFormat(); } name = layer->getName(); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index f7ed1aa0b..9816a45b5 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -47,7 +47,6 @@ namespace android { class GraphicBuffer; class Fence; -class LayerBase; class Region; class String8; class SurfaceFlinger; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6245b6bce..44ef0b879 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -49,37 +50,39 @@ namespace android { // --------------------------------------------------------------------------- +int32_t Layer::sSequence = 1; + Layer::Layer(SurfaceFlinger* flinger, const sp& 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& 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 bq = new SurfaceTextureLayer(); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true, @@ -102,9 +105,25 @@ void Layer::onFirstRef() Layer::~Layer() { + sp c(mClientRef.promote()); + if (c != 0) { + c->detachLayer(this); + } mFlinger->deleteTextureAsync(mTextureName); } +// --------------------------------------------------------------------------- +// callbacks +// --------------------------------------------------------------------------- + +void Layer::onLayerDisplayed(const sp& hw, + HWComposer::HWCLayerInterface* layer) { + if (layer) { + layer->onDisplayed(); + mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFenceFd()); + } +} + void Layer::onFrameAvailable() { android_atomic_inc(&mQueuedFrames); mFlinger->signalLayerUpdate(); @@ -112,56 +131,45 @@ 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 Layer::createSurface() -{ - /* - * This class provides an implementation of BnSurface (the "native" or - * "remote" side of the Binder IPC interface ISurface), and mixes in - * LayerCleaner to ensure that mFlinger->onLayerDestroyed() is called for - * this layer when the BSurface is destroyed. - * - * The idea is to provide a handle to the Layer through ISurface that - * is cleaned up automatically when the last reference to the ISurface - * goes away. (The references will be held on the "proxy" side, while - * the Layer exists on the "native" side.) - * - * The Layer has a reference to an instance of SurfaceFlinger's variant - * of GLConsumer, which holds a reference to the BufferQueue. The - * getSurfaceTexture() call returns a Binder interface reference for - * the producer interface of the buffer queue associated with the Layer. - */ - class BSurface : public BnSurface, public LayerCleaner { - wp mOwner; - virtual sp getSurfaceTexture() const { - sp res; - sp that( mOwner.promote() ); - if (that != NULL) { - res = that->mSurfaceFlingerConsumer->getBufferQueue(); - } - return res; - } - public: - BSurface(const sp& flinger, - const sp& layer) - : LayerCleaner(flinger, layer), mOwner(layer) { } - }; - sp sur(new BSurface(mFlinger, this)); - return sur; +String8 Layer::getName() const { + return mName; } -wp Layer::getSurfaceTextureBinder() const +void Layer::initStates(uint32_t w, uint32_t h, uint32_t flags) { - return mSurfaceFlingerConsumer->getBufferQueue()->asBinder(); + 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, @@ -199,6 +207,63 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, return NO_ERROR; } +sp Layer::createSurface() { + /* + * This class provides an implementation of BnSurface (the "native" or + * "remote" side of the Binder IPC interface ISurface), and mixes in + * LayerCleaner to ensure that mFlinger->onLayerDestroyed() is called for + * this layer when the BSurface is destroyed. + * + * The idea is to provide a handle to the Layer through ISurface that + * is cleaned up automatically when the last reference to the ISurface + * goes away. (The references will be held on the "proxy" side, while + * the Layer exists on the "native" side.) + * + * The Layer has a reference to an instance of SurfaceFlinger's variant + * of GLConsumer, which holds a reference to the BufferQueue. The + * getSurfaceTexture() call returns a Binder interface reference for + * the producer interface of the buffer queue associated with the Layer. + */ + class BSurface : public BnSurface, public LayerCleaner { + wp mOwner; + virtual sp getSurfaceTexture() const { + sp res; + sp that( mOwner.promote() ); + if (that != NULL) { + res = that->mSurfaceFlingerConsumer->getBufferQueue(); + } + return res; + } + public: + BSurface(const sp& flinger, + const sp& layer) + : LayerCleaner(flinger, layer), mOwner(layer) { } + }; + sp sur(new BSurface(mFlinger, this)); + return sur; +} + +wp Layer::getSurfaceTextureBinder() const { + return mSurfaceFlingerConsumer->getBufferQueue()->asBinder(); +} + +sp Layer::getSurface() +{ + sp s; + Mutex::Autolock _l(mLock); + + LOG_ALWAYS_FATAL_IF(mHasSurface, + "Layer::getSurface() has already been called"); + + 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& 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& 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& 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& hw, layer.setAcquireFenceFd(fenceFd); } +// --------------------------------------------------------------------------- +// drawing... +// --------------------------------------------------------------------------- + +void Layer::draw(const sp& hw, const Region& clip) const { + onDraw(hw, clip); +} + +void Layer::draw(const sp& hw) { + onDraw( hw, Region(hw->bounds()) ); +} + void Layer::onDraw(const sp& hw, const Region& clip) const { ATRACE_CALL(); @@ -304,8 +476,8 @@ void Layer::onDraw(const sp& hw, const Region& clip) const mFlinger->mDrawingState.layersSortedByZ); const size_t count = drawingLayers.size(); for (size_t i=0 ; i& layer(drawingLayers[i]); - if (layer.get() == static_cast(this)) + const sp& layer(drawingLayers[i]); + if (layer.get() == static_cast(this)) break; under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); } @@ -365,6 +537,119 @@ void Layer::onDraw(const sp& hw, const Region& clip) const glDisable(GL_TEXTURE_2D); } + +void Layer::clearWithOpenGL(const sp& 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& hw, const Region& clip) const { + clearWithOpenGL(hw, clip, 0,0,0,0); +} + +void Layer::drawWithOpenGL( + const sp& 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& 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& 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,44 +1145,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return outDirtyRegion; } -void Layer::dump(String8& result, char* buffer, size_t SIZE) const -{ - LayerBase::dump(result, buffer, SIZE); - - sp buf0(mActiveBuffer); - uint32_t w0=0, h0=0, s0=0, f0=0; - if (buf0 != 0) { - w0 = buf0->getWidth(); - h0 = buf0->getHeight(); - s0 = buf0->getStride(); - f0 = buf0->format; - } - snprintf(buffer, SIZE, - " " - "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X]," - " queued-frames=%d, mRefreshPending=%d\n", - mFormat, w0, h0, s0,f0, - mQueuedFrames, mRefreshPending); - - result.append(buffer); - - if (mSurfaceFlingerConsumer != 0) { - mSurfaceFlingerConsumer->dump(result, " ", buffer, SIZE); - } -} - -void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const -{ - LayerBase::dumpStats(result, buffer, SIZE); - mFrameTracker.dump(result); -} - -void Layer::clearStats() -{ - LayerBase::clearStats(); - mFrameTracker.clear(); -} - uint32_t Layer::getEffectiveUsage(uint32_t usage) const { // TODO: should we do something special if mSecure is set? @@ -766,6 +1171,86 @@ void Layer::updateTransformHint(const sp& hw) const { mSurfaceFlingerConsumer->setTransformHint(orientation); } +// ---------------------------------------------------------------------------- +// debugging +// ---------------------------------------------------------------------------- + +void Layer::dump(String8& result, char* buffer, size_t SIZE) const +{ + 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(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 buf0(mActiveBuffer); + uint32_t w0=0, h0=0, s0=0, f0=0; + if (buf0 != 0) { + w0 = buf0->getWidth(); + h0 = buf0->getHeight(); + s0 = buf0->getStride(); + f0 = buf0->format; + } + snprintf(buffer, SIZE, + " " + "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X]," + " queued-frames=%d, mRefreshPending=%d\n", + mFormat, w0, h0, s0,f0, + mQueuedFrames, mRefreshPending); + + result.append(buffer); + + if (mSurfaceFlingerConsumer != 0) { + mSurfaceFlingerConsumer->dump(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() { + mFrameTracker.clear(); +} + +// --------------------------------------------------------------------------- + +Layer::LayerCleaner::LayerCleaner(const sp& flinger, + const sp& layer) + : mFlinger(flinger), mLayer(layer) { +} + +Layer::LayerCleaner::~LayerCleaner() { + // destroy client resources + mFlinger->onLayerDestroyed(mLayer); +} + // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e9eab17fc..5fb6d8b68 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -20,118 +20,356 @@ #include #include -#include - -#include -#include - -#include - #include #include #include #include -#include "SurfaceFlingerConsumer.h" +#include +#include +#include + +#include +#include +#include + +#include + +#include + #include "FrameTracker.h" -#include "LayerBase.h" +#include "Client.h" +#include "SurfaceFlinger.h" +#include "SurfaceFlingerConsumer.h" #include "SurfaceTextureLayer.h" #include "Transform.h" +#include "DisplayHardware/HWComposer.h" + namespace android { // --------------------------------------------------------------------------- class Client; +class DisplayDevice; +class GraphicBuffer; +class SurfaceFlinger; class GLExtensions; // --------------------------------------------------------------------------- /* - * The Layer class is essentially a LayerBase combined with a BufferQueue. * A new BufferQueue and a new SurfaceFlingerConsumer are created when the * Layer is first referenced. * * This also implements onFrameAvailable(), which notifies SurfaceFlinger * that new data has arrived. */ -class Layer : public LayerBase, - public SurfaceFlingerConsumer::FrameAvailableListener -{ +class Layer : public SurfaceFlingerConsumer::FrameAvailableListener { + static int32_t sSequence; + public: + mutable bool contentDirty; + // regions below are in window-manager space + Region visibleRegion; + Region coveredRegion; + Region visibleNonTransparentRegion; + int32_t sequence; + + enum { // flags for doTransaction() + eDontUpdateGeometryState = 0x00000001, + eVisibleRegion = 0x00000002, + }; + + struct Geometry { + uint32_t w; + uint32_t h; + Rect crop; + inline bool operator ==(const Geometry& rhs) const { + return (w == rhs.w && h == rhs.h && crop == rhs.crop); + } + inline bool operator !=(const Geometry& rhs) const { + return !operator ==(rhs); + } + }; + + struct State { + Geometry active; + Geometry requested; + uint32_t z; + uint32_t layerStack; + uint8_t alpha; + uint8_t flags; + uint8_t reserved[2]; + int32_t sequence; // changes when visible regions can change + Transform transform; + Region transparentRegion; + }; + + class LayerMesh { + friend class Layer; + GLfloat mVertices[4][2]; + size_t mNumVertices; + public: + LayerMesh() : + mNumVertices(4) { + } + GLfloat const* getVertices() const { + return &mVertices[0][0]; + } + size_t getVertexCount() const { + return mNumVertices; + } + }; + + // ----------------------------------------------------------------------- + Layer(SurfaceFlinger* flinger, const sp& client); virtual ~Layer(); - virtual const char* getTypeId() const { return "Layer"; } - // the this layer's size and format status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags=0); - virtual bool isFixedSize() const; + // Creates an ISurface associated with this object. This may only be + // called once. to provide your own ISurface, override createSurface(). + sp getSurface(); + + // modify current state + bool setPosition(float x, float y); + bool setLayer(uint32_t z); + bool setSize(uint32_t w, uint32_t h); + bool setAlpha(uint8_t alpha); + bool setMatrix(const layer_state_t::matrix22_t& matrix); + bool setTransparentRegionHint(const Region& transparent); + bool setFlags(uint8_t flags, uint8_t mask); + bool setCrop(const Rect& crop); + bool setLayerStack(uint32_t layerStack); + + void commitTransaction(); + + uint32_t getTransactionFlags(uint32_t flags); + uint32_t setTransactionFlags(uint32_t flags); + + void computeGeometry(const sp& hw, LayerMesh* mesh) const; + Rect computeBounds() const; + + // ----------------------------------------------------------------------- + + /* + * initStates - called just after construction + */ + virtual void initStates(uint32_t w, uint32_t h, uint32_t flags); + + virtual const char* getTypeId() const { return "Layer"; } + + virtual void setName(const String8& name); + String8 getName() const; - // LayerBase interface virtual void setGeometry(const sp& hw, HWComposer::HWCLayerInterface& layer); virtual void setPerFrameData(const sp& hw, HWComposer::HWCLayerInterface& layer); virtual void setAcquireFence(const sp& hw, HWComposer::HWCLayerInterface& layer); + + /* + * called after page-flip + */ virtual void onLayerDisplayed(const sp& hw, HWComposer::HWCLayerInterface* layer); + + /* + * called before composition. + * returns true if the layer has pending updates. + */ virtual bool onPreComposition(); + + /* + * called after composition. + */ virtual void onPostComposition(); + /* + * draw - performs some global clipping optimizations + * and calls onDraw(). + * Typically this method is not overridden, instead implement onDraw() + * to perform the actual drawing. + */ + virtual void draw(const sp& hw, const Region& clip) const; + virtual void draw(const sp& hw); + + /* + * onDraw - draws the surface. + */ virtual void onDraw(const sp& hw, const Region& clip) const; + + /* + * needsLinearFiltering - true if this surface's state requires filtering + */ + virtual bool needsFiltering(const sp& hw) const; + + /* + * doTransaction - process the transaction. This is a good place to figure + * out which attributes of the surface have changed. + */ virtual uint32_t doTransaction(uint32_t transactionFlags); + + /* + * setVisibleRegion - called to set the new visible region. This gives + * a chance to update the new visible region or record the fact it changed. + */ + virtual void setVisibleRegion(const Region& visibleRegion); + + /* + * setCoveredRegion - called when the covered region changes. The covered + * region corresponds to any area of the surface that is covered + * (transparently or not) by another surface. + */ + virtual void setCoveredRegion(const Region& coveredRegion); + + /* + * setVisibleNonTransparentRegion - called when the visible and + * non-transparent region changes. + */ + virtual void setVisibleNonTransparentRegion(const Region& + visibleNonTransparentRegion); + + /* + * latchBuffer - called each time the screen is redrawn and returns whether + * the visible regions need to be recomputed (this is a fairly heavy + * operation, so this should be set only if needed). Typically this is used + * to figure out if the content or size of a surface has changed. + */ virtual Region latchBuffer(bool& recomputeVisibleRegions); + + /* + * isOpaque - true if this surface is opaque + */ virtual bool isOpaque() const; + + /* + * isSecure - true if this surface is secure, that is if it prevents + * screenshots or VNC servers. + */ virtual bool isSecure() const { return mSecure; } + + /* + * isProtected - true if the layer may contain protected content in the + * GRALLOC_USAGE_PROTECTED sense. + */ virtual bool isProtected() const; - virtual void onRemoved(); - virtual sp getLayer() const { return const_cast(this); } - virtual void setName(const String8& name); + + /* + * isVisible - true if this layer is visible, false otherwise + */ virtual bool isVisible() const; - // LayerBase interface - virtual wp getSurfaceTextureBinder() const; + /* + * isFixedSize - true if content has a fixed size + */ + virtual bool isFixedSize() const; - // only for debugging - inline const sp& getActiveBuffer() const { return mActiveBuffer; } + /* + * called with the state lock when the surface is removed from the + * current list + */ + virtual void onRemoved(); + + + virtual wp getSurfaceTextureBinder() const; // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. virtual void updateTransformHint(const sp& hw) const; + /* + * returns the rectangle that crops the content of the layer and scales it + * to the layer's size. + */ virtual Rect getContentCrop() const; + + /* + * returns the transform bits (90 rotation / h-flip / v-flip) of the + * layer's content + */ virtual uint32_t getContentTransform() const; -protected: - virtual void onFirstRef(); + // ----------------------------------------------------------------------- + + void clearWithOpenGL(const sp& hw, const Region& clip) const; + void setFiltering(bool filtering); + bool getFiltering() const; + + // only for debugging + inline const sp& getActiveBuffer() const { return mActiveBuffer; } + + inline const State& drawingState() const { return mDrawingState; } + inline const State& currentState() const { return mCurrentState; } + inline State& currentState() { return mCurrentState; } + + + /* always call base class first */ virtual void dump(String8& result, char* scratch, size_t size) const; + virtual void shortDump(String8& result, char* scratch, size_t size) const; virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const; virtual void clearStats(); - sp getConsumer() const { - return mSurfaceFlingerConsumer; - } +protected: + // constant + sp mFlinger; + + virtual void onFirstRef(); + + /* + * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer) + * is called. + */ + class LayerCleaner { + sp mFlinger; + wp mLayer; + protected: + ~LayerCleaner(); + public: + LayerCleaner(const sp& flinger, const sp& layer); + }; + private: // Creates an instance of ISurface for this Layer. virtual sp createSurface(); + // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener + virtual void onFrameAvailable(); + + uint32_t getEffectiveUsage(uint32_t usage) const; + Rect computeCrop(const sp& hw) const; bool isCropped() const; static bool getOpacityForFormat(uint32_t format); - // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener - virtual void onFrameAvailable(); + // drawing + void clearWithOpenGL(const sp& hw, const Region& clip, + GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const; + void drawWithOpenGL(const sp& hw, const Region& clip) const; + // ----------------------------------------------------------------------- // constants sp mSurfaceFlingerConsumer; GLuint mTextureName; + bool mPremultipliedAlpha; + String8 mName; + mutable bool mDebug; + PixelFormat mFormat; + const GLExtensions& mGLExtensions; + bool mOpaqueLayer; + + // these are protected by an external lock + State mCurrentState; + State mDrawingState; + volatile int32_t mTransactionFlags; // thread-safe volatile int32_t mQueuedFrames; @@ -145,15 +383,20 @@ private: bool mCurrentOpacity; bool mRefreshPending; bool mFrameLatencyNeeded; - - // constants - PixelFormat mFormat; - const GLExtensions& mGLExtensions; - bool mOpaqueLayer; + // Whether filtering is forced on or not + bool mFiltering; + // Whether filtering is needed b/c of the drawingstate + bool mNeedsFiltering; // page-flip thread (currently main thread) - bool mSecure; // no screenshots + bool mSecure; // no screenshots bool mProtectedByApp; // application requires protected path to external sink + + // protected by mLock + mutable Mutex mLock; + // Set to true if an ISurface has been associated with this object. + mutable bool mHasSurface; + const wp mClientRef; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp deleted file mode 100644 index 6f9ad4ce0..000000000 --- a/services/surfaceflinger/LayerBase.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include - -#include "clz.h" -#include "Client.h" -#include "LayerBase.h" -#include "Layer.h" -#include "SurfaceFlinger.h" -#include "DisplayDevice.h" - -namespace android { - -// --------------------------------------------------------------------------- - -int32_t LayerBase::sSequence = 1; - -LayerBase::LayerBase(SurfaceFlinger* flinger, const sp& client) - : contentDirty(false), - sequence(uint32_t(android_atomic_inc(&sSequence))), - mFlinger(flinger), mFiltering(false), - mNeedsFiltering(false), - mTransactionFlags(0), - mPremultipliedAlpha(true), mName("unnamed"), mDebug(false), - mHasSurface(false), - mClientRef(client) -{ -} - -LayerBase::~LayerBase() -{ - sp c(mClientRef.promote()); - if (c != 0) { - c->detachLayer(this); - } -} - -void LayerBase::setName(const String8& name) { - mName = name; -} - -String8 LayerBase::getName() const { - return mName; -} - -void LayerBase::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; -} - -bool LayerBase::needsFiltering(const sp& hw) const { - return mNeedsFiltering || hw->needsFiltering(); -} - -void LayerBase::commitTransaction() { - mDrawingState = mCurrentState; -} -void LayerBase::forceVisibilityTransaction() { - // this can be called without SurfaceFlinger.mStateLock, but if we - // can atomically increment the sequence number, it doesn't matter. - android_atomic_inc(&mCurrentState.sequence); - requestTransaction(); -} -bool LayerBase::requestTransaction() { - int32_t old = setTransactionFlags(eTransactionNeeded); - return ((old & eTransactionNeeded) == 0); -} -uint32_t LayerBase::getTransactionFlags(uint32_t flags) { - return android_atomic_and(~flags, &mTransactionFlags) & flags; -} -uint32_t LayerBase::setTransactionFlags(uint32_t flags) { - return android_atomic_or(flags, &mTransactionFlags); -} - -bool LayerBase::setPosition(float x, float y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) - return false; - mCurrentState.sequence++; - mCurrentState.transform.set(x, y); - requestTransaction(); - return true; -} -bool LayerBase::setLayer(uint32_t z) { - if (mCurrentState.z == z) - return false; - mCurrentState.sequence++; - mCurrentState.z = z; - requestTransaction(); - return true; -} -bool LayerBase::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; - requestTransaction(); - return true; -} -bool LayerBase::setAlpha(uint8_t alpha) { - if (mCurrentState.alpha == alpha) - return false; - mCurrentState.sequence++; - mCurrentState.alpha = alpha; - requestTransaction(); - return true; -} -bool LayerBase::setMatrix(const layer_state_t::matrix22_t& matrix) { - mCurrentState.sequence++; - mCurrentState.transform.set( - matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy); - requestTransaction(); - return true; -} -bool LayerBase::setTransparentRegionHint(const Region& transparent) { - mCurrentState.sequence++; - mCurrentState.transparentRegion = transparent; - requestTransaction(); - return true; -} -bool LayerBase::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; - requestTransaction(); - return true; -} -bool LayerBase::setCrop(const Rect& crop) { - if (mCurrentState.requested.crop == crop) - return false; - mCurrentState.sequence++; - mCurrentState.requested.crop = crop; - requestTransaction(); - return true; -} - -bool LayerBase::setLayerStack(uint32_t layerStack) { - if (mCurrentState.layerStack == layerStack) - return false; - mCurrentState.sequence++; - mCurrentState.layerStack = layerStack; - requestTransaction(); - return true; -} - -void LayerBase::setVisibleRegion(const Region& visibleRegion) { - // always called from main thread - this->visibleRegion = visibleRegion; -} - -void LayerBase::setCoveredRegion(const Region& coveredRegion) { - // always called from main thread - this->coveredRegion = coveredRegion; -} - -void LayerBase::setVisibleNonTransparentRegion(const Region& - setVisibleNonTransparentRegion) { - // always called from main thread - this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; -} - -uint32_t LayerBase::doTransaction(uint32_t flags) -{ - const Layer::State& front(drawingState()); - const Layer::State& temp(currentState()); - - // 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; -} - -void LayerBase::computeGeometry(const sp& 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]; - } - } -} - -Rect LayerBase::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; -} - -Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) { - Region result; - return result; -} - - -Rect LayerBase::getContentCrop() const { - // regular layers just use their active area as the content crop - const State& s(drawingState()); - return Rect(s.active.w, s.active.h); -} - -uint32_t LayerBase::getContentTransform() const { - // regular layers don't have a content transform - return 0; -} - -Rect LayerBase::computeCrop(const sp& 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 LayerBase::setGeometry( - const sp& hw, - HWComposer::HWCLayerInterface& layer) -{ - layer.setDefaultState(); - - // this gives us only the "orientation" component of the transform - const State& s(drawingState()); - const uint32_t finalTransform = s.transform.getOrientation(); - // we can only handle simple transformation - if (finalTransform & Transform::ROT_INVALID) { - layer.setTransform(0); - } else { - layer.setTransform(finalTransform); - } - - 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)); -} - -void LayerBase::setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& 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); -} - -void LayerBase::setAcquireFence(const sp& hw, - HWComposer::HWCLayerInterface& layer) { - layer.setAcquireFenceFd(-1); -} - -void LayerBase::onLayerDisplayed(const sp& hw, - HWComposer::HWCLayerInterface* layer) { - if (layer) { - layer->onDisplayed(); - } -} - -void LayerBase::setFiltering(bool filtering) -{ - mFiltering = filtering; -} - -bool LayerBase::getFiltering() const -{ - return mFiltering; -} - -bool LayerBase::isVisible() const { - const Layer::State& s(mDrawingState); - return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; -} - -void LayerBase::draw(const sp& hw, const Region& clip) const -{ - onDraw(hw, clip); -} - -void LayerBase::draw(const sp& hw) -{ - onDraw( hw, Region(hw->bounds()) ); -} - -void LayerBase::clearWithOpenGL(const sp& 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 LayerBase::clearWithOpenGL(const sp& hw, const Region& clip) const -{ - clearWithOpenGL(hw, clip, 0,0,0,0); -} - -void LayerBase::drawWithOpenGL(const sp& 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 LayerBase::dump(String8& result, char* buffer, size_t SIZE) const -{ - 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(mClientRef.promote()); - - snprintf(buffer, SIZE, - " " - "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), " - "isOpaque=%1d, needsDithering=%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(), needsDithering(), 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); -} - -void LayerBase::shortDump(String8& result, char* scratch, size_t size) const { - LayerBase::dump(result, scratch, size); -} - -void LayerBase::dumpStats(String8& result, char* scratch, size_t SIZE) const { -} - -void LayerBase::clearStats() { -} - -sp LayerBase::getLayer() const { - return 0; -} - -// --------------------------------------------------------------------------- - -sp LayerBase::createSurface() -{ - class BSurface : public BnSurface, public LayerCleaner { - virtual sp getSurfaceTexture() const { return 0; } - public: - BSurface(const sp& flinger, - const sp& layer) - : LayerCleaner(flinger, layer) { } - }; - sp sur(new BSurface(mFlinger, this)); - return sur; -} - -sp LayerBase::getSurface() -{ - sp s; - Mutex::Autolock _l(mLock); - - LOG_ALWAYS_FATAL_IF(mHasSurface, - "LayerBase::getSurface() has already been called"); - - mHasSurface = true; - s = createSurface(); - mClientSurfaceBinder = s->asBinder(); - return s; -} - -wp LayerBase::getSurfaceBinder() const { - return mClientSurfaceBinder; -} - -wp LayerBase::getSurfaceTextureBinder() const { - return 0; -} - -// --------------------------------------------------------------------------- - -LayerBase::LayerCleaner::LayerCleaner(const sp& flinger, - const sp& layer) - : mFlinger(flinger), mLayer(layer) { -} - -LayerBase::LayerCleaner::~LayerCleaner() { - // destroy client resources - mFlinger->onLayerDestroyed(mLayer); -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h deleted file mode 100644 index 01d82d430..000000000 --- a/services/surfaceflinger/LayerBase.h +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_LAYER_BASE_H -#define ANDROID_LAYER_BASE_H - -#include -#include - -#include -#include -#include - -#include -#include - -#include - -#include - -#include - -#include "Transform.h" -#include "DisplayHardware/HWComposer.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class Client; -class DisplayDevice; -class GraphicBuffer; -class Layer; -class SurfaceFlinger; - -// --------------------------------------------------------------------------- - -/* - * Layers are rectangular graphic entities, internal to SurfaceFlinger. - * They have properties including width, height, Z-depth, and 2D - * transformations (chiefly translation and 90-degree rotations). - * - * Layers are organized into "layer stacks". Each layer is a member of - * exactly one layer stack, identified by an integer in Layer::State. A - * given layer stack may appear on more than one display. - */ -class LayerBase : virtual public RefBase -{ - static int32_t sSequence; - -public: - LayerBase(SurfaceFlinger* flinger, const sp& client); - - - // Creates an ISurface associated with this object. This may only be - // called once (see also getSurfaceBinder()). - sp getSurface(); - - // Returns the Binder object for the ISurface associated with - // this object. - wp getSurfaceBinder() const; - - virtual wp getSurfaceTextureBinder() const; - - - mutable bool contentDirty; - // regions below are in window-manager space - Region visibleRegion; - Region coveredRegion; - Region visibleNonTransparentRegion; - int32_t sequence; - - struct Geometry { - uint32_t w; - uint32_t h; - Rect crop; - inline bool operator == (const Geometry& rhs) const { - return (w==rhs.w && h==rhs.h && crop==rhs.crop); - } - inline bool operator != (const Geometry& rhs) const { - return !operator == (rhs); - } - }; - - struct State { - Geometry active; - Geometry requested; - uint32_t z; - uint32_t layerStack; - uint8_t alpha; - uint8_t flags; - uint8_t reserved[2]; - int32_t sequence; // changes when visible regions can change - Transform transform; - Region transparentRegion; - }; - - class LayerMesh { - friend class LayerBase; - GLfloat mVertices[4][2]; - size_t mNumVertices; - public: - LayerMesh() : mNumVertices(4) { } - GLfloat const* getVertices() const { - return &mVertices[0][0]; - } - size_t getVertexCount() const { - return mNumVertices; - } - }; - - virtual void setName(const String8& name); - String8 getName() const; - - // modify current state - bool setPosition(float x, float y); - bool setLayer(uint32_t z); - bool setSize(uint32_t w, uint32_t h); - bool setAlpha(uint8_t alpha); - bool setMatrix(const layer_state_t::matrix22_t& matrix); - bool setTransparentRegionHint(const Region& transparent); - bool setFlags(uint8_t flags, uint8_t mask); - bool setCrop(const Rect& crop); - bool setLayerStack(uint32_t layerStack); - - void commitTransaction(); - bool requestTransaction(); - void forceVisibilityTransaction(); - - uint32_t getTransactionFlags(uint32_t flags); - uint32_t setTransactionFlags(uint32_t flags); - - void computeGeometry(const sp& hw, LayerMesh* mesh) const; - Rect computeBounds() const; - - - virtual sp getLayer() const; - - virtual const char* getTypeId() const { return "LayerBase"; } - - virtual void setGeometry(const sp& hw, - HWComposer::HWCLayerInterface& layer); - virtual void setPerFrameData(const sp& hw, - HWComposer::HWCLayerInterface& layer); - virtual void setAcquireFence(const sp& hw, - HWComposer::HWCLayerInterface& layer); - - /** - * draw - performs some global clipping optimizations - * and calls onDraw(). - * Typically this method is not overridden, instead implement onDraw() - * to perform the actual drawing. - */ - virtual void draw(const sp& hw, const Region& clip) const; - virtual void draw(const sp& hw); - - /** - * onDraw - draws the surface. - */ - virtual void onDraw(const sp& hw, const Region& clip) const = 0; - - /** - * initStates - called just after construction - */ - virtual void initStates(uint32_t w, uint32_t h, uint32_t flags); - - /** - * doTransaction - process the transaction. This is a good place to figure - * out which attributes of the surface have changed. - */ - virtual uint32_t doTransaction(uint32_t transactionFlags); - - /** - * setVisibleRegion - called to set the new visible region. This gives - * a chance to update the new visible region or record the fact it changed. - */ - virtual void setVisibleRegion(const Region& visibleRegion); - - /** - * setCoveredRegion - called when the covered region changes. The covered - * region corresponds to any area of the surface that is covered - * (transparently or not) by another surface. - */ - virtual void setCoveredRegion(const Region& coveredRegion); - - /** - * setVisibleNonTransparentRegion - called when the visible and - * non-transparent region changes. - */ - virtual void setVisibleNonTransparentRegion(const Region& - visibleNonTransparentRegion); - - /** - * latchBuffer - called each time the screen is redrawn and returns whether - * the visible regions need to be recomputed (this is a fairly heavy - * operation, so this should be set only if needed). Typically this is used - * to figure out if the content or size of a surface has changed. - */ - virtual Region latchBuffer(bool& recomputeVisibleRegions); - - /** - * isOpaque - true if this surface is opaque - */ - virtual bool isOpaque() const { return true; } - - /** - * needsDithering - true if this surface needs dithering - */ - virtual bool needsDithering() const { return false; } - - /** - * needsLinearFiltering - true if this surface's state requires filtering - */ - virtual bool needsFiltering(const sp& hw) const; - - /** - * isSecure - true if this surface is secure, that is if it prevents - * screenshots or VNC servers. - */ - virtual bool isSecure() const { return false; } - - /** - * isProtected - true if the layer may contain protected content in the - * GRALLOC_USAGE_PROTECTED sense. - */ - virtual bool isProtected() const { return false; } - - /* - * isVisible - true if this layer is visibile, false otherwise - */ - virtual bool isVisible() const; - - /** called with the state lock when the surface is removed from the - * current list */ - virtual void onRemoved() { } - - /** called after page-flip - */ - virtual void onLayerDisplayed(const sp& hw, - HWComposer::HWCLayerInterface* layer); - - /** called before composition. - * returns true if the layer has pending updates. - */ - virtual bool onPreComposition() { return false; } - - /** called before composition. - */ - virtual void onPostComposition() { } - - /** - * Updates the GLConsumer's transform hint, for layers that have - * a GLConsumer. - */ - virtual void updateTransformHint(const sp& hw) const { } - - /** - * returns the rectangle that crops the content of the layer and scales it - * to the layer's size. - */ - virtual Rect getContentCrop() const; - - /* - * returns the transform bits (90 rotation / h-flip / v-flip) of the - * layer's content - */ - virtual uint32_t getContentTransform() const; - - /** always call base class first */ - virtual void dump(String8& result, char* scratch, size_t size) const; - virtual void shortDump(String8& result, char* scratch, size_t size) const; - virtual void dumpStats(String8& result, char* buffer, size_t SIZE) const; - virtual void clearStats(); - - - enum { // flags for doTransaction() - eDontUpdateGeometryState = 0x00000001, - eVisibleRegion = 0x00000002, - }; - - - inline const State& drawingState() const { return mDrawingState; } - inline const State& currentState() const { return mCurrentState; } - inline State& currentState() { return mCurrentState; } - - void clearWithOpenGL(const sp& hw, const Region& clip) const; - - void setFiltering(bool filtering); - bool getFiltering() const; - -private: - virtual sp createSurface(); - - Rect computeCrop(const sp& hw) const; - -protected: - void clearWithOpenGL(const sp& hw, const Region& clip, - GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const; - void drawWithOpenGL(const sp& hw, const Region& clip) const; - - - /* - * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer) - * is called. - */ - class LayerCleaner { - sp mFlinger; - wp mLayer; - protected: - ~LayerCleaner(); - public: - LayerCleaner(const sp& flinger, - const sp& layer); - }; - - - - sp mFlinger; - -private: - // accessed only in the main thread - // Whether filtering is forced on or not - bool mFiltering; - - // Whether filtering is needed b/c of the drawingstate - bool mNeedsFiltering; - -protected: - // these are protected by an external lock - State mCurrentState; - State mDrawingState; - volatile int32_t mTransactionFlags; - - // don't change, don't need a lock - bool mPremultipliedAlpha; - String8 mName; - mutable bool mDebug; - - -private: - - mutable Mutex mLock; - - // Set to true if an ISurface has been associated with this object. - mutable bool mHasSurface; - - // The ISurface's Binder object, set by getSurface(). - wp mClientSurfaceBinder; - - const wp mClientRef; - - -public: - // called from class SurfaceFlinger - virtual ~LayerBase(); - -private: - LayerBase(const LayerBase& rhs); -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_BASE_H diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index f8c413962..23decffe9 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -34,12 +34,10 @@ namespace android { // --------------------------------------------------------------------------- LayerDim::LayerDim(SurfaceFlinger* flinger, const sp& client) - : Layer(flinger, client) -{ + : Layer(flinger, client) { } -LayerDim::~LayerDim() -{ +LayerDim::~LayerDim() { } void LayerDim::onDraw(const sp& hw, const Region& clip) const @@ -77,7 +75,7 @@ sp LayerDim::createSurface() virtual sp getSurfaceTexture() const { return 0; } public: BSurface(const sp& flinger, - const sp& layer) + const sp& layer) : LayerCleaner(flinger, layer) { } }; sp sur(new BSurface(mFlinger, this)); @@ -85,7 +83,7 @@ sp LayerDim::createSurface() } bool LayerDim::isVisible() const { - const Layer::State& s(mDrawingState); + const Layer::State& s(drawingState()); return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5ef22ae31..a27d18531 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -580,7 +580,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture( const LayerVector& currentLayers = mCurrentState.layersSortedByZ; size_t count = currentLayers.size(); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); // If this is an instance of Layer (as opposed to, say, LayerDim), // we will get the consumer interface of SurfaceFlingerConsumer's // BufferQueue. If it's the same Binder object as the graphic @@ -600,7 +600,7 @@ bool SurfaceFlinger::authenticateSurfaceTexture( // should not cause any harm. size_t purgatorySize = mLayerPurgatory.size(); for (size_t i=0 ; i& layer(mLayerPurgatory.itemAt(i)); + const sp& layer(mLayerPurgatory.itemAt(i)); wp lbcBinder = layer->getSurfaceTextureBinder(); if (lbcBinder == surfaceTextureBinder) { return true; @@ -908,7 +908,7 @@ void SurfaceFlinger::rebuildLayerStacks() { for (size_t dpy=0 ; dpy > layersSortedByZ; + Vector< sp > layersSortedByZ; const sp& hw(mDisplays[dpy]); const Transform& tr(hw->getTransform()); const Rect bounds(hw->getBounds()); @@ -918,7 +918,7 @@ void SurfaceFlinger::rebuildLayerStacks() { const size_t count = currentLayers.size(); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); const Layer::State& s(layer->drawingState()); if (s.layerStack == hw->getLayerStack()) { Region drawRegion(tr.transform( @@ -948,14 +948,14 @@ void SurfaceFlinger::setUpHWComposer() { sp hw(mDisplays[dpy]); const int32_t id = hw->getHwcDisplayId(); if (id >= 0) { - const Vector< sp >& currentLayers( + const Vector< sp >& currentLayers( hw->getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); if (hwc.createWorkList(id, count) == NO_ERROR) { HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id); for (size_t i=0 ; cur!=end && i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); layer->setGeometry(hw, *cur); if (mDebugDisableHWC || mDebugRegion) { cur->setSkip(true); @@ -971,7 +971,7 @@ void SurfaceFlinger::setUpHWComposer() { sp hw(mDisplays[dpy]); const int32_t id = hw->getHwcDisplayId(); if (id >= 0) { - const Vector< sp >& currentLayers( + const Vector< sp >& currentLayers( hw->getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); HWComposer::LayerListIterator cur = hwc.begin(id); @@ -981,7 +981,7 @@ void SurfaceFlinger::setUpHWComposer() { * update the per-frame h/w composer data for each layer * and build the transparent region of the FB */ - const sp& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); layer->setPerFrameData(hw, *cur); } } @@ -1035,7 +1035,7 @@ void SurfaceFlinger::postFramebuffer() for (size_t dpy=0 ; dpy hw(mDisplays[dpy]); - const Vector< sp >& currentLayers(hw->getVisibleLayersSortedByZ()); + const Vector< sp >& currentLayers(hw->getVisibleLayersSortedByZ()); hw->onSwapBuffersCompleted(hwc); const size_t count = currentLayers.size(); int32_t id = hw->getHwcDisplayId(); @@ -1091,7 +1091,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (transactionFlags & eTraversalNeeded) { for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -1238,8 +1238,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // NOTE: we rely on the fact that layers are sorted by // layerStack first (so we don't have to traverse the list // of displays for every layer). - const sp& layerBase(currentLayers[i]); - uint32_t layerStack = layerBase->drawingState().layerStack; + const sp& layer(currentLayers[i]); + uint32_t layerStack = layer->drawingState().layerStack; if (i==0 || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored @@ -1261,7 +1261,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (disp != NULL) { // presumably this means this layer is using a layerStack // that is not visible on any display - layerBase->updateTransformHint(disp); + layer->updateTransformHint(disp); } } } @@ -1284,7 +1284,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) mVisibleRegionsDirty = true; const size_t count = previousLayers.size(); for (size_t i=0 ; i& layer(previousLayers[i]); + const sp& layer(previousLayers[i]); if (currentLayers.indexOf(layer) < 0) { // this layer is not visible anymore // TODO: we could traverse the tree from front to back and @@ -1335,7 +1335,7 @@ void SurfaceFlinger::computeVisibleRegions( size_t i = currentLayers.size(); while (i--) { - const sp& layer = currentLayers[i]; + const sp& layer = currentLayers[i]; // start with the whole surface at its current location const Layer::State& s(layer->drawingState()); @@ -1478,7 +1478,7 @@ void SurfaceFlinger::handlePageFlip() const LayerVector& currentLayers(mDrawingState.layersSortedByZ); const size_t count = currentLayers.size(); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); const Region dirty(layer->latchBuffer(visibleRegions)); const Layer::State& s(layer->drawingState()); invalidateLayerStack(s.layerStack, dirty); @@ -1600,13 +1600,13 @@ void SurfaceFlinger::doComposeSurfaces(const sp& hw, const * and then, render the layers targeted at the framebuffer */ - const Vector< sp >& layers(hw->getVisibleLayersSortedByZ()); + const Vector< sp >& layers(hw->getVisibleLayersSortedByZ()); const size_t count = layers.size(); const Transform& tr = hw->getTransform(); if (cur != end) { // we're using h/w composer for (size_t i=0 ; i& layer(layers[i]); + const sp& layer(layers[i]); const Region clip(dirty.intersect(tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { switch (cur->getCompositionType()) { @@ -1638,7 +1638,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp& hw, const } else { // we're not using h/w composer for (size_t i=0 ; i& layer(layers[i]); + const sp& layer(layers[i]); const Region clip(dirty.intersect( tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { @@ -1677,7 +1677,7 @@ void SurfaceFlinger::drawWormhole(const sp& hw, void SurfaceFlinger::addClientLayer(const sp& client, const sp& handle, - const sp& lbc) + const sp& lbc) { // attach this layer to the client client->attachLayer(handle, lbc); @@ -1687,7 +1687,7 @@ void SurfaceFlinger::addClientLayer(const sp& client, mCurrentState.layersSortedByZ.add(lbc); } -status_t SurfaceFlinger::removeLayer(const sp& layer) +status_t SurfaceFlinger::removeLayer(const sp& layer) { Mutex::Autolock _l(mStateLock); status_t err = purgatorizeLayer_l(layer); @@ -1696,9 +1696,9 @@ status_t SurfaceFlinger::removeLayer(const sp& layer) return err; } -status_t SurfaceFlinger::removeLayer_l(const sp& layerBase) +status_t SurfaceFlinger::removeLayer_l(const sp& layer) { - ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); + ssize_t index = mCurrentState.layersSortedByZ.remove(layer); if (index >= 0) { mLayersRemoved = true; return NO_ERROR; @@ -1706,16 +1706,16 @@ status_t SurfaceFlinger::removeLayer_l(const sp& layerBase) return status_t(index); } -status_t SurfaceFlinger::purgatorizeLayer_l(const sp& layerBase) +status_t SurfaceFlinger::purgatorizeLayer_l(const sp& layer) { // First add the layer to the purgatory list, which makes sure it won't // go away, then remove it from the main list (through a transaction). - ssize_t err = removeLayer_l(layerBase); + ssize_t err = removeLayer_l(layer); if (err >= 0) { - mLayerPurgatory.add(layerBase); + mLayerPurgatory.add(layer); } - mLayersPendingRemoval.push(layerBase); + mLayersPendingRemoval.push(layer); // it's possible that we don't find a layer, because it might // have been destroyed already -- this is not technically an error @@ -1866,7 +1866,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( const layer_state_t& s) { uint32_t flags = 0; - sp layer(client->getLayerUser(s.surface)); + sp layer(client->getLayerUser(s.surface)); if (layer != 0) { const uint32_t what = s.what; if (what & layer_state_t::ePositionChanged) { @@ -1930,7 +1930,7 @@ sp SurfaceFlinger::createLayer( uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) { - sp layer; + sp layer; sp surfaceHandle; if (int32_t(w|h) < 0) { @@ -2017,7 +2017,7 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp layer = client->getLayerUser(handle); + sp layer = client->getLayerUser(handle); if (layer != 0) { err = purgatorizeLayer_l(layer); @@ -2028,11 +2028,11 @@ status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& layer) +status_t SurfaceFlinger::onLayerDestroyed(const wp& layer) { // called by ~ISurface() when all references are gone status_t err = NO_ERROR; - sp l(layer.promote()); + sp l(layer.promote()); if (l != NULL) { Mutex::Autolock _l(mStateLock); err = removeLayer_l(l); @@ -2249,7 +2249,7 @@ void SurfaceFlinger::listLayersLocked(const Vector& args, size_t& inde const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); snprintf(buffer, SIZE, "%s\n", layer->getName().string()); result.append(buffer); } @@ -2274,7 +2274,7 @@ void SurfaceFlinger::dumpStatsLocked(const Vector& args, size_t& index const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); if (name == layer->getName()) { layer->dumpStats(result, buffer, SIZE); } @@ -2294,7 +2294,7 @@ void SurfaceFlinger::clearStatsLocked(const Vector& args, size_t& inde const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); if (name.isEmpty() || (name == layer->getName())) { layer->clearStats(); } @@ -2350,7 +2350,7 @@ void SurfaceFlinger::dumpAllLocked( snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count); result.append(buffer); for (size_t i=0 ; i& layer(currentLayers[i]); + const sp& layer(currentLayers[i]); layer->dump(result, buffer, SIZE); } @@ -2362,7 +2362,7 @@ void SurfaceFlinger::dumpAllLocked( snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize); result.append(buffer); for (size_t i=0 ; i& layer(mLayerPurgatory.itemAt(i)); + const sp& layer(mLayerPurgatory.itemAt(i)); layer->shortDump(result, buffer, SIZE); } @@ -2451,7 +2451,7 @@ void SurfaceFlinger::dumpAllLocked( alloc.dump(result); } -const Vector< sp >& +const Vector< sp >& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) { // Note: mStateLock is held here return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ(); @@ -2708,10 +2708,10 @@ status_t SurfaceFlinger::captureScreenImplLocked( glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); - const Vector< sp >& layers(hw->getVisibleLayersSortedByZ()); + const Vector< sp >& layers(hw->getVisibleLayersSortedByZ()); const size_t count = layers.size(); for (size_t i=0 ; i& layer(layers[i]); + const sp& layer(layers[i]); const uint32_t z = layer->drawingState().z; if (z >= minLayerZ && z <= maxLayerZ) { if (filtering) layer->setFiltering(true); @@ -2874,15 +2874,15 @@ SurfaceFlinger::LayerVector::LayerVector() { } SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs) - : SortedVector >(rhs) { + : SortedVector >(rhs) { } int SurfaceFlinger::LayerVector::do_compare(const void* lhs, const void* rhs) const { // sort layers per layer-stack, then by z-order and finally by sequence - const sp& l(*reinterpret_cast*>(lhs)); - const sp& r(*reinterpret_cast*>(rhs)); + const sp& l(*reinterpret_cast*>(lhs)); + const sp& r(*reinterpret_cast*>(rhs)); uint32_t ls = l->currentState().layerStack; uint32_t rs = r->currentState().layerStack; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1f63b42b1..241a7d635 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -60,7 +60,6 @@ class DisplayEventConnection; class EventThread; class IGraphicBufferAlloc; class Layer; -class LayerBase; class LayerDim; class Surface; @@ -123,12 +122,11 @@ public: // for debugging only // TODO: this should be made accessible only to HWComposer - const Vector< sp >& getLayerSortedByZForHwcDisplay(int disp); + const Vector< sp >& getLayerSortedByZForHwcDisplay(int disp); private: friend class Client; friend class DisplayEventConnection; - friend class LayerBase; friend class Layer; // We're reference counted, never destroy SurfaceFlinger directly @@ -138,7 +136,7 @@ private: * Internal data structures */ - class LayerVector : public SortedVector > { + class LayerVector : public SortedVector< sp > { public: LayerVector(); LayerVector(const LayerVector& rhs); @@ -277,17 +275,17 @@ private: // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all // resources associated to this layer. - status_t onLayerDestroyed(const wp& layer); + status_t onLayerDestroyed(const wp& layer); // remove a layer from SurfaceFlinger immediately - status_t removeLayer(const sp& layer); + status_t removeLayer(const sp& layer); // add a layer to SurfaceFlinger void addClientLayer(const sp& client, const sp& handle, - const sp& lbc); + const sp& lbc); - status_t removeLayer_l(const sp& layer); - status_t purgatorizeLayer_l(const sp& layer); + status_t removeLayer_l(const sp& layer); + status_t purgatorizeLayer_l(const sp& layer); /* ------------------------------------------------------------------------ * Boot animation, on/off animations and screen capture @@ -401,10 +399,10 @@ private: State mCurrentState; volatile int32_t mTransactionFlags; Condition mTransactionCV; - SortedVector > mLayerPurgatory; + SortedVector< sp > mLayerPurgatory; bool mTransactionPending; bool mAnimTransactionPending; - Vector > mLayersPendingRemoval; + Vector< sp > mLayersPendingRemoval; // protected by mStateLock (but we could use another lock) bool mLayersRemoved; @@ -453,7 +451,7 @@ private: // protected by mDestroyedLayerLock; mutable Mutex mDestroyedLayerLock; - Vector mDestroyedLayers; + Vector mDestroyedLayers; /* ------------------------------------------------------------------------ * Feature prototyping