diff options
Diffstat (limited to 'services/surfaceflinger')
41 files changed, 2820 insertions, 2530 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 5a57697..ec296d3 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -2,23 +2,22 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - Client.cpp \ - DisplayDevice.cpp \ - EventThread.cpp \ - Layer.cpp \ - LayerBase.cpp \ - LayerDim.cpp \ - LayerScreenshot.cpp \ - DisplayHardware/FramebufferSurface.cpp \ - DisplayHardware/GraphicBufferAlloc.cpp \ - DisplayHardware/HWComposer.cpp \ - DisplayHardware/PowerHAL.cpp \ - GLExtensions.cpp \ - MessageQueue.cpp \ - SurfaceFlinger.cpp \ - SurfaceTextureLayer.cpp \ - Transform.cpp \ - + Client.cpp \ + DisplayDevice.cpp \ + EventThread.cpp \ + FrameTracker.cpp \ + GLExtensions.cpp \ + Layer.cpp \ + LayerDim.cpp \ + MessageQueue.cpp \ + SurfaceFlinger.cpp \ + SurfaceFlingerConsumer.cpp \ + SurfaceTextureLayer.cpp \ + Transform.cpp \ + DisplayHardware/FramebufferSurface.cpp \ + DisplayHardware/HWComposer.cpp \ + DisplayHardware/PowerHAL.cpp \ + DisplayHardware/VirtualDisplaySurface.cpp \ LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES @@ -44,6 +43,7 @@ endif LOCAL_SHARED_LIBRARIES := \ libcutils \ + liblog \ libdl \ libhardware \ libutils \ @@ -68,6 +68,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils \ + liblog \ libdl LOCAL_MODULE:= libsurfaceflinger_ddmconnection diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index c28254f..dd65348 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 { @@ -35,7 +34,7 @@ const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER" // --------------------------------------------------------------------------- Client::Client(const sp<SurfaceFlinger>& flinger) - : mFlinger(flinger), mNameGenerator(1) + : mFlinger(flinger) { } @@ -43,7 +42,7 @@ Client::~Client() { const size_t count = mLayers.size(); for (size_t i=0 ; i<count ; i++) { - sp<LayerBaseClient> layer(mLayers.valueAt(i).promote()); + sp<Layer> layer(mLayers.valueAt(i).promote()); if (layer != 0) { mFlinger->removeLayer(layer); } @@ -54,15 +53,13 @@ status_t Client::initCheck() const { return NO_ERROR; } -size_t Client::attachLayer(const sp<LayerBaseClient>& layer) +void Client::attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer) { Mutex::Autolock _l(mLock); - size_t name = mNameGenerator++; - mLayers.add(name, layer); - return name; + mLayers.add(handle, layer); } -void Client::detachLayer(const LayerBaseClient* layer) +void Client::detachLayer(const Layer* layer) { Mutex::Autolock _l(mLock); // we do a linear search here, because this doesn't happen often @@ -74,14 +71,14 @@ void Client::detachLayer(const LayerBaseClient* layer) } } } -sp<LayerBaseClient> Client::getLayerUser(int32_t i) const +sp<Layer> Client::getLayerUser(const sp<IBinder>& handle) const { Mutex::Autolock _l(mLock); - sp<LayerBaseClient> lbc; - wp<LayerBaseClient> layer(mLayers.valueFor(i)); + sp<Layer> lbc; + wp<Layer> layer(mLayers.valueFor(handle)); if (layer != 0) { lbc = layer.promote(); - ALOGE_IF(lbc==0, "getLayerUser(name=%d) is dead", int(i)); + ALOGE_IF(lbc==0, "getLayerUser(name=%p) is dead", handle.get()); } return lbc; } @@ -108,11 +105,11 @@ status_t Client::onTransact( } -sp<ISurface> Client::createSurface( - ISurfaceComposerClient::surface_data_t* params, +status_t Client::createSurface( const String8& name, - uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + sp<IBinder>* handle, + sp<IGraphicBufferProducer>* gbp) { /* * createSurface must be called from the GL thread so that it can @@ -120,39 +117,41 @@ sp<ISurface> Client::createSurface( */ class MessageCreateLayer : public MessageBase { - sp<ISurface> result; SurfaceFlinger* flinger; - ISurfaceComposerClient::surface_data_t* params; Client* client; + sp<IBinder>* handle; + sp<IGraphicBufferProducer>* gbp; + status_t result; const String8& name; uint32_t w, h; PixelFormat format; uint32_t flags; public: MessageCreateLayer(SurfaceFlinger* flinger, - ISurfaceComposerClient::surface_data_t* params, const String8& name, Client* client, - uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) - : flinger(flinger), params(params), client(client), name(name), - w(w), h(h), format(format), flags(flags) - { + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + sp<IBinder>* handle, + sp<IGraphicBufferProducer>* gbp) + : flinger(flinger), client(client), + handle(handle), gbp(gbp), + name(name), w(w), h(h), format(format), flags(flags) { } - sp<ISurface> getResult() const { return result; } + status_t getResult() const { return result; } virtual bool handler() { - result = flinger->createLayer(params, name, client, - w, h, format, flags); + result = flinger->createLayer(name, client, w, h, format, flags, + handle, gbp); return true; } }; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), - params, name, this, w, h, format, flags); + name, this, w, h, format, flags, handle, gbp); mFlinger->postMessageSync(msg); return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); } -status_t Client::destroySurface(SurfaceID sid) { - return mFlinger->onLayerRemoved(this, sid); + +status_t Client::destroySurface(const sp<IBinder>& handle) { + return mFlinger->onLayerRemoved(this, handle); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index d6c6931..84e649f 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -30,7 +30,7 @@ namespace android { // --------------------------------------------------------------------------- -class LayerBaseClient; +class Layer; class SurfaceFlinger; // --------------------------------------------------------------------------- @@ -44,20 +44,21 @@ public: status_t initCheck() const; // protected by SurfaceFlinger::mStateLock - size_t attachLayer(const sp<LayerBaseClient>& layer); + void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer); - void detachLayer(const LayerBaseClient* layer); + void detachLayer(const Layer* layer); - sp<LayerBaseClient> getLayerUser(int32_t i) const; + sp<Layer> getLayerUser(const sp<IBinder>& handle) const; private: // ISurfaceComposerClient interface - virtual sp<ISurface> createSurface( - surface_data_t* params, const String8& name, - uint32_t w, uint32_t h,PixelFormat format, - uint32_t flags); + virtual status_t createSurface( + const String8& name, + uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, + sp<IBinder>* handle, + sp<IGraphicBufferProducer>* gbp); - virtual status_t destroySurface(SurfaceID surfaceId); + virtual status_t destroySurface(const sp<IBinder>& handle); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); @@ -66,8 +67,7 @@ private: sp<SurfaceFlinger> mFlinger; // protected by mLock - DefaultKeyedVector< size_t, wp<LayerBaseClient> > mLayers; - size_t mNameGenerator; + DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers; // thread-safe mutable Mutex mLock; diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 69b9c34..68b0b7f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -27,7 +27,7 @@ #include <ui/DisplayInfo.h> #include <ui/PixelFormat.h> -#include <gui/SurfaceTextureClient.h> +#include <gui/Surface.h> #include <GLES/gl.h> #include <EGL/egl.h> @@ -35,14 +35,14 @@ #include <hardware/gralloc.h> -#include "DisplayHardware/FramebufferSurface.h" +#include "DisplayHardware/DisplaySurface.h" #include "DisplayHardware/HWComposer.h" #include "clz.h" #include "DisplayDevice.h" #include "GLExtensions.h" #include "SurfaceFlinger.h" -#include "LayerBase.h" +#include "Layer.h" // ---------------------------------------------------------------------------- using namespace android; @@ -70,16 +70,15 @@ void checkGLErrors() DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, + int32_t hwcId, bool isSecure, const wp<IBinder>& displayToken, - const sp<ANativeWindow>& nativeWindow, - const sp<FramebufferSurface>& framebufferSurface, + const sp<DisplaySurface>& displaySurface, EGLConfig config) : mFlinger(flinger), - mType(type), mHwcDisplayId(-1), + mType(type), mHwcDisplayId(hwcId), mDisplayToken(displayToken), - mNativeWindow(nativeWindow), - mFramebufferSurface(framebufferSurface), + mDisplaySurface(displaySurface), mDisplay(EGL_NO_DISPLAY), mSurface(EGL_NO_SURFACE), mContext(EGL_NO_CONTEXT), @@ -89,41 +88,10 @@ DisplayDevice::DisplayDevice( mIsSecure(isSecure), mSecureLayerVisible(false), mScreenAcquired(false), - mLayerStack(0), + mLayerStack(NO_LAYER_STACK), mOrientation() { - init(config); -} - -DisplayDevice::~DisplayDevice() { - if (mSurface != EGL_NO_SURFACE) { - eglDestroySurface(mDisplay, mSurface); - mSurface = EGL_NO_SURFACE; - } -} - -bool DisplayDevice::isValid() const { - return mFlinger != NULL; -} - -int DisplayDevice::getWidth() const { - return mDisplayWidth; -} - -int DisplayDevice::getHeight() const { - return mDisplayHeight; -} - -PixelFormat DisplayDevice::getFormat() const { - return mFormat; -} - -EGLSurface DisplayDevice::getEGLSurface() const { - return mSurface; -} - -void DisplayDevice::init(EGLConfig config) -{ + mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer()); ANativeWindow* const window = mNativeWindow.get(); int format; @@ -147,11 +115,8 @@ void DisplayDevice::init(EGLConfig config) mViewport.makeInvalid(); mFrame.makeInvalid(); - // external displays are always considered enabled - mScreenAcquired = (mType >= DisplayDevice::NUM_DISPLAY_TYPES); - - // get an h/w composer ID - mHwcDisplayId = mFlinger->allocateHwcDisplayId(mType); + // virtual displays are always considered enabled + mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL); // Name the display. The name will be replaced shortly if the display // was created with createDisplay(). @@ -171,6 +136,42 @@ void DisplayDevice::init(EGLConfig config) setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } +DisplayDevice::~DisplayDevice() { + if (mSurface != EGL_NO_SURFACE) { + eglDestroySurface(mDisplay, mSurface); + mSurface = EGL_NO_SURFACE; + } +} + +void DisplayDevice::disconnect(HWComposer& hwc) { + if (mHwcDisplayId >= 0) { + hwc.disconnectDisplay(mHwcDisplayId); + if (mHwcDisplayId >= DISPLAY_VIRTUAL) + hwc.freeDisplayId(mHwcDisplayId); + mHwcDisplayId = -1; + } +} + +bool DisplayDevice::isValid() const { + return mFlinger != NULL; +} + +int DisplayDevice::getWidth() const { + return mDisplayWidth; +} + +int DisplayDevice::getHeight() const { + return mDisplayHeight; +} + +PixelFormat DisplayDevice::getFormat() const { + return mFormat; +} + +EGLSurface DisplayDevice::getEGLSurface() const { + return mSurface; +} + void DisplayDevice::setDisplayName(const String8& displayName) { if (!displayName.isEmpty()) { // never override the name with an empty name @@ -183,10 +184,7 @@ uint32_t DisplayDevice::getPageFlipCount() const { } status_t DisplayDevice::compositionComplete() const { - if (mFramebufferSurface == NULL) { - return NO_ERROR; - } - return mFramebufferSurface->compositionComplete(); + return mDisplaySurface->compositionComplete(); } void DisplayDevice::flip(const Region& dirty) const @@ -196,58 +194,50 @@ void DisplayDevice::flip(const Region& dirty) const EGLDisplay dpy = mDisplay; EGLSurface surface = mSurface; -#ifdef EGL_ANDROID_swap_rectangle +#ifdef EGL_ANDROID_swap_rectangle if (mFlags & SWAP_RECTANGLE) { const Region newDirty(dirty.intersect(bounds())); const Rect b(newDirty.getBounds()); eglSetSwapRectangleANDROID(dpy, surface, b.left, b.top, b.width(), b.height()); - } + } #endif mPageFlipCount++; } void DisplayDevice::swapBuffers(HWComposer& hwc) const { - EGLBoolean success = EGL_TRUE; - if (hwc.initCheck() != NO_ERROR) { - // no HWC, we call eglSwapBuffers() - success = eglSwapBuffers(mDisplay, mSurface); - } else { - // We have a valid HWC, but not all displays can use it, in particular - // the virtual displays are on their own. - // TODO: HWC 1.2 will allow virtual displays - if (mType >= DisplayDevice::DISPLAY_VIRTUAL) { - // always call eglSwapBuffers() for virtual displays - success = eglSwapBuffers(mDisplay, mSurface); - } else if (hwc.supportsFramebufferTarget()) { - // as of hwc 1.1 we always call eglSwapBuffers if we have some - // GLES layers - if (hwc.hasGlesComposition(mType)) { - success = eglSwapBuffers(mDisplay, mSurface); + // We need to call eglSwapBuffers() unless: + // (a) there was no GLES composition this frame, or + // (b) we're using a legacy HWC with no framebuffer target support (in + // which case HWComposer::commit() handles things). + if (hwc.initCheck() != NO_ERROR || + (hwc.hasGlesComposition(mHwcDisplayId) && + hwc.supportsFramebufferTarget())) { + EGLBoolean success = eglSwapBuffers(mDisplay, mSurface); + if (!success) { + EGLint error = eglGetError(); + if (error == EGL_CONTEXT_LOST || + mType == DisplayDevice::DISPLAY_PRIMARY) { + LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x", + mDisplay, mSurface, error); + } else { + ALOGE("eglSwapBuffers(%p, %p) failed with 0x%08x", + mDisplay, mSurface, error); } - } else { - // HWC doesn't have the framebuffer target, we don't call - // eglSwapBuffers(), since this is handled by HWComposer::commit(). } } - if (!success) { - EGLint error = eglGetError(); - if (error == EGL_CONTEXT_LOST || - mType == DisplayDevice::DISPLAY_PRIMARY) { - LOG_ALWAYS_FATAL("eglSwapBuffers(%p, %p) failed with 0x%08x", - mDisplay, mSurface, error); - } + status_t result = mDisplaySurface->advanceFrame(); + if (result != NO_ERROR) { + ALOGE("[%s] failed pushing new frame to HWC: %d", + mDisplayName.string(), result); } } void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const { if (hwc.initCheck() == NO_ERROR) { - if (hwc.supportsFramebufferTarget()) { - int fd = hwc.getAndResetReleaseFenceFd(mType); - mFramebufferSurface->setReleaseFenceFd(fd); - } + mDisplaySurface->onFrameCommitted(); } } @@ -282,18 +272,19 @@ void DisplayDevice::setViewportAndProjection(const sp<const DisplayDevice>& hw) // ---------------------------------------------------------------------------- -void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) { +void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) { mVisibleLayersSortedByZ = layers; mSecureLayerVisible = false; size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - if (layers[i]->isSecure()) { + const sp<Layer>& layer(layers[i]); + if (layer->isSecure()) { mSecureLayerVisible = true; } } } -const Vector< sp<LayerBase> >& DisplayDevice::getVisibleLayersSortedByZ() const { +const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const { return mVisibleLayersSortedByZ; } @@ -365,94 +356,96 @@ status_t DisplayDevice::orientationToTransfrom( } void DisplayDevice::setProjection(int orientation, - const Rect& viewport, const Rect& frame) { - mOrientation = orientation; - mViewport = viewport; - mFrame = frame; - updateGeometryTransform(); -} + const Rect& newViewport, const Rect& newFrame) { + Rect viewport(newViewport); + Rect frame(newFrame); -void DisplayDevice::updateGeometryTransform() { - int w = mDisplayWidth; - int h = mDisplayHeight; - Transform TL, TP, R, S; - if (DisplayDevice::orientationToTransfrom( - mOrientation, w, h, &R) == NO_ERROR) { - dirtyRegion.set(bounds()); - - Rect viewport(mViewport); - Rect frame(mFrame); - - if (!frame.isValid()) { - // the destination frame can be invalid if it has never been set, - // in that case we assume the whole display frame. - frame = Rect(w, h); - } + const int w = mDisplayWidth; + const int h = mDisplayHeight; - if (viewport.isEmpty()) { - // viewport can be invalid if it has never been set, in that case - // we assume the whole display size. - // it's also invalid to have an empty viewport, so we handle that - // case in the same way. - viewport = Rect(w, h); - if (R.getOrientation() & Transform::ROT_90) { - // viewport is always specified in the logical orientation - // of the display (ie: post-rotation). - swap(viewport.right, viewport.bottom); - } - } + Transform R; + DisplayDevice::orientationToTransfrom(orientation, w, h, &R); - float src_width = viewport.width(); - float src_height = viewport.height(); - float dst_width = frame.width(); - float dst_height = frame.height(); - if (src_width != dst_width || src_height != dst_height) { - float sx = dst_width / src_width; - float sy = dst_height / src_height; - S.set(sx, 0, 0, sy); + if (!frame.isValid()) { + // the destination frame can be invalid if it has never been set, + // in that case we assume the whole display frame. + frame = Rect(w, h); + } + + if (viewport.isEmpty()) { + // viewport can be invalid if it has never been set, in that case + // we assume the whole display size. + // it's also invalid to have an empty viewport, so we handle that + // case in the same way. + viewport = Rect(w, h); + if (R.getOrientation() & Transform::ROT_90) { + // viewport is always specified in the logical orientation + // of the display (ie: post-rotation). + swap(viewport.right, viewport.bottom); } + } + + dirtyRegion.set(getBounds()); + + Transform TL, TP, S; + float src_width = viewport.width(); + float src_height = viewport.height(); + float dst_width = frame.width(); + float dst_height = frame.height(); + if (src_width != dst_width || src_height != dst_height) { + float sx = dst_width / src_width; + float sy = dst_height / src_height; + S.set(sx, 0, 0, sy); + } - float src_x = viewport.left; - float src_y = viewport.top; - float dst_x = frame.left; - float dst_y = frame.top; - TL.set(-src_x, -src_y); - TP.set(dst_x, dst_y); - - // The viewport and frame are both in the logical orientation. - // Apply the logical translation, scale to physical size, apply the - // physical translation and finally rotate to the physical orientation. - mGlobalTransform = R * TP * S * TL; - - const uint8_t type = mGlobalTransform.getType(); - mNeedsFiltering = (!mGlobalTransform.preserveRects() || - (type >= Transform::SCALE)); + float src_x = viewport.left; + float src_y = viewport.top; + float dst_x = frame.left; + float dst_y = frame.top; + TL.set(-src_x, -src_y); + TP.set(dst_x, dst_y); + + // The viewport and frame are both in the logical orientation. + // Apply the logical translation, scale to physical size, apply the + // physical translation and finally rotate to the physical orientation. + mGlobalTransform = R * TP * S * TL; + + const uint8_t type = mGlobalTransform.getType(); + mNeedsFiltering = (!mGlobalTransform.preserveRects() || + (type >= Transform::SCALE)); + + mScissor = mGlobalTransform.transform(viewport); + if (mScissor.isEmpty()) { + mScissor.set(getBounds()); } + + mOrientation = orientation; + mViewport = viewport; + mFrame = frame; } void DisplayDevice::dump(String8& result, char* buffer, size_t SIZE) const { const Transform& tr(mGlobalTransform); snprintf(buffer, SIZE, "+ DisplayDevice: %s\n" - " type=%x, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " + " type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), " "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%u\n" - " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], " + " v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d]," "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n", - mDisplayName.string(), mType, + mDisplayName.string(), mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(), mOrientation, tr.getType(), getPageFlipCount(), mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(), mViewport.left, mViewport.top, mViewport.right, mViewport.bottom, mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, + mScissor.left, mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0], tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]); result.append(buffer); - String8 fbtargetDump; - if (mFramebufferSurface != NULL) { - mFramebufferSurface->dump(fbtargetDump); - result.append(fbtargetDump); - } + String8 surfaceDump; + mDisplaySurface->dump(surfaceDump); + result.append(surfaceDump); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d6da422..377d924 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -37,8 +37,8 @@ struct ANativeWindow; namespace android { class DisplayInfo; -class FramebufferSurface; -class LayerBase; +class DisplaySurface; +class Layer; class SurfaceFlinger; class HWComposer; @@ -65,13 +65,17 @@ public: SWAP_RECTANGLE = 0x00080000, }; + enum { + NO_LAYER_STACK = 0xFFFFFFFF, + }; + DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, + int32_t hwcId, // negative for non-HWC-composited displays bool isSecure, const wp<IBinder>& displayToken, - const sp<ANativeWindow>& nativeWindow, - const sp<FramebufferSurface>& framebufferSurface, + const sp<DisplaySurface>& displaySurface, EGLConfig config); ~DisplayDevice(); @@ -95,8 +99,8 @@ public: EGLSurface getEGLSurface() const; - void setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers); - const Vector< sp<LayerBase> >& getVisibleLayersSortedByZ() const; + void setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers); + const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const; bool getSecureLayerVisible() const; Region getDirtyRegion(bool repaintEverything) const; @@ -105,8 +109,9 @@ public: int getOrientation() const { return mOrientation; } const Transform& getTransform() const { return mGlobalTransform; } - const Rect& getViewport() const { return mViewport; } - const Rect& getFrame() const { return mFrame; } + const Rect getViewport() const { return mViewport; } + const Rect getFrame() const { return mFrame; } + const Rect& getScissor() const { return mScissor; } bool needsFiltering() const { return mNeedsFiltering; } uint32_t getLayerStack() const { return mLayerStack; } @@ -116,7 +121,7 @@ public: void swapBuffers(HWComposer& hwc) const; status_t compositionComplete() const; - + // called after h/w composer has completed its set() call void onSwapBuffersCompleted(HWComposer& hwc) const; @@ -141,6 +146,9 @@ public: bool isScreenAcquired() const; bool canDraw() const; + // release HWC resources (if any) for removable displays + void disconnect(HWComposer& hwc); + /* ------------------------------------------------------------------------ * Debugging */ @@ -148,8 +156,6 @@ public: void dump(String8& result, char* buffer, size_t SIZE) const; private: - void init(EGLConfig config); - /* * Constants, set during initialization */ @@ -160,9 +166,7 @@ private: // ANativeWindow this display is rendering into sp<ANativeWindow> mNativeWindow; - - // set if mNativeWindow is a FramebufferSurface - sp<FramebufferSurface> mFramebufferSurface; + sp<DisplaySurface> mDisplaySurface; EGLDisplay mDisplay; EGLSurface mSurface; @@ -181,7 +185,7 @@ private: */ // list of visible layers on that display - Vector< sp<LayerBase> > mVisibleLayersSortedByZ; + Vector< sp<Layer> > mVisibleLayersSortedByZ; // Whether we have a visible secure layer on this display bool mSecureLayerVisible; @@ -196,12 +200,14 @@ private: static status_t orientationToTransfrom(int orientation, int w, int h, Transform* tr); - void updateGeometryTransform(); - uint32_t mLayerStack; int mOrientation; + // user-provided visible area of the layer stack Rect mViewport; + // user-provided rectangle where mViewport gets mapped to Rect mFrame; + // pre-computed scissor to apply to the display + Rect mScissor; Transform mGlobalTransform; bool mNeedsFiltering; }; diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h new file mode 100644 index 0000000..2eca3cb --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h @@ -0,0 +1,68 @@ +/* + * Copyright 2013 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_SF_DISPLAY_SURFACE_H +#define ANDROID_SF_DISPLAY_SURFACE_H + +#include <utils/Errors.h> +#include <utils/RefBase.h> +#include <utils/StrongPointer.h> + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class IGraphicBufferProducer; +class String8; + +class DisplaySurface : public virtual RefBase { +public: + virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const = 0; + + // Should be called when composition rendering is complete for a frame (but + // eglSwapBuffers hasn't necessarily been called). Required by certain + // older drivers for synchronization. + // TODO: Remove this when we drop support for HWC 1.0. + virtual status_t compositionComplete() = 0; + + // Inform the surface that GLES composition is complete for this frame, and + // the surface should make sure that HWComposer has the correct buffer for + // this frame. Some implementations may only push a new buffer to + // HWComposer if GLES composition took place, others need to push a new + // buffer on every frame. + // + // advanceFrame must be followed by a call to onFrameCommitted before + // advanceFrame may be called again. + virtual status_t advanceFrame() = 0; + + // onFrameCommitted is called after the frame has been committed to the + // hardware composer. The surface collects the release fence for this + // frame's buffer. + virtual void onFrameCommitted() = 0; + + virtual void dump(String8& result) const = 0; + +protected: + DisplaySurface() {} + virtual ~DisplaySurface() {} +}; + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SF_DISPLAY_SURFACE_H + diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 6c86a53..54a3ce8 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -29,12 +29,12 @@ #include <EGL/egl.h> #include <hardware/hardware.h> -#include <gui/SurfaceTextureClient.h> +#include <gui/Surface.h> +#include <gui/GraphicBufferAlloc.h> #include <ui/GraphicBuffer.h> -#include "DisplayHardware/FramebufferSurface.h" -#include "DisplayHardware/GraphicBufferAlloc.h" -#include "DisplayHardware/HWComposer.h" +#include "FramebufferSurface.h" +#include "HWComposer.h" #ifndef NUM_FRAMEBUFFER_SURFACE_BUFFERS #define NUM_FRAMEBUFFER_SURFACE_BUFFERS (2) @@ -68,6 +68,17 @@ FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp) : mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS); } +sp<IGraphicBufferProducer> FramebufferSurface::getIGraphicBufferProducer() const { + return getBufferQueue(); +} + +status_t FramebufferSurface::advanceFrame() { + // Once we remove FB HAL support, we can call nextBuffer() from here + // instead of using onFrameAvailable(). No real benefit, except it'll be + // more like VirtualDisplaySurface. + return NO_ERROR; +} + status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) { Mutex::Autolock lock(mMutex); @@ -129,22 +140,14 @@ void FramebufferSurface::freeBufferLocked(int slotIndex) { } } -status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) { - status_t err = NO_ERROR; - if (fenceFd >= 0) { - sp<Fence> fence(new Fence(fenceFd)); - if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) { - status_t err = addReleaseFence(mCurrentBufferSlot, fence); - ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)", - strerror(-err), err); - } +void FramebufferSurface::onFrameCommitted() { + sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType); + if (fence->isValid() && + mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) { + status_t err = addReleaseFence(mCurrentBufferSlot, fence); + ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)", + strerror(-err), err); } - return err; -} - -status_t FramebufferSurface::setUpdateRectangle(const Rect& r) -{ - return INVALID_OPERATION; } status_t FramebufferSurface::compositionComplete() @@ -152,11 +155,33 @@ status_t FramebufferSurface::compositionComplete() return mHwc.fbCompositionComplete(); } -void FramebufferSurface::dump(String8& result) { - mHwc.fbDump(result); +// Since DisplaySurface and ConsumerBase both have a method with this +// signature, results will vary based on the static pointer type the caller is +// using: +// void dump(FrameBufferSurface* fbs, String8& s) { +// // calls FramebufferSurface::dump() +// fbs->dump(s); +// +// // calls ConsumerBase::dump() since it is non-virtual +// static_cast<ConsumerBase*>(fbs)->dump(s); +// +// // calls FramebufferSurface::dump() since it is virtual +// static_cast<DisplaySurface*>(fbs)->dump(s); +// } +// To make sure that all of these end up doing the same thing, we just redirect +// to ConsumerBase::dump() here. It will take the internal lock, and then call +// virtual dumpLocked(), which is where the real work happens. +void FramebufferSurface::dump(String8& result) const { ConsumerBase::dump(result); } +void FramebufferSurface::dumpLocked(String8& result, const char* prefix, + char* buffer, size_t SIZE) const +{ + mHwc.fbDump(result); + ConsumerBase::dumpLocked(result, prefix, buffer, SIZE); +} + // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index 6336345..2fde789 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -22,6 +22,8 @@ #include <gui/ConsumerBase.h> +#include "DisplaySurface.h" + // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- @@ -32,23 +34,20 @@ class HWComposer; // --------------------------------------------------------------------------- -class FramebufferSurface : public ConsumerBase { +class FramebufferSurface : public ConsumerBase, + public DisplaySurface { public: FramebufferSurface(HWComposer& hwc, int disp); - bool isUpdateOnDemand() const { return false; } - status_t setUpdateRectangle(const Rect& updateRect); - status_t compositionComplete(); + virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const; - virtual void dump(String8& result); + virtual status_t compositionComplete(); + virtual status_t advanceFrame(); + virtual void onFrameCommitted(); - // setReleaseFenceFd stores a fence file descriptor that will signal when the - // current buffer is no longer being read. This fence will be returned to - // the producer when the current buffer is released by updateTexImage(). - // Multiple fences can be set for a given buffer; they will be merged into - // a single union fence. The SurfaceTexture will close the file descriptor - // when finished with it. - status_t setReleaseFenceFd(int fenceFd); + // Implementation of DisplaySurface::dump(). Note that ConsumerBase also + // has a non-virtual dump() with the same signature. + virtual void dump(String8& result) const; private: virtual ~FramebufferSurface() { }; // this class cannot be overloaded @@ -56,6 +55,9 @@ private: virtual void onFrameAvailable(); virtual void freeBufferLocked(int slotIndex); + virtual void dumpLocked(String8& result, const char* prefix, + char* buffer, size_t SIZE) const; + // nextBuffer waits for and then latches the next buffer from the // BufferQueue and releases the previously latched buffer to the // BufferQueue. The new buffer is returned in the 'buffer' argument. diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp deleted file mode 100644 index 965ff01..0000000 --- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - ** - ** Copyright 2012 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 <cutils/log.h> - -#include <ui/GraphicBuffer.h> - -#include "DisplayHardware/GraphicBufferAlloc.h" - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -GraphicBufferAlloc::GraphicBufferAlloc() { -} - -GraphicBufferAlloc::~GraphicBufferAlloc() { -} - -sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error) { - sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(w, h, format, usage)); - status_t err = graphicBuffer->initCheck(); - *error = err; - if (err != 0 || graphicBuffer->handle == 0) { - if (err == NO_MEMORY) { - GraphicBuffer::dumpAllocationsToSystemLog(); - } - ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " - "failed (%s), handle=%p", - w, h, strerror(-err), graphicBuffer->handle); - return 0; - } - return graphicBuffer; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h b/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h deleted file mode 100644 index b08750c..0000000 --- a/services/surfaceflinger/DisplayHardware/GraphicBufferAlloc.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2012 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_SF_GRAPHIC_BUFFER_ALLOC_H -#define ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H - -#include <stdint.h> -#include <sys/types.h> - -#include <gui/IGraphicBufferAlloc.h> -#include <ui/PixelFormat.h> -#include <utils/Errors.h> - -namespace android { -// --------------------------------------------------------------------------- - -class GraphicBuffer; - -class GraphicBufferAlloc : public BnGraphicBufferAlloc { -public: - GraphicBufferAlloc(); - virtual ~GraphicBufferAlloc(); - virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h, - PixelFormat format, uint32_t usage, status_t* error); -}; - - -// --------------------------------------------------------------------------- -}; // namespace android - -#endif // ANDROID_SF_GRAPHIC_BUFFER_ALLOC_H diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 068fdcd..a9afbe5 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -25,6 +25,7 @@ #include <string.h> #include <sys/types.h> +#include <utils/CallStack.h> #include <utils/Errors.h> #include <utils/misc.h> #include <utils/String8.h> @@ -37,19 +38,27 @@ #include <hardware/hardware.h> #include <hardware/hwcomposer.h> +#include <android/configuration.h> + #include <cutils/log.h> #include <cutils/properties.h> -#include "Layer.h" // needed only for debugging -#include "LayerBase.h" #include "HWComposer.h" -#include "SurfaceFlinger.h" -#include <utils/CallStack.h> + +#include "../Layer.h" // needed only for debugging +#include "../SurfaceFlinger.h" namespace android { +// This is not a real HWC version. It's used for in-development features that +// haven't been committed to a specific real HWC version. +#define HWC_DEVICE_API_VERSION_1_EXP HARDWARE_DEVICE_API_VERSION_2(1, 0xFF, HWC_HEADER_VERSION) + #define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION +#define NUM_PHYSICAL_DISPLAYS HWC_NUM_DISPLAY_TYPES +#define VIRTUAL_DISPLAY_ID_BASE HWC_NUM_DISPLAY_TYPES + static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) { uint32_t hwcVersion = hwc->common.version; return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; @@ -100,7 +109,7 @@ HWComposer::HWComposer( bool needVSyncThread = true; // Note: some devices may insist that the FB HAL be opened before HWC. - loadFbHalModule(); + int fberr = loadFbHalModule(); loadHwcModule(); if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { @@ -114,12 +123,13 @@ HWComposer::HWComposer( // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory. if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) && !mFbDev) { - ALOGE("ERROR: failed to open framebuffer, aborting"); + ALOGE("ERROR: failed to open framebuffer (%s), aborting", + strerror(-fberr)); abort(); } // these display IDs are always reserved - for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { + for (size_t i=0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) { mAllocatedDisplayIDs.markBit(i); } @@ -146,12 +156,12 @@ HWComposer::HWComposer( // the number of displays we actually have depends on the // hw composer version - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { - // 1.2 adds support for virtual displays + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) { + // 1.?? adds support for virtual displays mNumDisplays = MAX_DISPLAYS; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // 1.1 adds support for multiple displays - mNumDisplays = HWC_NUM_DISPLAY_TYPES; + mNumDisplays = NUM_PHYSICAL_DISPLAYS; } else { mNumDisplays = 1; } @@ -179,7 +189,7 @@ HWComposer::HWComposer( } } else if (mHwc) { // here we're guaranteed to have at least HWC 1.1 - for (size_t i =0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { + for (size_t i =0 ; i<NUM_PHYSICAL_DISPLAYS ; i++) { queryDisplayProperties(i); } } @@ -235,20 +245,17 @@ void HWComposer::loadHwcModule() } // Load and prepare the FB HAL, which uses the gralloc module. Sets mFbDev. -void HWComposer::loadFbHalModule() +int HWComposer::loadFbHalModule() { hw_module_t const* module; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) { + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); + if (err != 0) { ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID); - return; + return err; } - int err = framebuffer_open(module, &mFbDev); - if (err) { - ALOGE("framebuffer_open failed (%s)", strerror(-err)); - return; - } + return framebuffer_open(module, &mFbDev); } status_t HWComposer::initCheck() const { @@ -287,7 +294,7 @@ void HWComposer::vsync(int disp, int64_t timestamp) { } void HWComposer::hotplug(int disp, int connected) { - if (disp == HWC_DISPLAY_PRIMARY || disp >= HWC_NUM_DISPLAY_TYPES) { + if (disp == HWC_DISPLAY_PRIMARY || disp >= VIRTUAL_DISPLAY_ID_BASE) { ALOGE("hotplug event received for invalid display: disp=%d connected=%d", disp, connected); return; @@ -296,6 +303,11 @@ void HWComposer::hotplug(int disp, int connected) { mEventHandler.onHotplugReceived(disp, bool(connected)); } +static float getDefaultDensity(uint32_t height) { + if (height >= 1080) return ACONFIGURATION_DENSITY_XHIGH; + else return ACONFIGURATION_DENSITY_TV; +} + static const uint32_t DISPLAY_ATTRIBUTES[] = { HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_WIDTH, @@ -306,10 +318,6 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = { }; #define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0]) -// http://developer.android.com/reference/android/util/DisplayMetrics.html -#define ANDROID_DENSITY_TV 213 -#define ANDROID_DENSITY_XHIGH 320 - status_t HWComposer::queryDisplayProperties(int disp) { LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); @@ -363,15 +371,23 @@ status_t HWComposer::queryDisplayProperties(int disp) { mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888; mDisplayData[disp].connected = true; if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) { - // is there anything smarter we can do? - if (h >= 1080) { - mDisplayData[disp].xdpi = ANDROID_DENSITY_XHIGH; - mDisplayData[disp].ydpi = ANDROID_DENSITY_XHIGH; - } else { - mDisplayData[disp].xdpi = ANDROID_DENSITY_TV; - mDisplayData[disp].ydpi = ANDROID_DENSITY_TV; - } + float dpi = getDefaultDensity(h); + mDisplayData[disp].xdpi = dpi; + mDisplayData[disp].ydpi = dpi; + } + return NO_ERROR; +} + +status_t HWComposer::setVirtualDisplayProperties(int32_t id, + uint32_t w, uint32_t h, uint32_t format) { + if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) || + !mAllocatedDisplayIDs.hasBit(id)) { + return BAD_INDEX; } + mDisplayData[id].width = w; + mDisplayData[id].height = h; + mDisplayData[id].format = format; + mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h); return NO_ERROR; } @@ -381,11 +397,12 @@ int32_t HWComposer::allocateDisplayId() { } int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit(); mAllocatedDisplayIDs.markBit(id); + mDisplayData[id].connected = true; return id; } status_t HWComposer::freeDisplayId(int32_t id) { - if (id < HWC_NUM_DISPLAY_TYPES) { + if (id < NUM_PHYSICAL_DISPLAYS) { // cannot free the reserved IDs return BAD_VALUE; } @@ -393,6 +410,7 @@ status_t HWComposer::freeDisplayId(int32_t id) { return BAD_INDEX; } mAllocatedDisplayIDs.clearBit(id); + mDisplayData[id].connected = false; return NO_ERROR; } @@ -409,6 +427,10 @@ nsecs_t HWComposer::getRefreshTimestamp(int disp) const { return now - ((now - mLastHwVSync) % mDisplayData[disp].refresh); } +sp<Fence> HWComposer::getDisplayFence(int disp) const { + return mDisplayData[disp].lastDisplayFence; +} + uint32_t HWComposer::getWidth(int disp) const { return mDisplayData[disp].width; } @@ -494,7 +516,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1]; memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t)); - const hwc_rect_t r = { 0, 0, disp.width, disp.height }; + const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height }; disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET; disp.framebufferTarget->hints = 0; disp.framebufferTarget->flags = 0; @@ -508,6 +530,7 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { &disp.framebufferTarget->displayFrame; disp.framebufferTarget->acquireFenceFd = -1; disp.framebufferTarget->releaseFenceFd = -1; + disp.framebufferTarget->planeAlpha = 0xFF; } disp.list->retireFenceFd = -1; disp.list->flags = HWC_GEOMETRY_CHANGED; @@ -524,7 +547,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id, DisplayData& disp(mDisplayData[id]); if (!disp.framebufferTarget) { // this should never happen, but apparently eglCreateWindowSurface() - // triggers a SurfaceTextureClient::queueBuffer() on some + // triggers a Surface::queueBuffer() on some // devices (!?) -- log and ignore. ALOGE("HWComposer: framebufferTarget is null"); // CallStack stack; @@ -534,7 +557,7 @@ status_t HWComposer::setFramebufferTarget(int32_t id, } int acquireFenceFd = -1; - if (acquireFence != NULL) { + if (acquireFence->isValid()) { acquireFenceFd = acquireFence->dup(); } @@ -562,7 +585,7 @@ status_t HWComposer::prepare() { } mLists[i] = disp.list; if (mLists[i]) { - if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_EXP)) { mLists[i]->outbuf = NULL; mLists[i]->outbufAcquireFenceFd = -1; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { @@ -611,20 +634,20 @@ status_t HWComposer::prepare() { } bool HWComposer::hasHwcComposition(int32_t id) const { - if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) return false; return mDisplayData[id].hasOvComp; } bool HWComposer::hasGlesComposition(int32_t id) const { - if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) - return false; + if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return true; return mDisplayData[id].hasFbComp; } -int HWComposer::getAndResetReleaseFenceFd(int32_t id) { +sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) { if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) - return BAD_INDEX; + return Fence::NO_FENCE; int fd = INVALID_OPERATION; if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { @@ -635,7 +658,7 @@ int HWComposer::getAndResetReleaseFenceFd(int32_t id) { disp.framebufferTarget->releaseFenceFd = -1; } } - return fd; + return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE; } status_t HWComposer::commit() { @@ -649,13 +672,24 @@ status_t HWComposer::commit() { mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW); } + for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) { + DisplayData& disp(mDisplayData[i]); + if (disp.outbufHandle) { + mLists[i]->outbuf = disp.outbufHandle; + mLists[i]->outbufAcquireFenceFd = + disp.outbufAcquireFence->dup(); + } + } + err = mHwc->set(mHwc, mNumDisplays, mLists); for (size_t i=0 ; i<mNumDisplays ; i++) { DisplayData& disp(mDisplayData[i]); + disp.lastDisplayFence = disp.lastRetireFence; + disp.lastRetireFence = Fence::NO_FENCE; if (disp.list) { if (disp.list->retireFenceFd != -1) { - close(disp.list->retireFenceFd); + disp.lastRetireFence = new Fence(disp.list->retireFenceFd); disp.list->retireFenceFd = -1; } disp.list->flags &= ~HWC_GEOMETRY_CHANGED; @@ -666,7 +700,7 @@ status_t HWComposer::commit() { } status_t HWComposer::release(int disp) { - LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); if (mHwc) { eventControl(disp, HWC_EVENT_VSYNC, 0); return (status_t)mHwc->blank(mHwc, disp, 1); @@ -675,7 +709,7 @@ status_t HWComposer::release(int disp) { } status_t HWComposer::acquire(int disp) { - LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); + LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE); if (mHwc) { return (status_t)mHwc->blank(mHwc, disp, 0); } @@ -684,17 +718,15 @@ status_t HWComposer::acquire(int disp) { void HWComposer::disconnectDisplay(int disp) { LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY); - if (disp >= HWC_NUM_DISPLAY_TYPES) { - // nothing to do for these yet - return; - } DisplayData& dd(mDisplayData[disp]); - if (dd.list != NULL) { - free(dd.list); - dd.list = NULL; - dd.framebufferTarget = NULL; // points into dd.list - dd.fbTargetHandle = NULL; - } + free(dd.list); + dd.list = NULL; + dd.framebufferTarget = NULL; // points into dd.list + dd.fbTargetHandle = NULL; + dd.outbufHandle = NULL; + dd.lastRetireFence = Fence::NO_FENCE; + dd.lastDisplayFence = Fence::NO_FENCE; + dd.outbufAcquireFence = Fence::NO_FENCE; } int HWComposer::getVisualID() const { @@ -718,9 +750,7 @@ int HWComposer::fbPost(int32_t id, if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { return setFramebufferTarget(id, acquireFence, buffer); } else { - if (acquireFence != NULL) { - acquireFence->waitForever(1000, "HWComposer::fbPost"); - } + acquireFence->waitForever("HWComposer::fbPost"); return mFbDev->post(mFbDev, buffer->handle); } } @@ -745,6 +775,25 @@ void HWComposer::fbDump(String8& result) { } } +status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buf) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return BAD_INDEX; + if (id < VIRTUAL_DISPLAY_ID_BASE) + return INVALID_OPERATION; + + DisplayData& disp(mDisplayData[id]); + disp.outbufHandle = buf->handle; + disp.outbufAcquireFence = acquireFence; + return NO_ERROR; +} + +sp<Fence> HWComposer::getLastRetireFence(int32_t id) { + if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) + return Fence::NO_FENCE; + return mDisplayData[id].lastRetireFence; +} + /* * Helper template to implement a concrete HWCLayer * This holds the pointer to the concrete hwc layer type @@ -775,9 +824,10 @@ private: * This implements the HWCLayer side of HWCIterableLayer. */ class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> { + struct hwc_composer_device_1* mHwc; public: - HWCLayerVersion1(hwc_layer_1_t* layer) - : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer) { } + HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer) + : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { } virtual int32_t getCompositionType() const { return getLayer()->compositionType; @@ -785,10 +835,10 @@ public: virtual uint32_t getHints() const { return getLayer()->hints; } - virtual int getAndResetReleaseFenceFd() { + virtual sp<Fence> getAndResetReleaseFence() { int fd = getLayer()->releaseFenceFd; getLayer()->releaseFenceFd = -1; - return fd; + return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE; } virtual void setAcquireFenceFd(int fenceFd) { getLayer()->acquireFenceFd = fenceFd; @@ -796,17 +846,28 @@ public: virtual void setPerFrameDefaultState() { //getLayer()->compositionType = HWC_FRAMEBUFFER; } + virtual void setPlaneAlpha(uint8_t alpha) { + if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) { + getLayer()->planeAlpha = alpha; + } else { + if (alpha < 0xFF) { + getLayer()->flags |= HWC_SKIP_LAYER; + } + } + } virtual void setDefaultState() { - getLayer()->compositionType = HWC_FRAMEBUFFER; - getLayer()->hints = 0; - getLayer()->flags = HWC_SKIP_LAYER; - getLayer()->handle = 0; - getLayer()->transform = 0; - getLayer()->blending = HWC_BLENDING_NONE; - getLayer()->visibleRegionScreen.numRects = 0; - getLayer()->visibleRegionScreen.rects = NULL; - getLayer()->acquireFenceFd = -1; - getLayer()->releaseFenceFd = -1; + hwc_layer_1_t* const l = getLayer(); + l->compositionType = HWC_FRAMEBUFFER; + l->hints = 0; + l->flags = HWC_SKIP_LAYER; + l->handle = 0; + l->transform = 0; + l->blending = HWC_BLENDING_NONE; + l->visibleRegionScreen.numRects = 0; + l->visibleRegionScreen.rects = NULL; + l->acquireFenceFd = -1; + l->releaseFenceFd = -1; + l->planeAlpha = 0xFF; } virtual void setSkip(bool skip) { if (skip) { @@ -869,7 +930,7 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in if (!mHwc || !disp.list || index > disp.list->numHwLayers) { return LayerListIterator(); } - return LayerListIterator(new HWCLayerVersion1(disp.list->hwLayers), index); + return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index); } /* @@ -907,17 +968,17 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { result.appendFormat(" mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync); for (size_t i=0 ; i<mNumDisplays ; i++) { const DisplayData& disp(mDisplayData[i]); + if (!disp.connected) + continue; - const Vector< sp<LayerBase> >& visibleLayersSortedByZ = + const Vector< sp<Layer> >& visibleLayersSortedByZ = mFlinger->getLayerSortedByZForHwcDisplay(i); - if (disp.connected) { - result.appendFormat( - " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n", - i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); - } + result.appendFormat( + " Display[%d] : %ux%u, xdpi=%f, ydpi=%f, refresh=%lld\n", + i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh); - if (disp.list && disp.connected) { + if (disp.list) { result.appendFormat( " numHwLayers=%u, flags=%08x\n", disp.list->numHwLayers, disp.list->flags); @@ -932,13 +993,11 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const { String8 name("unknown"); if (i < visibleLayersSortedByZ.size()) { - const sp<LayerBase>& layer(visibleLayersSortedByZ[i]); - if (layer->getLayer() != NULL) { - const sp<GraphicBuffer>& buffer( - layer->getLayer()->getActiveBuffer()); - if (buffer != NULL) { - format = buffer->getPixelFormat(); - } + const sp<Layer>& layer(visibleLayersSortedByZ[i]); + const sp<GraphicBuffer>& buffer( + layer->getActiveBuffer()); + if (buffer != NULL) { + format = buffer->getPixelFormat(); } name = layer->getName(); } @@ -1032,5 +1091,22 @@ bool HWComposer::VSyncThread::threadLoop() { return true; } +HWComposer::DisplayData::DisplayData() +: width(0), height(0), format(0), + xdpi(0.0f), ydpi(0.0f), + refresh(0), + connected(false), + hasFbComp(false), hasOvComp(false), + capacity(0), list(NULL), + framebufferTarget(NULL), fbTargetHandle(0), + lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE), + outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE), + events(0) +{} + +HWComposer::DisplayData::~DisplayData() { + free(list); +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 7c67407..604de38 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -22,13 +22,15 @@ #include <hardware/hwcomposer_defs.h> +#include <ui/Fence.h> + +#include <utils/BitSet.h> #include <utils/Condition.h> #include <utils/Mutex.h> #include <utils/StrongPointer.h> #include <utils/Thread.h> #include <utils/Timers.h> #include <utils/Vector.h> -#include <utils/BitSet.h> extern "C" int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, @@ -45,7 +47,6 @@ namespace android { class GraphicBuffer; class Fence; -class LayerBase; class Region; class String8; class SurfaceFlinger; @@ -111,9 +112,9 @@ public: // does this display have layers handled by GLES bool hasGlesComposition(int32_t id) const; - // get the releaseFence file descriptor for the given display + // get the releaseFence file descriptor for a display's framebuffer layer. // the release fence is only valid after commit() - int getAndResetReleaseFenceFd(int32_t id); + sp<Fence> getAndResetReleaseFence(int32_t id); // needed forward declarations class LayerListIterator; @@ -127,6 +128,17 @@ public: int fbCompositionComplete(); void fbDump(String8& result); + // Set the output buffer and acquire fence for a virtual display. + // Returns INVALID_OPERATION if id is not a virtual display. + status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence, + const sp<GraphicBuffer>& buf); + + // Get the retire fence for the last committed frame. This fence will + // signal when the h/w composer is completely finished with the frame. + // For physical displays, it is no longer being displayed. For virtual + // displays, writes to the output buffer are complete. + sp<Fence> getLastRetireFence(int32_t id); + /* * Interface to hardware composer's layers functionality. * This abstracts the HAL interface to layers which can evolve in @@ -140,8 +152,7 @@ public: public: virtual int32_t getCompositionType() const = 0; virtual uint32_t getHints() const = 0; - virtual int getAndResetReleaseFenceFd() = 0; - virtual void setPerFrameDefaultState() = 0; + virtual sp<Fence> getAndResetReleaseFence() = 0; virtual void setDefaultState() = 0; virtual void setSkip(bool skip) = 0; virtual void setBlending(uint32_t blending) = 0; @@ -151,6 +162,7 @@ public: virtual void setVisibleRegionScreen(const Region& reg) = 0; virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0; virtual void setAcquireFenceFd(int fenceFd) = 0; + virtual void setPlaneAlpha(uint8_t alpha) = 0; virtual void onDisplayed() = 0; }; @@ -233,6 +245,7 @@ public: // HWC_DISPLAY_PRIMARY). nsecs_t getRefreshPeriod(int disp) const; nsecs_t getRefreshTimestamp(int disp) const; + sp<Fence> getDisplayFence(int disp) const; uint32_t getWidth(int disp) const; uint32_t getHeight(int disp) const; uint32_t getFormat(int disp) const; @@ -240,6 +253,9 @@ public: float getDpiY(int disp) const; bool isConnected(int disp) const; + status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h, + uint32_t format); + // this class is only used to fake the VSync event on systems that don't // have it. class VSyncThread : public Thread { @@ -263,7 +279,7 @@ public: private: void loadHwcModule(); - void loadFbHalModule(); + int loadFbHalModule(); LayerListIterator getLayerIterator(int32_t id, size_t index); @@ -286,13 +302,8 @@ private: struct DisplayData { - DisplayData() : xdpi(0), ydpi(0), refresh(0), - connected(false), hasFbComp(false), hasOvComp(false), - capacity(0), list(NULL), - framebufferTarget(NULL), fbTargetHandle(NULL), events(0) { } - ~DisplayData() { - free(list); - } + DisplayData(); + ~DisplayData(); uint32_t width; uint32_t height; uint32_t format; // pixel format from FB hal, for pre-hwc-1.1 @@ -306,6 +317,12 @@ private: hwc_display_contents_1* list; hwc_layer_1* framebufferTarget; buffer_handle_t fbTargetHandle; + sp<Fence> lastRetireFence; // signals when the last set op retires + sp<Fence> lastDisplayFence; // signals when the last set op takes + // effect on screen + buffer_handle_t outbufHandle; + sp<Fence> outbufAcquireFence; + // protected by mEventControlLock int32_t events; }; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp new file mode 100644 index 0000000..2838b23 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -0,0 +1,56 @@ +/* + * Copyright 2013 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 "VirtualDisplaySurface.h" + +#include <cutils/log.h> +#include <gui/IGraphicBufferProducer.h> + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, + const sp<IGraphicBufferProducer>& sink, const String8& name) +: mSink(sink) +{ + LOG_ALWAYS_FATAL_IF(dispId >= 0); +} + +VirtualDisplaySurface::~VirtualDisplaySurface() { +} + +sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const { + return mSink; +} + +status_t VirtualDisplaySurface::compositionComplete() { + return NO_ERROR; +} + +status_t VirtualDisplaySurface::advanceFrame() { + return NO_ERROR; +} + +void VirtualDisplaySurface::onFrameCommitted() { +} + +void VirtualDisplaySurface::dump(String8& result) const { +} + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h new file mode 100644 index 0000000..f321795 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -0,0 +1,55 @@ +/* + * Copyright 2013 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_SF_VIRTUAL_DISPLAY_SURFACE_H +#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H + +#include "DisplaySurface.h" + +// --------------------------------------------------------------------------- +namespace android { +// --------------------------------------------------------------------------- + +class HWComposer; + +/* This DisplaySurface implementation is a stub used for developing HWC + * virtual display support. It is currently just a passthrough. + */ +class VirtualDisplaySurface : public DisplaySurface { +public: + VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, + const sp<IGraphicBufferProducer>& sink, + const String8& name); + + virtual sp<IGraphicBufferProducer> getIGraphicBufferProducer() const; + + virtual status_t compositionComplete(); + virtual status_t advanceFrame(); + virtual void onFrameCommitted(); + virtual void dump(String8& result) const; + +private: + virtual ~VirtualDisplaySurface(); + + sp<IGraphicBufferProducer> mSink; +}; + +// --------------------------------------------------------------------------- +} // namespace android +// --------------------------------------------------------------------------- + +#endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H + diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index edb9fa5..4d0fc79 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -41,7 +41,7 @@ EventThread::EventThread(const sp<SurfaceFlinger>& flinger) mUseSoftwareVSync(false), mDebugVsyncEnabled(false) { - for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) { + for (int32_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[i].header.id = 0; mVSyncEvent[i].header.timestamp = 0; @@ -112,11 +112,11 @@ void EventThread::onScreenAcquired() { void EventThread::onVSyncReceived(int type, nsecs_t timestamp) { - ALOGE_IF(type >= HWC_DISPLAY_TYPES_SUPPORTED, - "received event for an invalid display (id=%d)", type); + ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES, + "received vsync event for an invalid display (id=%d)", type); Mutex::Autolock _l(mLock); - if (type < HWC_DISPLAY_TYPES_SUPPORTED) { + if (type < HWC_NUM_DISPLAY_TYPES) { mVSyncEvent[type].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[type].header.id = type; mVSyncEvent[type].header.timestamp = timestamp; @@ -126,11 +126,11 @@ void EventThread::onVSyncReceived(int type, nsecs_t timestamp) { } void EventThread::onHotplugReceived(int type, bool connected) { - ALOGE_IF(type >= HWC_DISPLAY_TYPES_SUPPORTED, - "received event for an invalid display (id=%d)", type); + ALOGE_IF(type >= HWC_NUM_DISPLAY_TYPES, + "received hotplug event for an invalid display (id=%d)", type); Mutex::Autolock _l(mLock); - if (type < HWC_DISPLAY_TYPES_SUPPORTED) { + if (type < HWC_NUM_DISPLAY_TYPES) { DisplayEventReceiver::Event event; event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG; event.header.id = type; @@ -184,7 +184,7 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent( size_t vsyncCount = 0; nsecs_t timestamp = 0; - for (int32_t i=0 ; i<HWC_DISPLAY_TYPES_SUPPORTED ; i++) { + for (int32_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { timestamp = mVSyncEvent[i].header.timestamp; if (timestamp) { // we have a vsync event to dispatch diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp new file mode 100644 index 0000000..9b55d44 --- /dev/null +++ b/services/surfaceflinger/FrameTracker.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012 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. + */ + +// This is needed for stdint.h to define INT64_MAX in C++ +#define __STDC_LIMIT_MACROS + +#include <ui/Fence.h> + +#include <utils/String8.h> + +#include "FrameTracker.h" + +namespace android { + +FrameTracker::FrameTracker() : + mOffset(0), + mNumFences(0) { +} + +void FrameTracker::setDesiredPresentTime(nsecs_t presentTime) { + Mutex::Autolock lock(mMutex); + mFrameRecords[mOffset].desiredPresentTime = presentTime; +} + +void FrameTracker::setFrameReadyTime(nsecs_t readyTime) { + Mutex::Autolock lock(mMutex); + mFrameRecords[mOffset].frameReadyTime = readyTime; +} + +void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) { + Mutex::Autolock lock(mMutex); + mFrameRecords[mOffset].frameReadyFence = readyFence; + mNumFences++; +} + +void FrameTracker::setActualPresentTime(nsecs_t presentTime) { + Mutex::Autolock lock(mMutex); + mFrameRecords[mOffset].actualPresentTime = presentTime; +} + +void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) { + Mutex::Autolock lock(mMutex); + mFrameRecords[mOffset].actualPresentFence = readyFence; + mNumFences++; +} + +void FrameTracker::advanceFrame() { + Mutex::Autolock lock(mMutex); + mOffset = (mOffset+1) % NUM_FRAME_RECORDS; + mFrameRecords[mOffset].desiredPresentTime = INT64_MAX; + mFrameRecords[mOffset].frameReadyTime = INT64_MAX; + mFrameRecords[mOffset].actualPresentTime = INT64_MAX; + + if (mFrameRecords[mOffset].frameReadyFence != NULL) { + // We're clobbering an unsignaled fence, so we need to decrement the + // fence count. + mFrameRecords[mOffset].frameReadyFence = NULL; + mNumFences--; + } + + if (mFrameRecords[mOffset].actualPresentFence != NULL) { + // We're clobbering an unsignaled fence, so we need to decrement the + // fence count. + mFrameRecords[mOffset].actualPresentFence = NULL; + mNumFences--; + } + + // Clean up the signaled fences to keep the number of open fence FDs in + // this process reasonable. + processFencesLocked(); +} + +void FrameTracker::clear() { + Mutex::Autolock lock(mMutex); + for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) { + mFrameRecords[i].desiredPresentTime = 0; + mFrameRecords[i].frameReadyTime = 0; + mFrameRecords[i].actualPresentTime = 0; + mFrameRecords[i].frameReadyFence.clear(); + mFrameRecords[i].actualPresentFence.clear(); + } + mNumFences = 0; + mFrameRecords[mOffset].desiredPresentTime = INT64_MAX; + mFrameRecords[mOffset].frameReadyTime = INT64_MAX; + mFrameRecords[mOffset].actualPresentTime = INT64_MAX; +} + +void FrameTracker::processFencesLocked() const { + FrameRecord* records = const_cast<FrameRecord*>(mFrameRecords); + int& numFences = const_cast<int&>(mNumFences); + + for (int i = 1; i < NUM_FRAME_RECORDS && numFences > 0; i++) { + size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS; + + const sp<Fence>& rfence = records[idx].frameReadyFence; + if (rfence != NULL) { + records[idx].frameReadyTime = rfence->getSignalTime(); + if (records[idx].frameReadyTime < INT64_MAX) { + records[idx].frameReadyFence = NULL; + numFences--; + } + } + + const sp<Fence>& pfence = records[idx].actualPresentFence; + if (pfence != NULL) { + records[idx].actualPresentTime = pfence->getSignalTime(); + if (records[idx].actualPresentTime < INT64_MAX) { + records[idx].actualPresentFence = NULL; + numFences--; + } + } + } +} + +void FrameTracker::dump(String8& result) const { + Mutex::Autolock lock(mMutex); + processFencesLocked(); + + const size_t o = mOffset; + for (size_t i = 1; i < NUM_FRAME_RECORDS; i++) { + const size_t index = (o+i) % NUM_FRAME_RECORDS; + result.appendFormat("%lld\t%lld\t%lld\n", + mFrameRecords[index].desiredPresentTime, + mFrameRecords[index].actualPresentTime, + mFrameRecords[index].frameReadyTime); + } + result.append("\n"); +} + +} // namespace android diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h new file mode 100644 index 0000000..3d122c4 --- /dev/null +++ b/services/surfaceflinger/FrameTracker.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2012 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_FRAMETRACKER_H +#define ANDROID_FRAMETRACKER_H + +#include <stddef.h> + +#include <utils/Mutex.h> +#include <utils/Timers.h> +#include <utils/RefBase.h> + +namespace android { + +class String8; +class Fence; + +// FrameTracker tracks information about the most recently rendered frames. It +// uses a circular buffer of frame records, and is *NOT* thread-safe - +// mutexing must be done at a higher level if multi-threaded access is +// possible. +// +// Some of the time values tracked may be set either as a specific timestamp +// or a fence. When a non-NULL fence is set for a given time value, the +// signal time of that fence is used instead of the timestamp. +class FrameTracker { + +public: + // NUM_FRAME_RECORDS is the size of the circular buffer used to track the + // frame time history. + enum { NUM_FRAME_RECORDS = 128 }; + + FrameTracker(); + + // setDesiredPresentTime sets the time at which the current frame + // should be presented to the user under ideal (i.e. zero latency) + // conditions. + void setDesiredPresentTime(nsecs_t desiredPresentTime); + + // setFrameReadyTime sets the time at which the current frame became ready + // to be presented to the user. For example, if the frame contents is + // being written to memory by some asynchronous hardware, this would be + // the time at which those writes completed. + void setFrameReadyTime(nsecs_t readyTime); + + // setFrameReadyFence sets the fence that is used to get the time at which + // the current frame became ready to be presented to the user. + void setFrameReadyFence(const sp<Fence>& readyFence); + + // setActualPresentTime sets the timestamp at which the current frame became + // visible to the user. + void setActualPresentTime(nsecs_t displayTime); + + // setActualPresentFence sets the fence that is used to get the time + // at which the current frame became visible to the user. + void setActualPresentFence(const sp<Fence>& fence); + + // advanceFrame advances the frame tracker to the next frame. + void advanceFrame(); + + // clear resets all the tracked frame data to zero. + void clear(); + + // dump appends the current frame display time history to the result string. + void dump(String8& result) const; + +private: + struct FrameRecord { + FrameRecord() : + desiredPresentTime(0), + frameReadyTime(0), + actualPresentTime(0) {} + nsecs_t desiredPresentTime; + nsecs_t frameReadyTime; + nsecs_t actualPresentTime; + sp<Fence> frameReadyFence; + sp<Fence> actualPresentFence; + }; + + // processFences iterates over all the frame records that have a fence set + // and replaces that fence with a timestamp if the fence has signaled. If + // the fence is not signaled the record's displayTime is set to INT64_MAX. + // + // This method is const because although it modifies the frame records it + // does so in such a way that the information represented should not + // change. This allows it to be called from the dump method. + void processFencesLocked() const; + + // mFrameRecords is the circular buffer storing the tracked data for each + // frame. + FrameRecord mFrameRecords[NUM_FRAME_RECORDS]; + + // mOffset is the offset into mFrameRecords of the current frame. + size_t mOffset; + + // mNumFences is the total number of fences set in the frame records. It + // is incremented each time a fence is added and decremented each time a + // signaled fence is removed in processFences or if advanceFrame clobbers + // a fence. + // + // The number of fences is tracked so that the run time of processFences + // doesn't grow with NUM_FRAME_RECORDS. + int mNumFences; + + // mMutex is used to protect access to all member variables. + mutable Mutex mMutex; +}; + +} + +#endif // ANDROID_FRAMETRACKER_H diff --git a/services/surfaceflinger/GLExtensions.cpp b/services/surfaceflinger/GLExtensions.cpp index 493122d..e5fb083 100644 --- a/services/surfaceflinger/GLExtensions.cpp +++ b/services/surfaceflinger/GLExtensions.cpp @@ -28,7 +28,8 @@ ANDROID_SINGLETON_STATIC_INSTANCE( GLExtensions ) GLExtensions::GLExtensions() : mHaveTextureExternal(false), mHaveNpot(false), - mHaveDirectTexture(false) + mHaveDirectTexture(false), + mHaveFramebufferObject(false) { } @@ -79,7 +80,7 @@ void GLExtensions::initWithGLStrings( mHaveDirectTexture = true; } #else -#warning "EGL_ANDROID_image_native_buffer not supported" +#error "EGL_ANDROID_image_native_buffer not supported" #endif if (hasExtension("GL_ARB_texture_non_power_of_two")) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 7edbdc5..4779804 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -50,116 +50,122 @@ namespace android { // --------------------------------------------------------------------------- -Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client) - : LayerBaseClient(flinger, client), +int32_t Layer::sSequence = 1; + +Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : 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), - mFrameLatencyOffset(0), - 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) { - LayerBaseClient::onLayerDisplayed(hw, layer); - if (layer) { - mSurfaceTexture->setReleaseFence(layer->getAndResetReleaseFenceFd()); - } + uint32_t layerFlags = 0; + if (flags & ISurfaceComposerClient::eHidden) + layerFlags = layer_state_t::eLayerHidden; + + if (flags & ISurfaceComposerClient::eNonPremultiplied) + mPremultipliedAlpha = false; + + mName = name; + + 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; } void Layer::onFirstRef() { - LayerBaseClient::onFirstRef(); - - struct FrameQueuedListener : public SurfaceTexture::FrameAvailableListener { - FrameQueuedListener(Layer* layer) : mLayer(layer) { } - private: - wp<Layer> mLayer; - virtual void onFrameAvailable() { - sp<Layer> that(mLayer.promote()); - if (that != 0) { - that->onFrameQueued(); - } - } - }; - - // Creates a custom BufferQueue for SurfaceTexture to use - sp<BufferQueue> bq = new SurfaceTextureLayer(); - mSurfaceTexture = new SurfaceTexture(mTextureName, true, + // Creates a custom BufferQueue for SurfaceFlingerConsumer to use + sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger); + mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true, GL_TEXTURE_EXTERNAL_OES, false, bq); - mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); - mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this)); - mSurfaceTexture->setSynchronousMode(true); + mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); + mSurfaceFlingerConsumer->setFrameAvailableListener(this); + mSurfaceFlingerConsumer->setSynchronousMode(true); + mSurfaceFlingerConsumer->setName(mName); #ifdef TARGET_DISABLE_TRIPLE_BUFFERING #warning "disabling triple buffering" - mSurfaceTexture->setDefaultMaxBufferCount(2); + mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); #else - mSurfaceTexture->setDefaultMaxBufferCount(3); + mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); #endif const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); } -Layer::~Layer() -{ +Layer::~Layer() { + sp<Client> c(mClientRef.promote()); + if (c != 0) { + c->detachLayer(this); + } mFlinger->deleteTextureAsync(mTextureName); } -void Layer::onFrameQueued() { - android_atomic_inc(&mQueuedFrames); - mFlinger->signalLayerUpdate(); -} +// --------------------------------------------------------------------------- +// callbacks +// --------------------------------------------------------------------------- -// called with SurfaceFlinger::mStateLock as soon as the layer is entered -// in the purgatory list -void Layer::onRemoved() -{ - mSurfaceTexture->abandon(); +void Layer::onLayerDisplayed(const sp<const DisplayDevice>& hw, + HWComposer::HWCLayerInterface* layer) { + if (layer) { + layer->onDisplayed(); + mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence()); + } } -void Layer::setName(const String8& name) { - LayerBase::setName(name); - mSurfaceTexture->setName(name); +void Layer::onFrameAvailable() { + android_atomic_inc(&mQueuedFrames); + mFlinger->signalLayerUpdate(); } -sp<ISurface> Layer::createSurface() -{ - class BSurface : public BnSurface, public LayerCleaner { - wp<const Layer> mOwner; - virtual sp<ISurfaceTexture> getSurfaceTexture() const { - sp<ISurfaceTexture> res; - sp<const Layer> that( mOwner.promote() ); - if (that != NULL) { - res = that->mSurfaceTexture->getBufferQueue(); - } - return res; - } - public: - BSurface(const sp<SurfaceFlinger>& flinger, - const sp<Layer>& layer) - : LayerCleaner(flinger, layer), mOwner(layer) { } - }; - sp<ISurface> sur(new BSurface(mFlinger, this)); - return sur; +// called with SurfaceFlinger::mStateLock from the drawing thread after +// the layer has been remove from the current state list (and just before +// it's removed from the drawing state list) +void Layer::onRemoved() { + mSurfaceFlingerConsumer->abandon(); } -wp<IBinder> Layer::getSurfaceTextureBinder() const -{ - return mSurfaceTexture->getBufferQueue()->asBinder(); +// --------------------------------------------------------------------------- +// set-up +// --------------------------------------------------------------------------- + +String8 Layer::getName() const { + return mName; } status_t Layer::setBuffers( uint32_t w, uint32_t h, @@ -190,33 +196,124 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque); mCurrentOpacity = getOpacityForFormat(format); - mSurfaceTexture->setDefaultBufferSize(w, h); - mSurfaceTexture->setDefaultBufferFormat(format); - mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); + mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); + mSurfaceFlingerConsumer->setDefaultBufferFormat(format); + mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); return NO_ERROR; } -Rect Layer::computeBufferCrop() const { - // Start with the SurfaceTexture's buffer crop... +sp<IBinder> Layer::getHandle() { + Mutex::Autolock _l(mLock); + + LOG_ALWAYS_FATAL_IF(mHasSurface, + "Layer::getHandle() has already been called"); + + mHasSurface = true; + + /* + * The layer handle is just a BBinder object passed to the client + * (remote process) -- we don't keep any reference on our side such that + * the dtor is called when the remote side let go of its reference. + * + * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for + * this layer when the handle is destroyed. + */ + + class Handle : public BBinder, public LayerCleaner { + wp<const Layer> mOwner; + public: + Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer) + : LayerCleaner(flinger, layer), mOwner(layer) { + } + }; + + return new Handle(mFlinger, this); +} + +sp<BufferQueue> Layer::getBufferQueue() const { + return mSurfaceFlingerConsumer->getBufferQueue(); +} + +//virtual sp<IGraphicBufferProducer> getSurfaceTexture() const { +// sp<IGraphicBufferProducer> res; +// sp<const Layer> that( mOwner.promote() ); +// if (that != NULL) { +// res = that->mSurfaceFlingerConsumer->getBufferQueue(); +// } +// return res; +//} + +// --------------------------------------------------------------------------- +// 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) Rect crop; if (!mCurrentCrop.isEmpty()) { + // if the buffer crop is defined, we use that crop = mCurrentCrop; - } else if (mActiveBuffer != NULL){ - crop = Rect(mActiveBuffer->getWidth(), mActiveBuffer->getHeight()); + } else if (mActiveBuffer != NULL) { + // otherwise we use the whole buffer + crop = mActiveBuffer->getBounds(); } else { + // if we don't have a buffer yet, we use an empty/invalid crop crop.makeInvalid(); - return crop; } + return crop; +} - // ... then reduce that in the same proportions as the window crop reduces - // the window size. - const State& s(drawingState()); +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 - // SurfaceTexture. - uint32_t invTransform = mCurrentTransform; + // SurfaceFlingerConsumer. + uint32_t invTransform = getContentTransform(); int winWidth = s.active.w; int winHeight = s.active.h; if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { @@ -225,17 +322,24 @@ Rect Layer::computeBufferCrop() const { winWidth = s.active.h; winHeight = s.active.w; } - Rect winCrop = s.active.crop.transform(invTransform, - s.active.w, s.active.h); + 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); - crop.left += int(ceilf(float(winCrop.left) * xScale)); - crop.top += int(ceilf(float(winCrop.top) * yScale)); - crop.right -= int(ceilf(float(winWidth - winCrop.right) * xScale)); - crop.bottom -= int(ceilf(float(winHeight - winCrop.bottom) * yScale)); - } + 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; } @@ -243,21 +347,32 @@ void Layer::setGeometry( const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer) { - LayerBaseClient::setGeometry(hw, layer); + layer.setDefaultState(); // enable this layer layer.setSkip(false); - // we can't do alpha-fade with the hwc HAL - const State& s(drawingState()); - if (s.alpha < 0xFF) { + if (isSecure() && !hw->isSecure()) { layer.setSkip(true); } - if (isSecure() && !hw->isSecure()) { - 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); + /* * Transformations are applied in this order: * 1) buffer orientation/flip/mirror @@ -267,23 +382,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); } - layer.setCrop(computeBufferCrop()); } void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer) { - LayerBaseClient::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); @@ -297,8 +418,8 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& hw, // acquire fence the first time a new buffer is acquired on EACH display. if (layer.getCompositionType() == HWC_OVERLAY) { - sp<Fence> fence = mSurfaceTexture->getCurrentFence(); - if (fence.get()) { + sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence(); + if (fence->isValid()) { fenceFd = fence->dup(); if (fenceFd == -1) { ALOGW("failed to dup layer fence, skipping sync: %d", errno); @@ -308,6 +429,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(); @@ -327,8 +460,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) ); } @@ -340,9 +473,11 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const return; } - status_t err = mSurfaceTexture->doGLFenceWait(); - if (err != OK) { - ALOGE("onDraw: failed waiting for fence: %d", err); + // Bind the current buffer to the GL texture, and wait for it to be + // ready for us to draw into. + status_t err = mSurfaceFlingerConsumer->bindTextureImage(); + if (err != NO_ERROR) { + ALOGW("onDraw: bindTextureImage failed (err=%d)", err); // Go ahead and draw the buffer anyway; no matter what we do the screen // is probably going to have something visibly wrong. } @@ -355,8 +490,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const // Query the texture matrix given our current filtering mode. float textureMatrix[16]; - mSurfaceTexture->setFilteringEnabled(useFiltering); - mSurfaceTexture->getTransformMatrix(textureMatrix); + mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering); + mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix); // Set things up for texturing. glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureName); @@ -386,6 +521,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 @@ -404,6 +652,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 { @@ -425,8 +696,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()); @@ -475,7 +777,7 @@ uint32_t Layer::doTransaction(uint32_t flags) // record the new size, form this point on, when the client request // a buffer, it'll get the new size. - mSurfaceTexture->setDefaultBufferSize( + mSurfaceFlingerConsumer->setDefaultBufferSize( temp.requested.w, temp.requested.h); } @@ -485,7 +787,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. @@ -498,15 +800,116 @@ 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.requestedTransparentRegion = 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; } // ---------------------------------------------------------------------------- @@ -520,18 +923,38 @@ bool Layer::onPreComposition() { void Layer::onPostComposition() { if (mFrameLatencyNeeded) { + nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp(); + mFrameTracker.setDesiredPresentTime(desiredPresentTime); + + sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence(); + if (frameReadyFence->isValid()) { + mFrameTracker.setFrameReadyFence(frameReadyFence); + } else { + // There was no fence for this frame, so assume that it was ready + // to be presented at the desired present time. + mFrameTracker.setFrameReadyTime(desiredPresentTime); + } + const HWComposer& hwc = mFlinger->getHwComposer(); - const size_t offset = mFrameLatencyOffset; - mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp(); - mFrameStats[offset].set = systemTime(); - mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); - mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128; + sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); + if (presentFence->isValid()) { + mFrameTracker.setActualPresentFence(presentFence); + } else { + // The HWC doesn't support present fences, so use the refresh + // timestamp instead. + nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + mFrameTracker.setActualPresentTime(presentTime); + } + + mFrameTracker.advanceFrame(); mFrameLatencyNeeded = false; } } bool Layer::isVisible() const { - return LayerBaseClient::isVisible() && (mActiveBuffer != NULL); + const Layer::State& s(mDrawingState); + return !(s.flags & layer_state_t::eLayerHidden) && s.alpha + && (mActiveBuffer != NULL); } Region Layer::latchBuffer(bool& recomputeVisibleRegions) @@ -559,7 +982,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) mFlinger->signalLayerUpdate(); } - struct Reject : public SurfaceTexture::BufferRejecter { + struct Reject : public SurfaceFlingerConsumer::BufferRejecter { Layer::State& front; Layer::State& current; bool& recomputeVisibleRegions; @@ -584,7 +1007,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) swap(bufWidth, bufHeight); } - bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; if (front.active != front.requested) { @@ -637,6 +1059,27 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return true; } } + + // if the transparent region has changed (this test is + // conservative, but that's fine, worst case we're doing + // a bit of extra work), we latch the new one and we + // trigger a visible-region recompute. + if (!front.activeTransparentRegion.isTriviallyEqual( + front.requestedTransparentRegion)) { + front.activeTransparentRegion = front.requestedTransparentRegion; + + // We also need to update the current state so that + // we don't end-up overwriting the drawing state with + // this stale current state during the next transaction + // + // NOTE: We don't need to hold the transaction lock here + // because State::active is only accessed from this thread. + current.activeTransparentRegion = front.activeTransparentRegion; + + // recompute visible region + recomputeVisibleRegions = true; + } + return false; } }; @@ -644,14 +1087,14 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) Reject r(mDrawingState, currentState(), recomputeVisibleRegions); - if (mSurfaceTexture->updateTexImage(&r, true) < NO_ERROR) { + if (mSurfaceFlingerConsumer->updateTexImage(&r) != NO_ERROR) { // something happened! recomputeVisibleRegions = true; return outDirtyRegion; } // update the active buffer - mActiveBuffer = mSurfaceTexture->getCurrentBuffer(); + mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(); if (mActiveBuffer == NULL) { // this can only happen if the very first buffer was rejected. return outDirtyRegion; @@ -665,9 +1108,9 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) recomputeVisibleRegions = true; } - Rect crop(mSurfaceTexture->getCurrentCrop()); - const uint32_t transform(mSurfaceTexture->getCurrentTransform()); - const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode()); + Rect crop(mSurfaceFlingerConsumer->getCurrentCrop()); + const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform()); + const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode()); if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || (scalingMode != mCurrentScalingMode)) @@ -705,9 +1148,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 { - LayerBaseClient::dump(result, buffer, SIZE); + const Layer::State& s(drawingState()); + + snprintf(buffer, SIZE, + "+ %s %p (%s)\n", + getTypeId(), this, getName().string()); + result.append(buffer); + + s.activeTransparentRegion.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; @@ -726,61 +1224,34 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const result.append(buffer); - if (mSurfaceTexture != 0) { - mSurfaceTexture->dump(result, " ", buffer, SIZE); + if (mSurfaceFlingerConsumer != 0) { + mSurfaceFlingerConsumer->dump(result, " ", buffer, SIZE); } } -void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const -{ - LayerBaseClient::dumpStats(result, buffer, SIZE); - const size_t o = mFrameLatencyOffset; - const nsecs_t period = - mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); - result.appendFormat("%lld\n", period); - for (size_t i=0 ; i<128 ; i++) { - const size_t index = (o+i) % 128; - const nsecs_t time_app = mFrameStats[index].timestamp; - const nsecs_t time_set = mFrameStats[index].set; - const nsecs_t time_vsync = mFrameStats[index].vsync; - result.appendFormat("%lld\t%lld\t%lld\n", - time_app, - time_vsync, - time_set); - } - result.append("\n"); + +void Layer::shortDump(String8& result, char* scratch, size_t size) const { + Layer::dump(result, scratch, size); } -void Layer::clearStats() -{ - LayerBaseClient::clearStats(); - memset(mFrameStats, 0, sizeof(mFrameStats)); +void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const { + mFrameTracker.dump(result); } -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::clearStats() { + mFrameTracker.clear(); } -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; - } - } - mSurfaceTexture->setTransformHint(orientation); +// --------------------------------------------------------------------------- + +Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, + const sp<Layer>& 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 c5eb26b..2765db1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -20,103 +20,351 @@ #include <stdint.h> #include <sys/types.h> -#include <gui/SurfaceTexture.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> +#include <utils/RefBase.h> +#include <utils/String8.h> #include <utils/Timers.h> #include <ui/GraphicBuffer.h> #include <ui/PixelFormat.h> +#include <ui/Region.h> #include <gui/ISurfaceComposerClient.h> -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES/gl.h> -#include <GLES/glext.h> +#include <private/gui/LayerState.h> -#include "LayerBase.h" +#include "FrameTracker.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; // --------------------------------------------------------------------------- -class Layer : public LayerBaseClient -{ +/* + * 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 SurfaceFlingerConsumer::FrameAvailableListener { + static int32_t sSequence; + public: - Layer(SurfaceFlinger* flinger, const sp<Client>& client); - virtual ~Layer(); + 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, + }; - virtual const char* getTypeId() const { return "Layer"; } + 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; + // the transparentRegion hint is a bit special, it's latched only + // when we receive a buffer -- this is because it's "content" + // dependent. + Region activeTransparentRegion; + Region requestedTransparentRegion; + }; + + 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>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags); + virtual ~Layer(); // the this layer's size and format - status_t setBuffers(uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags=0); + status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); + + // 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); - bool isFixedSize() const; + void computeGeometry(const sp<const DisplayDevice>& hw, LayerMesh* mesh) const; + Rect computeBounds() const; + + sp<IBinder> getHandle(); + sp<BufferQueue> getBufferQueue() const; + String8 getName() const; + + // ----------------------------------------------------------------------- + + virtual const char* getTypeId() const { return "Layer"; } - // LayerBase interface virtual void setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); virtual void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); virtual void setAcquireFence(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer); + + /* + * called after page-flip + */ virtual void onLayerDisplayed(const sp<const DisplayDevice>& 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<const DisplayDevice>& hw, const Region& clip) const; + virtual void draw(const sp<const DisplayDevice>& hw); + + /* + * onDraw - draws the surface. + */ virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const; + + /* + * needsLinearFiltering - true if this surface's state requires filtering + */ + virtual bool needsFiltering(const sp<const DisplayDevice>& 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<Layer> getLayer() const { return const_cast<Layer*>(this); } - virtual void setName(const String8& name); + + /* + * isVisible - true if this layer is visible, false otherwise + */ virtual bool isVisible() const; - // LayerBaseClient interface - virtual wp<IBinder> getSurfaceTextureBinder() const; + /* + * isFixedSize - true if content has a fixed size + */ + virtual bool isFixedSize() const; + + /* + * called with the state lock when the surface is removed from the + * current list + */ + virtual void onRemoved(); - // only for debugging - inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; } - // Updates the transform hint in our SurfaceTexture to match + // Updates the transform hint in our SurfaceFlingerConsumer to match // the current orientation of the display device. virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const; -protected: - virtual void onFirstRef(); + /* + * 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; + + // ----------------------------------------------------------------------- + + void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const; + void setFiltering(bool filtering); + bool getFiltering() const; + + // only for debugging + inline const sp<GraphicBuffer>& 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(); +protected: + // constant + sp<SurfaceFlinger> mFlinger; + + virtual void onFirstRef(); + + /* + * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer) + * is called. + */ + class LayerCleaner { + sp<SurfaceFlinger> mFlinger; + wp<Layer> mLayer; + protected: + ~LayerCleaner(); + public: + LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer); + }; + + private: - friend class SurfaceTextureLayer; - void onFrameQueued(); - virtual sp<ISurface> createSurface(); + // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener + virtual void onFrameAvailable(); + + uint32_t getEffectiveUsage(uint32_t usage) const; + Rect computeCrop(const sp<const DisplayDevice>& hw) const; bool isCropped() const; - Rect computeBufferCrop() const; static bool getOpacityForFormat(uint32_t format); + // drawing + void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip, + GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const; + void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const; + + // ----------------------------------------------------------------------- // constants - sp<SurfaceTexture> mSurfaceTexture; + sp<SurfaceFlingerConsumer> 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; + FrameTracker mFrameTracker; // main thread sp<GraphicBuffer> mActiveBuffer; @@ -126,26 +374,20 @@ private: bool mCurrentOpacity; bool mRefreshPending; bool mFrameLatencyNeeded; - int mFrameLatencyOffset; - - struct Statistics { - Statistics() : timestamp(0), set(0), vsync(0) { } - nsecs_t timestamp; // buffer timestamp - nsecs_t set; // buffer displayed timestamp - nsecs_t vsync; // vsync immediately before set - }; - - // protected by mLock - Statistics mFrameStats[128]; - - // 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 once we've returned this surface's handle + mutable bool mHasSurface; + const wp<Client> mClientRef; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp deleted file mode 100644 index 9b03c74..0000000 --- a/services/surfaceflinger/LayerBase.cpp +++ /dev/null @@ -1,573 +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 <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <utils/Errors.h> -#include <utils/Log.h> -#include <binder/IPCThreadState.h> -#include <binder/IServiceManager.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include <hardware/hardware.h> - -#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) - : contentDirty(false), - sequence(uint32_t(android_atomic_inc(&sSequence))), - mFlinger(flinger), mFiltering(false), - mNeedsFiltering(false), - mTransactionFlags(0), - mPremultipliedAlpha(true), mName("unnamed"), mDebug(false) -{ -} - -LayerBase::~LayerBase() -{ -} - -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<const DisplayDevice>& 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<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]; - } - } -} - -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 s.transform.transform(win); -} - -Region LayerBase::latchBuffer(bool& recomputeVisibleRegions) { - Region result; - return result; -} - -void LayerBase::setGeometry( - const sp<const DisplayDevice>& 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()) { - layer.setBlending(mPremultipliedAlpha ? - HWC_BLENDING_PREMULT : - HWC_BLENDING_COVERAGE); - } - - const Transform& tr = hw->getTransform(); - Rect transformedBounds(computeBounds()); - transformedBounds = tr.transform(transformedBounds); - - // scaling is already applied in transformedBounds - layer.setFrame(transformedBounds); - layer.setCrop(transformedBounds.getBounds()); -} - -void LayerBase::setPerFrameData(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer) { - layer.setPerFrameDefaultState(); - // 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. - const Transform& tr = hw->getTransform(); - layer.setVisibleRegionScreen(tr.transform(visibleRegion)); -} - -void LayerBase::setAcquireFence(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer) { - layer.setAcquireFenceFd(-1); -} - -void LayerBase::onLayerDisplayed(const sp<const DisplayDevice>& 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<const DisplayDevice>& hw, const Region& clip) const -{ - onDraw(hw, clip); -} - -void LayerBase::draw(const sp<const DisplayDevice>& hw) -{ - onDraw( hw, Region(hw->bounds()) ); -} - -void LayerBase::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 LayerBase::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const -{ - clearWithOpenGL(hw, clip, 0,0,0,0); -} - -void LayerBase::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; - }; - - Rect win(s.active.w, s.active.h); - if (!s.active.crop.isEmpty()) { - win.intersect(s.active.crop, &win); - } - - 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"); - - 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", - 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]); - 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<LayerBaseClient> LayerBase::getLayerBaseClient() const { - return 0; -} - -sp<Layer> LayerBase::getLayer() const { - return 0; -} - -// --------------------------------------------------------------------------- - -int32_t LayerBaseClient::sIdentity = 1; - -LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, - const sp<Client>& client) - : LayerBase(flinger), - mHasSurface(false), - mClientRef(client), - mIdentity(uint32_t(android_atomic_inc(&sIdentity))) -{ -} - -LayerBaseClient::~LayerBaseClient() -{ - sp<Client> c(mClientRef.promote()); - if (c != 0) { - c->detachLayer(this); - } -} - -sp<ISurface> LayerBaseClient::createSurface() -{ - class BSurface : public BnSurface, public LayerCleaner { - virtual sp<ISurfaceTexture> getSurfaceTexture() const { return 0; } - public: - BSurface(const sp<SurfaceFlinger>& flinger, - const sp<LayerBaseClient>& layer) - : LayerCleaner(flinger, layer) { } - }; - sp<ISurface> sur(new BSurface(mFlinger, this)); - return sur; -} - -sp<ISurface> LayerBaseClient::getSurface() -{ - sp<ISurface> s; - Mutex::Autolock _l(mLock); - - LOG_ALWAYS_FATAL_IF(mHasSurface, - "LayerBaseClient::getSurface() has already been called"); - - mHasSurface = true; - s = createSurface(); - mClientSurfaceBinder = s->asBinder(); - return s; -} - -wp<IBinder> LayerBaseClient::getSurfaceBinder() const { - return mClientSurfaceBinder; -} - -wp<IBinder> LayerBaseClient::getSurfaceTextureBinder() const { - return 0; -} - -void LayerBaseClient::dump(String8& result, char* buffer, size_t SIZE) const -{ - LayerBase::dump(result, buffer, SIZE); - - sp<Client> client(mClientRef.promote()); - snprintf(buffer, SIZE, - " client=%p, identity=%u\n", - client.get(), getIdentity()); - - result.append(buffer); -} - - -void LayerBaseClient::shortDump(String8& result, char* scratch, size_t size) const -{ - LayerBaseClient::dump(result, scratch, size); -} - -// --------------------------------------------------------------------------- - -LayerBaseClient::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger, - const sp<LayerBaseClient>& layer) - : mFlinger(flinger), mLayer(layer) { -} - -LayerBaseClient::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 4d5a5b0..0000000 --- a/services/surfaceflinger/LayerBase.h +++ /dev/null @@ -1,359 +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 <stdint.h> -#include <sys/types.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES/gl.h> - -#include <utils/RefBase.h> -#include <utils/String8.h> - -#include <ui/Region.h> - -#include <gui/ISurfaceComposerClient.h> - -#include <private/gui/LayerState.h> - -#include "Transform.h" -#include "DisplayHardware/HWComposer.h" - -namespace android { - -// --------------------------------------------------------------------------- - -class Client; -class DisplayDevice; -class GraphicBuffer; -class Layer; -class LayerBaseClient; -class SurfaceFlinger; - -// --------------------------------------------------------------------------- - -class LayerBase : public RefBase -{ - static int32_t sSequence; - -public: - LayerBase(SurfaceFlinger* flinger); - - 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<const DisplayDevice>& hw, LayerMesh* mesh) const; - Rect computeBounds() const; - - - virtual sp<LayerBaseClient> getLayerBaseClient() const; - virtual sp<Layer> getLayer() const; - - virtual const char* getTypeId() const { return "LayerBase"; } - - virtual void setGeometry(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer); - virtual void setPerFrameData(const sp<const DisplayDevice>& hw, - HWComposer::HWCLayerInterface& layer); - virtual void setAcquireFence(const sp<const DisplayDevice>& 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<const DisplayDevice>& hw, const Region& clip) const; - virtual void draw(const sp<const DisplayDevice>& hw); - - /** - * onDraw - draws the surface. - */ - virtual void onDraw(const sp<const DisplayDevice>& 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<const DisplayDevice>& 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<const DisplayDevice>& 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 SurfaceTexture's transform hint, for layers that have - * a SurfaceTexture. - */ - virtual void updateTransformHint(const sp<const DisplayDevice>& hw) 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<const DisplayDevice>& hw, const Region& clip) const; - - void setFiltering(bool filtering); - bool getFiltering() const; - -protected: - void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip, - GLclampf r, GLclampf g, GLclampf b, GLclampf alpha) const; - void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const; - - sp<SurfaceFlinger> 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; - - -public: - // called from class SurfaceFlinger - virtual ~LayerBase(); - -private: - LayerBase(const LayerBase& rhs); -}; - - -// --------------------------------------------------------------------------- - -class LayerBaseClient : public LayerBase -{ -public: - LayerBaseClient(SurfaceFlinger* flinger, const sp<Client>& client); - - virtual ~LayerBaseClient(); - - sp<ISurface> getSurface(); - wp<IBinder> getSurfaceBinder() const; - virtual wp<IBinder> getSurfaceTextureBinder() const; - - virtual sp<LayerBaseClient> getLayerBaseClient() const { - return const_cast<LayerBaseClient*>(this); } - - virtual const char* getTypeId() const { return "LayerBaseClient"; } - - uint32_t getIdentity() const { return mIdentity; } - -protected: - virtual void dump(String8& result, char* scratch, size_t size) const; - virtual void shortDump(String8& result, char* scratch, size_t size) const; - - class LayerCleaner { - sp<SurfaceFlinger> mFlinger; - wp<LayerBaseClient> mLayer; - protected: - ~LayerCleaner(); - public: - LayerCleaner(const sp<SurfaceFlinger>& flinger, - const sp<LayerBaseClient>& layer); - }; - -private: - virtual sp<ISurface> createSurface(); - - mutable Mutex mLock; - mutable bool mHasSurface; - wp<IBinder> mClientSurfaceBinder; - const wp<Client> mClientRef; - // only read - const uint32_t mIdentity; - static int32_t sIdentity; -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_BASE_H diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index 25caa0a..36bafdb 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -33,13 +33,12 @@ namespace android { // --------------------------------------------------------------------------- -LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client) - : LayerBaseClient(flinger, client) -{ +LayerDim::LayerDim(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags) + : Layer(flinger, client, name, w, h, flags) { } -LayerDim::~LayerDim() -{ +LayerDim::~LayerDim() { } void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const @@ -71,6 +70,12 @@ void LayerDim::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) con } } +bool LayerDim::isVisible() const { + const Layer::State& s(drawingState()); + return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; +} + + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h index 06f312d..e19bf52 100644 --- a/services/surfaceflinger/LayerDim.h +++ b/services/surfaceflinger/LayerDim.h @@ -23,16 +23,17 @@ #include <EGL/egl.h> #include <EGL/eglext.h> -#include "LayerBase.h" +#include "Layer.h" // --------------------------------------------------------------------------- namespace android { -class LayerDim : public LayerBaseClient +class LayerDim : public Layer { public: - LayerDim(SurfaceFlinger* flinger, const sp<Client>& client); + LayerDim(SurfaceFlinger* flinger, const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags); virtual ~LayerDim(); virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const; @@ -41,6 +42,9 @@ public: virtual bool isProtectedByApp() const { return false; } virtual bool isProtectedByDRM() const { return false; } virtual const char* getTypeId() const { return "LayerDim"; } + + virtual bool isFixedSize() const { return true; } + virtual bool isVisible() const; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerScreenshot.cpp b/services/surfaceflinger/LayerScreenshot.cpp deleted file mode 100644 index f8009b3..0000000 --- a/services/surfaceflinger/LayerScreenshot.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2011 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 <stdlib.h> -#include <stdint.h> -#include <sys/types.h> - -#include <GLES/gl.h> -#include <GLES/glext.h> - -#include <utils/Errors.h> -#include <utils/Log.h> - -#include <ui/GraphicBuffer.h> - -#include "LayerScreenshot.h" -#include "SurfaceFlinger.h" -#include "DisplayDevice.h" - - -namespace android { -// --------------------------------------------------------------------------- - -LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, - const sp<Client>& client) - : LayerBaseClient(flinger, client), - mTextureName(0), mFlinger(flinger), mIsSecure(false) -{ -} - -LayerScreenshot::~LayerScreenshot() -{ - if (mTextureName) { - mFlinger->deleteTextureAsync(mTextureName); - } -} - -status_t LayerScreenshot::captureLocked(int32_t layerStack) { - GLfloat u, v; - status_t result = mFlinger->renderScreenToTextureLocked(layerStack, - &mTextureName, &u, &v); - if (result != NO_ERROR) { - return result; - } - initTexture(u, v); - - // Currently screenshot always comes from the default display - mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible(); - - return NO_ERROR; -} - -status_t LayerScreenshot::capture() { - GLfloat u, v; - status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v); - if (result != NO_ERROR) { - return result; - } - initTexture(u, v); - - // Currently screenshot always comes from the default display - mIsSecure = mFlinger->getDefaultDisplayDevice()->getSecureLayerVisible(); - - return NO_ERROR; -} - -void LayerScreenshot::initTexture(GLfloat u, GLfloat v) { - glBindTexture(GL_TEXTURE_2D, mTextureName); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - mTexCoords[0] = 0; mTexCoords[1] = v; - mTexCoords[2] = 0; mTexCoords[3] = 0; - mTexCoords[4] = u; mTexCoords[5] = 0; - mTexCoords[6] = u; mTexCoords[7] = v; -} - -void LayerScreenshot::initStates(uint32_t w, uint32_t h, uint32_t flags) { - LayerBaseClient::initStates(w, h, flags); - if (!(flags & ISurfaceComposerClient::eHidden)) { - capture(); - } - if (flags & ISurfaceComposerClient::eSecure) { - ALOGW("ignoring surface flag eSecure - LayerScreenshot is considered " - "secure iff it captures the contents of a secure surface."); - } -} - -uint32_t LayerScreenshot::doTransaction(uint32_t flags) -{ - const LayerBase::State& draw(drawingState()); - const LayerBase::State& curr(currentState()); - - if (draw.flags & layer_state_t::eLayerHidden) { - if (!(curr.flags & layer_state_t::eLayerHidden)) { - // we're going from hidden to visible - status_t err = captureLocked(curr.layerStack); - if (err != NO_ERROR) { - ALOGW("createScreenshotSurface failed (%s)", strerror(-err)); - } - } - } else if (curr.flags & layer_state_t::eLayerHidden) { - // we're going from visible to hidden - if (mTextureName) { - glDeleteTextures(1, &mTextureName); - mTextureName = 0; - } - } - return LayerBaseClient::doTransaction(flags); -} - -void LayerScreenshot::onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const -{ - const State& s(drawingState()); - if (s.alpha>0) { - const GLfloat alpha = s.alpha/255.0f; - const uint32_t fbHeight = hw->getHeight(); - - if (s.alpha == 0xFF) { - glDisable(GL_BLEND); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - } else { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - - GLuint texName = mTextureName; - if (isSecure() && !hw->isSecure()) { - texName = mFlinger->getProtectedTexName(); - } - - LayerMesh mesh; - computeGeometry(hw, &mesh); - - glColor4f(alpha, alpha, alpha, alpha); - - glDisable(GL_TEXTURE_EXTERNAL_OES); - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, texName); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords); - glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); - glDrawArrays(GL_TRIANGLE_FAN, 0, mesh.getVertexCount()); - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } -} - -// --------------------------------------------------------------------------- - -}; // namespace android diff --git a/services/surfaceflinger/LayerScreenshot.h b/services/surfaceflinger/LayerScreenshot.h deleted file mode 100644 index 38cbd88..0000000 --- a/services/surfaceflinger/LayerScreenshot.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2011 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_SCREENSHOT_H -#define ANDROID_LAYER_SCREENSHOT_H - -#include <stdint.h> -#include <sys/types.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "LayerBase.h" - -// --------------------------------------------------------------------------- - -namespace android { - -class LayerScreenshot : public LayerBaseClient -{ - GLuint mTextureName; - GLfloat mTexCoords[8]; - sp<SurfaceFlinger> mFlinger; - bool mIsSecure; -public: - LayerScreenshot(SurfaceFlinger* flinger, const sp<Client>& client); - virtual ~LayerScreenshot(); - - status_t capture(); - - virtual void initStates(uint32_t w, uint32_t h, uint32_t flags); - virtual uint32_t doTransaction(uint32_t flags); - virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip) const; - virtual bool isOpaque() const { return false; } - virtual bool isSecure() const { return mIsSecure; } - virtual bool isProtectedByApp() const { return false; } - virtual bool isProtectedByDRM() const { return false; } - virtual const char* getTypeId() const { return "LayerScreenshot"; } - -private: - status_t captureLocked(int32_t layerStack); - void initTexture(GLfloat u, GLfloat v); -}; - -// --------------------------------------------------------------------------- - -}; // namespace android - -#endif // ANDROID_LAYER_SCREENSHOT_H diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp index 3f77f74..c9c7b96 100644 --- a/services/surfaceflinger/MessageQueue.cpp +++ b/services/surfaceflinger/MessageQueue.cpp @@ -61,6 +61,12 @@ void MessageQueue::Handler::dispatchInvalidate() { } } +void MessageQueue::Handler::dispatchTransaction() { + if ((android_atomic_or(eventMaskTransaction, &mEventMask) & eventMaskTransaction) == 0) { + mQueue.mLooper->sendMessage(this, Message(MessageQueue::TRANSACTION)); + } +} + void MessageQueue::Handler::handleMessage(const Message& message) { switch (message.what) { case INVALIDATE: @@ -71,6 +77,10 @@ void MessageQueue::Handler::handleMessage(const Message& message) { android_atomic_and(~eventMaskRefresh, &mEventMask); mQueue.mFlinger->onMessageReceived(message.what); break; + case TRANSACTION: + android_atomic_and(~eventMaskTransaction, &mEventMask); + mQueue.mFlinger->onMessageReceived(message.what); + break; } } @@ -132,6 +142,7 @@ status_t MessageQueue::postMessage( return NO_ERROR; } + /* when INVALIDATE_ON_VSYNC is set SF only processes * buffer updates on VSYNC and performs a refresh immediately * after. @@ -143,6 +154,10 @@ status_t MessageQueue::postMessage( */ #define INVALIDATE_ON_VSYNC 1 +void MessageQueue::invalidateTransactionNow() { + mHandler->dispatchTransaction(); +} + void MessageQueue::invalidate() { #if INVALIDATE_ON_VSYNC mEvents->requestNextVsync(); diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h index 710b2c2..b77e08e 100644 --- a/services/surfaceflinger/MessageQueue.h +++ b/services/surfaceflinger/MessageQueue.h @@ -62,8 +62,9 @@ private: class MessageQueue { class Handler : public MessageHandler { enum { - eventMaskInvalidate = 0x1, - eventMaskRefresh = 0x2 + eventMaskInvalidate = 0x1, + eventMaskRefresh = 0x2, + eventMaskTransaction = 0x4 }; MessageQueue& mQueue; int32_t mEventMask; @@ -72,6 +73,7 @@ class MessageQueue { virtual void handleMessage(const Message& message); void dispatchRefresh(); void dispatchInvalidate(); + void dispatchTransaction(); }; friend class Handler; @@ -89,8 +91,9 @@ class MessageQueue { public: enum { - INVALIDATE = 0, - REFRESH = 1, + INVALIDATE = 0, + REFRESH = 1, + TRANSACTION = 2 }; MessageQueue(); @@ -100,8 +103,13 @@ public: void waitMessage(); status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0); + + // sends INVALIDATE message at next VSYNC void invalidate(); + // sends REFRESH message at next VSYNC void refresh(); + // sends TRANSACTION message immediately + void invalidateTransactionNow(); }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 055bfe4..ef0d521 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -39,7 +39,8 @@ #include <gui/BufferQueue.h> #include <gui/GuiConfig.h> #include <gui/IDisplayEventConnection.h> -#include <gui/SurfaceTextureClient.h> +#include <gui/Surface.h> +#include <gui/GraphicBufferAlloc.h> #include <ui/GraphicBufferAllocator.h> #include <ui/PixelFormat.h> @@ -52,6 +53,7 @@ #include <utils/Trace.h> #include <private/android_filesystem_config.h> +#include <private/gui/SyncFeatures.h> #include "clz.h" #include "DdmConnection.h" @@ -61,18 +63,16 @@ #include "GLExtensions.h" #include "Layer.h" #include "LayerDim.h" -#include "LayerScreenshot.h" #include "SurfaceFlinger.h" #include "DisplayHardware/FramebufferSurface.h" -#include "DisplayHardware/GraphicBufferAlloc.h" #include "DisplayHardware/HWComposer.h" - - -#define EGL_VERSION_HW_ANDROID 0x3143 +#include "DisplayHardware/VirtualDisplaySurface.h" #define DISPLAY_COUNT 1 +EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); + namespace android { // --------------------------------------------------------------------------- @@ -93,6 +93,7 @@ SurfaceFlinger::SurfaceFlinger() mBootTime(systemTime()), mVisibleRegionsDirty(false), mHwWorkListDirty(false), + mAnimCompositionPending(false), mDebugRegion(0), mDebugDDMS(0), mDebugDisableHWC(0), @@ -108,6 +109,9 @@ SurfaceFlinger::SurfaceFlinger() // debugging stuff... char value[PROPERTY_VALUE_MAX]; + property_get("ro.bq.gpu_to_cpu_unsupported", value, "0"); + mGpuToCpuSupported = !atoi(value); + property_get("debug.sf.showupdates", value, "0"); mDebugRegion = atoi(value); @@ -488,6 +492,10 @@ status_t SurfaceFlinger::readyToRun() mEGLConfig = selectEGLConfig(mEGLDisplay, format); mEGLContext = createGLContext(mEGLDisplay, mEGLConfig); + // figure out which format we got + eglGetConfigAttrib(mEGLDisplay, mEGLConfig, + EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId); + LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT, "couldn't create EGLContext"); @@ -501,11 +509,10 @@ status_t SurfaceFlinger::readyToRun() createBuiltinDisplayLocked(type); wp<IBinder> token = mBuiltinDisplays[i]; - sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i); - sp<SurfaceTextureClient> stc = new SurfaceTextureClient( - static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue())); sp<DisplayDevice> hw = new DisplayDevice(this, - type, isSecure, token, stc, fbs, mEGLConfig); + type, allocateHwcDisplayId(type), isSecure, token, + new FramebufferSurface(*mHwc, i), + mEGLConfig); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests // for displays other than the main display, so we always @@ -571,44 +578,10 @@ uint32_t SurfaceFlinger::getMaxViewportDims() const { // ---------------------------------------------------------------------------- bool SurfaceFlinger::authenticateSurfaceTexture( - const sp<ISurfaceTexture>& surfaceTexture) const { + const sp<IGraphicBufferProducer>& bufferProducer) const { Mutex::Autolock _l(mStateLock); - sp<IBinder> surfaceTextureBinder(surfaceTexture->asBinder()); - - // Check the visible layer list for the ISurface - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); - sp<LayerBaseClient> lbc(layer->getLayerBaseClient()); - if (lbc != NULL) { - wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder(); - if (lbcBinder == surfaceTextureBinder) { - return true; - } - } - } - - // Check the layers in the purgatory. This check is here so that if a - // SurfaceTexture gets destroyed before all the clients are done using it, - // the error will not be reported as "surface XYZ is not authenticated", but - // will instead fail later on when the client tries to use the surface, - // which should be reported as "surface XYZ returned an -ENODEV". The - // purgatorized layers are no less authentic than the visible ones, so this - // should not cause any harm. - size_t purgatorySize = mLayerPurgatory.size(); - for (size_t i=0 ; i<purgatorySize ; i++) { - const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i)); - sp<LayerBaseClient> lbc(layer->getLayerBaseClient()); - if (lbc != NULL) { - wp<IBinder> lbcBinder = lbc->getSurfaceTextureBinder(); - if (lbcBinder == surfaceTextureBinder) { - return true; - } - } - } - - return false; + sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder()); + return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0; } status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) { @@ -771,6 +744,9 @@ void SurfaceFlinger::eventControl(int disp, int event, int enabled) { void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { + case MessageQueue::TRANSACTION: + handleMessageTransaction(); + break; case MessageQueue::INVALIDATE: handleMessageTransaction(); handleMessageInvalidate(); @@ -831,10 +807,10 @@ void SurfaceFlinger::doDebugFlashRegions() while (it != end) { const Rect& r = *it++; GLfloat vertices[][2] = { - { r.left, height - r.top }, - { r.left, height - r.bottom }, - { r.right, height - r.bottom }, - { r.right, height - r.top } + { (GLfloat) r.left, (GLfloat) (height - r.top) }, + { (GLfloat) r.left, (GLfloat) (height - r.bottom) }, + { (GLfloat) r.right, (GLfloat) (height - r.bottom) }, + { (GLfloat) r.right, (GLfloat) (height - r.top) } }; glVertexPointer(2, GL_FLOAT, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -880,6 +856,22 @@ void SurfaceFlinger::postComposition() for (size_t i=0 ; i<count ; i++) { currentLayers[i]->onPostComposition(); } + + if (mAnimCompositionPending) { + mAnimCompositionPending = false; + + const HWComposer& hwc = getHwComposer(); + sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY); + if (presentFence->isValid()) { + mAnimFrameTracker.setActualPresentFence(presentFence); + } else { + // The HWC doesn't support present fences, so use the refresh + // timestamp instead. + nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); + mAnimFrameTracker.setActualPresentTime(presentTime); + } + mAnimFrameTracker.advanceFrame(); + } } void SurfaceFlinger::rebuildLayerStacks() { @@ -893,7 +885,7 @@ void SurfaceFlinger::rebuildLayerStacks() { for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { Region opaqueRegion; Region dirtyRegion; - Vector< sp<LayerBase> > layersSortedByZ; + Vector< sp<Layer> > layersSortedByZ; const sp<DisplayDevice>& hw(mDisplays[dpy]); const Transform& tr(hw->getTransform()); const Rect bounds(hw->getBounds()); @@ -903,7 +895,7 @@ void SurfaceFlinger::rebuildLayerStacks() { const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); const Layer::State& s(layer->drawingState()); if (s.layerStack == hw->getLayerStack()) { Region drawRegion(tr.transform( @@ -933,14 +925,14 @@ void SurfaceFlinger::setUpHWComposer() { sp<const DisplayDevice> hw(mDisplays[dpy]); const int32_t id = hw->getHwcDisplayId(); if (id >= 0) { - const Vector< sp<LayerBase> >& currentLayers( + const Vector< sp<Layer> >& 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<count ; ++i, ++cur) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); layer->setGeometry(hw, *cur); if (mDebugDisableHWC || mDebugRegion) { cur->setSkip(true); @@ -956,7 +948,7 @@ void SurfaceFlinger::setUpHWComposer() { sp<const DisplayDevice> hw(mDisplays[dpy]); const int32_t id = hw->getHwcDisplayId(); if (id >= 0) { - const Vector< sp<LayerBase> >& currentLayers( + const Vector< sp<Layer> >& currentLayers( hw->getVisibleLayersSortedByZ()); const size_t count = currentLayers.size(); HWComposer::LayerListIterator cur = hwc.begin(id); @@ -966,7 +958,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<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); layer->setPerFrameData(hw, *cur); } } @@ -1020,7 +1012,7 @@ void SurfaceFlinger::postFramebuffer() for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { sp<const DisplayDevice> hw(mDisplays[dpy]); - const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ()); + const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ()); hw->onSwapBuffersCompleted(hwc); const size_t count = currentLayers.size(); int32_t id = hw->getHwcDisplayId(); @@ -1076,7 +1068,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (transactionFlags & eTraversalNeeded) { for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); if (!trFlags) continue; @@ -1113,11 +1105,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // Call makeCurrent() on the primary display so we can // be sure that nothing associated with this display // is current. - const sp<const DisplayDevice> hw(getDefaultDisplayDevice()); - DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext); + const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice()); + DisplayDevice::makeCurrent(mEGLDisplay, defaultDisplay, mEGLContext); + sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i))); + if (hw != NULL) + hw->disconnect(getHwComposer()); + if (draw[i].type < DisplayDevice::NUM_DISPLAY_TYPES) + mEventThread->onHotplugReceived(draw[i].type, false); mDisplays.removeItem(draw.keyAt(i)); - getHwComposer().disconnectDisplay(draw[i].type); - mEventThread->onHotplugReceived(draw[i].type, false); } else { ALOGW("trying to remove the main display"); } @@ -1130,6 +1125,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. + sp<DisplayDevice> hw(getDisplayDevice(display)); + if (hw != NULL) + hw->disconnect(getHwComposer()); mDisplays.removeItem(display); mDrawingState.displays.removeItemsAt(i); dc--; i--; @@ -1159,38 +1157,48 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (draw.indexOfKey(curr.keyAt(i)) < 0) { const DisplayDeviceState& state(curr[i]); - sp<FramebufferSurface> fbs; - sp<SurfaceTextureClient> stc; - if (!state.isVirtualDisplay()) { - + sp<DisplaySurface> dispSurface; + int32_t hwcDisplayId = -1; + if (state.isVirtualDisplay()) { + // Virtual displays without a surface are dormant: + // they have external state (layer stack, projection, + // etc.) but no internal state (i.e. a DisplayDevice). + if (state.surface != NULL) { + hwcDisplayId = allocateHwcDisplayId(state.type); + dispSurface = new VirtualDisplaySurface( + *mHwc, hwcDisplayId, state.surface, + state.displayName); + } + } else { ALOGE_IF(state.surface!=NULL, "adding a supported display, but rendering " "surface is provided (%p), ignoring it", state.surface.get()); - + hwcDisplayId = allocateHwcDisplayId(state.type); // for supported (by hwc) displays we provide our // own rendering surface - fbs = new FramebufferSurface(*mHwc, state.type); - stc = new SurfaceTextureClient( - static_cast< sp<ISurfaceTexture> >( - fbs->getBufferQueue())); - } else { - if (state.surface != NULL) { - stc = new SurfaceTextureClient(state.surface); - } + dispSurface = new FramebufferSurface(*mHwc, state.type); } const wp<IBinder>& display(curr.keyAt(i)); - if (stc != NULL) { + if (dispSurface != NULL) { sp<DisplayDevice> hw = new DisplayDevice(this, - state.type, state.isSecure, display, stc, fbs, - mEGLConfig); + state.type, hwcDisplayId, state.isSecure, + display, dispSurface, mEGLConfig); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); hw->setDisplayName(state.displayName); mDisplays.add(display, hw); - mEventThread->onHotplugReceived(state.type, true); + if (state.isVirtualDisplay()) { + if (hwcDisplayId >= 0) { + mHwc->setVirtualDisplayProperties(hwcDisplayId, + hw->getWidth(), hw->getHeight(), + hw->getFormat()); + } + } else { + mEventThread->onHotplugReceived(state.type, true); + } } } } @@ -1223,8 +1231,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>& layerBase(currentLayers[i]); - uint32_t layerStack = layerBase->drawingState().layerStack; + const sp<Layer>& layer(currentLayers[i]); + uint32_t layerStack = layer->drawingState().layerStack; if (i==0 || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored @@ -1237,17 +1245,22 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (disp == NULL) { disp = hw; } else { - disp = getDefaultDisplayDevice(); + disp = NULL; break; } } } } - if (disp != NULL) { - // presumably this means this layer is using a layerStack - // that is not visible on any display - layerBase->updateTransformHint(disp); + if (disp == NULL) { + // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to + // redraw after transform hint changes. See bug 8508397. + + // could be null when this layer is using a layerStack + // that is not visible on any display. Also can occur at + // screen off/on times. + disp = getDefaultDisplayDevice(); } + layer->updateTransformHint(disp); } } @@ -1269,7 +1282,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) mVisibleRegionsDirty = true; const size_t count = previousLayers.size(); for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(previousLayers[i]); + const sp<Layer>& 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 @@ -1296,6 +1309,10 @@ void SurfaceFlinger::commitTransaction() mLayersPendingRemoval.clear(); } + // If this transaction is part of a window animation then the next frame + // we composite should be considered an animation as well. + mAnimCompositionPending = mAnimTransactionPending; + mDrawingState = mCurrentState; mTransactionPending = false; mAnimTransactionPending = false; @@ -1316,12 +1333,12 @@ void SurfaceFlinger::computeVisibleRegions( size_t i = currentLayers.size(); while (i--) { - const sp<LayerBase>& layer = currentLayers[i]; + const sp<Layer>& layer = currentLayers[i]; // start with the whole surface at its current location const Layer::State& s(layer->drawingState()); - // only consider the layers on the given later stack + // only consider the layers on the given layer stack if (s.layerStack != layerStack) continue; @@ -1358,7 +1375,7 @@ void SurfaceFlinger::computeVisibleRegions( // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(); - Rect bounds(layer->computeBounds()); + Rect bounds(s.transform.transform(layer->computeBounds())); visibleRegion.set(bounds); if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region @@ -1367,14 +1384,14 @@ void SurfaceFlinger::computeVisibleRegions( if (tr.transformed()) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.transparentRegion); + transparentRegion = tr.transform(s.activeTransparentRegion); } else { // transformation too complex, can't do the // transparent region optimization. transparentRegion.clear(); } } else { - transparentRegion = s.transparentRegion; + transparentRegion = s.activeTransparentRegion; } } @@ -1459,7 +1476,7 @@ void SurfaceFlinger::handlePageFlip() const LayerVector& currentLayers(mDrawingState.layersSortedByZ); const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); const Region dirty(layer->latchBuffer(visibleRegions)); const Layer::State& s(layer->drawingState()); invalidateLayerStack(s.layerStack, dirty); @@ -1541,7 +1558,20 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); } else { - const Region region(hw->undefinedRegion.intersect(dirty)); + // we start with the whole screen area + const Region bounds(hw->getBounds()); + + // we remove the scissor part + // we're left with the letterbox region + // (common case is that letterbox ends-up being empty) + const Region letterbox(bounds.subtract(hw->getScissor())); + + // compute the area to clear + Region region(hw->undefinedRegion.merge(letterbox)); + + // but limit it to the dirty region + region.andSelf(dirty); + // screen is already cleared here if (!region.isEmpty()) { // can happen with SurfaceView @@ -1549,13 +1579,12 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const } } - if (hw->getDisplayType() >= DisplayDevice::DISPLAY_EXTERNAL) { - // TODO: just to be on the safe side, we don't set the + if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) { + // just to be on the safe side, we don't set the // scissor on the main display. It should never be needed // anyways (though in theory it could since the API allows it). const Rect& bounds(hw->getBounds()); - const Transform& tr(hw->getTransform()); - const Rect scissor(tr.transform(hw->getViewport())); + const Rect& scissor(hw->getScissor()); if (scissor != bounds) { // scissor doesn't match the screen's dimensions, so we // need to clear everything outside of it and enable @@ -1563,9 +1592,6 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const const GLint height = hw->getHeight(); glScissor(scissor.left, height - scissor.bottom, scissor.getWidth(), scissor.getHeight()); - // clear everything unscissored - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); // enable scissor for this frame glEnable(GL_SCISSOR_TEST); } @@ -1576,13 +1602,13 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const * and then, render the layers targeted at the framebuffer */ - const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ()); + const Vector< sp<Layer> >& 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<count && cur!=end ; ++i, ++cur) { - const sp<LayerBase>& layer(layers[i]); + const sp<Layer>& layer(layers[i]); const Region clip(dirty.intersect(tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { switch (cur->getCompositionType()) { @@ -1614,7 +1640,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const } else { // we're not using h/w composer for (size_t i=0 ; i<count ; ++i) { - const sp<LayerBase>& layer(layers[i]); + const sp<Layer>& layer(layers[i]); const Region clip(dirty.intersect( tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) { @@ -1641,66 +1667,43 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, while (it != end) { const Rect& r = *it++; GLfloat vertices[][2] = { - { r.left, height - r.top }, - { r.left, height - r.bottom }, - { r.right, height - r.bottom }, - { r.right, height - r.top } + { (GLfloat) r.left, (GLfloat) (height - r.top) }, + { (GLfloat) r.left, (GLfloat) (height - r.bottom) }, + { (GLfloat) r.right, (GLfloat) (height - r.bottom) }, + { (GLfloat) r.right, (GLfloat) (height - r.top) } }; glVertexPointer(2, GL_FLOAT, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } } -ssize_t SurfaceFlinger::addClientLayer(const sp<Client>& client, - const sp<LayerBaseClient>& lbc) +void SurfaceFlinger::addClientLayer(const sp<Client>& client, + const sp<IBinder>& handle, + const sp<IGraphicBufferProducer>& gbc, + const sp<Layer>& lbc) { // attach this layer to the client - size_t name = client->attachLayer(lbc); + client->attachLayer(handle, lbc); // add this layer to the current state list Mutex::Autolock _l(mStateLock); mCurrentState.layersSortedByZ.add(lbc); - - return ssize_t(name); + mGraphicBufferProducerList.add(gbc->asBinder()); } -status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer) +status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { Mutex::Autolock _l(mStateLock); - status_t err = purgatorizeLayer_l(layer); - if (err == NO_ERROR) - setTransactionFlags(eTransactionNeeded); - return err; -} - -status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase) -{ - ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase); + ssize_t index = mCurrentState.layersSortedByZ.remove(layer); if (index >= 0) { + mLayersPendingRemoval.push(layer); mLayersRemoved = true; + setTransactionFlags(eTransactionNeeded); return NO_ERROR; } return status_t(index); } -status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase) -{ - // 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); - if (err >= 0) { - mLayerPurgatory.add(layerBase); - } - - mLayersPendingRemoval.push(layerBase); - - // it's possible that we don't find a layer, because it might - // have been destroyed already -- this is not technically an error - // from the user because there is a race between Client::destroySurface(), - // ~Client() and ~ISurface(). - return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err; -} - uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags) { return android_atomic_release_load(&mTransactionFlags); @@ -1843,7 +1846,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( const layer_state_t& s) { uint32_t flags = 0; - sp<LayerBaseClient> layer(client->getLayerUser(s.surface)); + sp<Layer> layer(client->getLayerUser(s.surface)); if (layer != 0) { const uint32_t what = s.what; if (what & layer_state_t::ePositionChanged) { @@ -1901,55 +1904,49 @@ uint32_t SurfaceFlinger::setClientStateLocked( return flags; } -sp<ISurface> SurfaceFlinger::createLayer( - ISurfaceComposerClient::surface_data_t* params, +status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, - uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { - sp<LayerBaseClient> layer; - sp<ISurface> surfaceHandle; - + //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string()); if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); - return surfaceHandle; + return BAD_VALUE; } - //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string()); + status_t result = NO_ERROR; + + sp<Layer> layer; + switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: - layer = createNormalLayer(client, w, h, flags, format); + result = createNormalLayer(client, + name, w, h, flags, format, + handle, gbp, &layer); break; - case ISurfaceComposerClient::eFXSurfaceBlur: case ISurfaceComposerClient::eFXSurfaceDim: - layer = createDimLayer(client, w, h, flags); + result = createDimLayer(client, + name, w, h, flags, + handle, gbp, &layer); break; - case ISurfaceComposerClient::eFXSurfaceScreenshot: - layer = createScreenshotLayer(client, w, h, flags); + default: + result = BAD_VALUE; break; } - if (layer != 0) { - layer->initStates(w, h, flags); - layer->setName(name); - ssize_t token = addClientLayer(client, layer); - surfaceHandle = layer->getSurface(); - if (surfaceHandle != 0) { - params->token = token; - params->identity = layer->getIdentity(); - } + if (result == NO_ERROR) { + addClientLayer(client, *handle, *gbp, layer); setTransactionFlags(eTransactionNeeded); } - - return surfaceHandle; + return result; } -sp<Layer> SurfaceFlinger::createNormalLayer( - const sp<Client>& client, - uint32_t w, uint32_t h, uint32_t flags, - PixelFormat& format) +status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { // initialize the surfaces switch (format) { @@ -1971,71 +1968,48 @@ sp<Layer> SurfaceFlinger::createNormalLayer( format = PIXEL_FORMAT_RGBA_8888; #endif - sp<Layer> layer = new Layer(this, client); - status_t err = layer->setBuffers(w, h, format, flags); - if (CC_LIKELY(err != NO_ERROR)) { - ALOGE("createNormalLayer() failed (%s)", strerror(-err)); - layer.clear(); + *outLayer = new Layer(this, client, name, w, h, flags); + status_t err = (*outLayer)->setBuffers(w, h, format, flags); + if (err == NO_ERROR) { + *handle = (*outLayer)->getHandle(); + *gbp = (*outLayer)->getBufferQueue(); } - return layer; -} -sp<LayerDim> SurfaceFlinger::createDimLayer( - const sp<Client>& client, - uint32_t w, uint32_t h, uint32_t flags) -{ - sp<LayerDim> layer = new LayerDim(this, client); - return layer; + ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); + return err; } -sp<LayerScreenshot> SurfaceFlinger::createScreenshotLayer( - const sp<Client>& client, - uint32_t w, uint32_t h, uint32_t flags) +status_t SurfaceFlinger::createDimLayer(const sp<Client>& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags, + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { - sp<LayerScreenshot> layer = new LayerScreenshot(this, client); - return layer; + *outLayer = new LayerDim(this, client, name, w, h, flags); + *handle = (*outLayer)->getHandle(); + *gbp = (*outLayer)->getBufferQueue(); + return NO_ERROR; } -status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, SurfaceID sid) +status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle) { - /* - * called by the window manager, when a surface should be marked for - * destruction. - * - * The surface is removed from the current and drawing lists, but placed - * in the purgatory queue, so it's not destroyed right-away (we need - * to wait for all client's references to go away first). - */ - - status_t err = NAME_NOT_FOUND; - Mutex::Autolock _l(mStateLock); - sp<LayerBaseClient> layer = client->getLayerUser(sid); - - if (layer != 0) { - err = purgatorizeLayer_l(layer); - if (err == NO_ERROR) { - setTransactionFlags(eTransactionNeeded); - } + // called by the window manager when it wants to remove a Layer + status_t err = NO_ERROR; + sp<Layer> l(client->getLayerUser(handle)); + if (l != NULL) { + err = removeLayer(l); + ALOGE_IF(err<0 && err != NAME_NOT_FOUND, + "error removing layer=%p (%s)", l.get(), strerror(-err)); } return err; } -status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer) +status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer) { - // called by ~ISurface() when all references are gone + // called by ~LayerCleaner() when all references to the IBinder (handle) + // are gone status_t err = NO_ERROR; - sp<LayerBaseClient> l(layer.promote()); + sp<Layer> l(layer.promote()); if (l != NULL) { - Mutex::Autolock _l(mStateLock); - err = removeLayer_l(l); - if (err == NAME_NOT_FOUND) { - // The surface wasn't in the current list, which means it was - // removed already, which means it is in the purgatory, - // and need to be removed from there. - ssize_t idx = mLayerPurgatory.remove(l); - ALOGE_IF(idx < 0, - "layer=%p is not in the purgatory list", l.get()); - } + err = removeLayer(l); ALOGE_IF(err<0 && err != NAME_NOT_FOUND, "error removing layer=%p (%s)", l.get(), strerror(-err)); } @@ -2045,12 +2019,14 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<LayerBaseClient>& layer) // --------------------------------------------------------------------------- void SurfaceFlinger::onInitializeDisplays() { - // reset screen orientation + // reset screen orientation and use primary layer stack Vector<ComposerState> state; Vector<DisplayState> displays; DisplayState d; - d.what = DisplayState::eDisplayProjectionChanged; + d.what = DisplayState::eDisplayProjectionChanged | + DisplayState::eLayerStackChanged; d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]; + d.layerStack = 0; d.orientation = DisplayState::eOrientationDefault; d.frame.makeInvalid(); d.viewport.makeInvalid(); @@ -2173,11 +2149,14 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) char buffer[SIZE]; String8 result; - if (!PermissionCache::checkCallingPermission(sDump)) { + + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + if ((uid != AID_SHELL) && + !PermissionCache::checkPermission(sDump, pid, uid)) { snprintf(buffer, SIZE, "Permission Denial: " - "can't dump SurfaceFlinger from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); + "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid); result.append(buffer); } else { // Try to get the main lock, but don't insist if we can't @@ -2239,7 +2218,7 @@ void SurfaceFlinger::listLayersLocked(const Vector<String16>& args, size_t& inde const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); snprintf(buffer, SIZE, "%s\n", layer->getName().string()); result.append(buffer); } @@ -2254,22 +2233,26 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index index++; } - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); - if (name.isEmpty()) { - snprintf(buffer, SIZE, "%s\n", layer->getName().string()); - result.append(buffer); - } - if (name.isEmpty() || (name == layer->getName())) { - layer->dumpStats(result, buffer, SIZE); + const nsecs_t period = + getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); + result.appendFormat("%lld\n", period); + + if (name.isEmpty()) { + mAnimFrameTracker.dump(result); + } else { + const LayerVector& currentLayers = mCurrentState.layersSortedByZ; + const size_t count = currentLayers.size(); + for (size_t i=0 ; i<count ; i++) { + const sp<Layer>& layer(currentLayers[i]); + if (name == layer->getName()) { + layer->dumpStats(result, buffer, SIZE); + } } } } void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index, - String8& result, char* buffer, size_t SIZE) const + String8& result, char* buffer, size_t SIZE) { String8 name; if (index < args.size()) { @@ -2280,11 +2263,13 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde const LayerVector& currentLayers = mCurrentState.layersSortedByZ; const size_t count = currentLayers.size(); for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); if (name.isEmpty() || (name == layer->getName())) { layer->clearStats(); } } + + mAnimFrameTracker.clear(); } /*static*/ void SurfaceFlinger::appendSfConfigString(String8& result) @@ -2326,6 +2311,10 @@ void SurfaceFlinger::dumpAllLocked( appendGuiConfigString(result); result.append("\n"); + result.append("Sync configuration: "); + result.append(SyncFeatures::getInstance().toString()); + result.append("\n"); + /* * Dump the visible layer list */ @@ -2334,23 +2323,11 @@ void SurfaceFlinger::dumpAllLocked( snprintf(buffer, SIZE, "Visible layers (count = %d)\n", count); result.append(buffer); for (size_t i=0 ; i<count ; i++) { - const sp<LayerBase>& layer(currentLayers[i]); + const sp<Layer>& layer(currentLayers[i]); layer->dump(result, buffer, SIZE); } /* - * Dump the layers in the purgatory - */ - - const size_t purgatorySize = mLayerPurgatory.size(); - snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize); - result.append(buffer); - for (size_t i=0 ; i<purgatorySize ; i++) { - const sp<LayerBase>& layer(mLayerPurgatory.itemAt(i)); - layer->shortDump(result, buffer, SIZE); - } - - /* * Dump Display state */ @@ -2371,17 +2348,20 @@ void SurfaceFlinger::dumpAllLocked( HWComposer& hwc(getHwComposer()); sp<const DisplayDevice> hw(getDefaultDisplayDevice()); const GLExtensions& extensions(GLExtensions::getInstance()); + + snprintf(buffer, SIZE, "EGL implementation : %s\n", + eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION)); + result.append(buffer); + snprintf(buffer, SIZE, "%s\n", + eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS)); + result.append(buffer); + snprintf(buffer, SIZE, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(), extensions.getVersion()); result.append(buffer); - - snprintf(buffer, SIZE, "EGL : %s\n", - eglQueryString(mEGLDisplay, EGL_VERSION_HW_ANDROID)); - result.append(buffer); - - snprintf(buffer, SIZE, "EXTS: %s\n", extensions.getExtension()); + snprintf(buffer, SIZE, "%s\n", extensions.getExtension()); result.append(buffer); hw->undefinedRegion.dump(result, "undefinedRegion"); @@ -2395,13 +2375,18 @@ void SurfaceFlinger::dumpAllLocked( " transaction-flags : %08x\n" " refresh-rate : %f fps\n" " x-dpi : %f\n" - " y-dpi : %f\n", + " y-dpi : %f\n" + " EGL_NATIVE_VISUAL_ID : %d\n" + " gpu_to_cpu_unsupported : %d\n" + , mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0, mTransactionFlags, 1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY), hwc.getDpiX(HWC_DISPLAY_PRIMARY), - hwc.getDpiY(HWC_DISPLAY_PRIMARY)); + hwc.getDpiY(HWC_DISPLAY_PRIMARY), + mEGLNativeVisualId, + !mGpuToCpuSupported); result.append(buffer); snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n", @@ -2435,10 +2420,22 @@ void SurfaceFlinger::dumpAllLocked( alloc.dump(result); } -const Vector< sp<LayerBase> >& -SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) { +const Vector< sp<Layer> >& +SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) { // Note: mStateLock is held here - return getDisplayDevice( getBuiltInDisplay(disp) )->getVisibleLayersSortedByZ(); + wp<IBinder> dpy; + for (size_t i=0 ; i<mDisplays.size() ; i++) { + if (mDisplays.valueAt(i)->getHwcDisplayId() == id) { + dpy = mDisplays.keyAt(i); + break; + } + } + if (dpy == NULL) { + ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id); + // Just use the primary display so we have something to return + dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY); + } + return getDisplayDevice(dpy)->getVisibleLayersSortedByZ(); } bool SurfaceFlinger::startDdmConnection() @@ -2464,6 +2461,7 @@ status_t SurfaceFlinger::onTransact( { switch (code) { case CREATE_CONNECTION: + case CREATE_DISPLAY: case SET_TRANSACTION_STATE: case BOOT_FINISHED: case BLANK: @@ -2570,101 +2568,320 @@ void SurfaceFlinger::repaintEverything() { } // --------------------------------------------------------------------------- +// Capture screen into an IGraphiBufferProducer +// --------------------------------------------------------------------------- -status_t SurfaceFlinger::renderScreenToTexture(uint32_t layerStack, - GLuint* textureName, GLfloat* uOut, GLfloat* vOut) -{ - Mutex::Autolock _l(mStateLock); - return renderScreenToTextureLocked(layerStack, textureName, uOut, vOut); +/* The code below is here to handle b/8734824 + * + * We create a IGraphicBufferProducer wrapper that forwards all calls + * to the calling binder thread, where they are executed. This allows + * the calling thread to be reused (on the other side) and not + * depend on having "enough" binder threads to handle the requests. + * + */ + +class GraphicProducerWrapper : public BBinder, public MessageHandler { + sp<IGraphicBufferProducer> impl; + sp<Looper> looper; + status_t result; + bool exitPending; + bool exitRequested; + mutable Barrier barrier; + volatile int32_t memoryBarrier; + uint32_t code; + Parcel const* data; + Parcel* reply; + + enum { + MSG_API_CALL, + MSG_EXIT + }; + + /* + * this is called by our "fake" BpGraphicBufferProducer. We package the + * data and reply Parcel and forward them to the calling thread. + */ + virtual status_t transact(uint32_t code, + const Parcel& data, Parcel* reply, uint32_t flags) { + this->code = code; + this->data = &data; + this->reply = reply; + android_atomic_acquire_store(0, &memoryBarrier); + if (exitPending) { + // if we've exited, we run the message synchronously right here + handleMessage(Message(MSG_API_CALL)); + } else { + barrier.close(); + looper->sendMessage(this, Message(MSG_API_CALL)); + barrier.wait(); + } + return NO_ERROR; + } + + /* + * here we run on the binder calling thread. All we've got to do is + * call the real BpGraphicBufferProducer. + */ + virtual void handleMessage(const Message& message) { + android_atomic_release_load(&memoryBarrier); + if (message.what == MSG_API_CALL) { + impl->asBinder()->transact(code, data[0], reply); + barrier.open(); + } else if (message.what == MSG_EXIT) { + exitRequested = true; + } + } + +public: + GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl) : + impl(impl), looper(new Looper(true)), result(NO_ERROR), + exitPending(false), exitRequested(false) { + } + + status_t waitForResponse() { + do { + looper->pollOnce(-1); + } while (!exitRequested); + return result; + } + + void exit(status_t result) { + exitPending = true; + looper->sendMessage(this, Message(MSG_EXIT)); + } +}; + +status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ, + bool isCpuConsumer) { + + if (CC_UNLIKELY(display == 0)) + return BAD_VALUE; + + if (CC_UNLIKELY(producer == 0)) + return BAD_VALUE; + + + class MessageCaptureScreen : public MessageBase { + SurfaceFlinger* flinger; + sp<IBinder> display; + sp<IGraphicBufferProducer> producer; + uint32_t reqWidth, reqHeight; + uint32_t minLayerZ,maxLayerZ; + bool useReadPixels; + status_t result; + public: + MessageCaptureScreen(SurfaceFlinger* flinger, + const sp<IBinder>& display, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ, bool useReadPixels) + : flinger(flinger), display(display), producer(producer), + reqWidth(reqWidth), reqHeight(reqHeight), + minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), + useReadPixels(useReadPixels), + result(PERMISSION_DENIED) + { + } + status_t getResult() const { + return result; + } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + sp<const DisplayDevice> hw(flinger->getDisplayDevice(display)); + if (!useReadPixels) { + result = flinger->captureScreenImplLocked(hw, + producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); + } else { + result = flinger->captureScreenImplCpuConsumerLocked(hw, + producer, reqWidth, reqHeight, minLayerZ, maxLayerZ); + } + static_cast<GraphicProducerWrapper*>(producer->asBinder().get())->exit(result); + return true; + } + }; + + // make sure to process transactions before screenshots -- a transaction + // might already be pending but scheduled for VSYNC; this guarantees we + // will handle it before the screenshot. When VSYNC finally arrives + // the scheduled transaction will be a no-op. If no transactions are + // scheduled at this time, this will end-up being a no-op as well. + mEventQueue.invalidateTransactionNow(); + + bool useReadPixels = false; + if (isCpuConsumer) { + bool formatSupportedBytBitmap = + (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBA_8888) || + (mEGLNativeVisualId == HAL_PIXEL_FORMAT_RGBX_8888); + if (formatSupportedBytBitmap == false) { + // the pixel format we have is not compatible with + // Bitmap.java, which is the likely client of this API, + // so we just revert to glReadPixels() in that case. + useReadPixels = true; + } + if (mGpuToCpuSupported == false) { + // When we know the GL->CPU path works, we can call + // captureScreenImplLocked() directly, instead of using the + // glReadPixels() workaround. + useReadPixels = true; + } + } + + // this creates a "fake" BBinder which will serve as a "fake" remote + // binder to receive the marshaled calls and forward them to the + // real remote (a BpGraphicBufferProducer) + sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer); + + // the asInterface() call below creates our "fake" BpGraphicBufferProducer + // which does the marshaling work forwards to our "fake remote" above. + sp<MessageBase> msg = new MessageCaptureScreen(this, + display, IGraphicBufferProducer::asInterface( wrapper ), + reqWidth, reqHeight, minLayerZ, maxLayerZ, + useReadPixels); + + status_t res = postMessageAsync(msg); + if (res == NO_ERROR) { + res = wrapper->waitForResponse(); + } + return res; } -status_t SurfaceFlinger::renderScreenToTextureLocked(uint32_t layerStack, - GLuint* textureName, GLfloat* uOut, GLfloat* vOut) + +void SurfaceFlinger::renderScreenImplLocked( + const sp<const DisplayDevice>& hw, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ, + bool yswap) { ATRACE_CALL(); - if (!GLExtensions::getInstance().haveFramebufferObject()) - return INVALID_OPERATION; - // get screen geometry - // FIXME: figure out what it means to have a screenshot texture w/ multi-display - sp<const DisplayDevice> hw(getDefaultDisplayDevice()); const uint32_t hw_w = hw->getWidth(); const uint32_t hw_h = hw->getHeight(); - GLfloat u = 1; - GLfloat v = 1; + + const bool filtering = reqWidth != hw_w || reqWidth != hw_h; // make sure to clear all GL error flags while ( glGetError() != GL_NO_ERROR ) ; - // create a FBO - GLuint name, tname; - glGenTextures(1, &tname); - glBindTexture(GL_TEXTURE_2D, tname); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - if (glGetError() != GL_NO_ERROR) { - while ( glGetError() != GL_NO_ERROR ) ; - GLint tw = (2 << (31 - clz(hw_w))); - GLint th = (2 << (31 - clz(hw_h))); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); - u = GLfloat(hw_w) / tw; - v = GLfloat(hw_h) / th; - } - glGenFramebuffersOES(1, &name); - glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); - glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, - GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0); - - DisplayDevice::setViewportAndProjection(hw); + // set-up our viewport + glViewport(0, 0, reqWidth, reqHeight); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (yswap) glOrthof(0, hw_w, hw_h, 0, 0, 1); + else glOrthof(0, hw_w, 0, hw_h, 0, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); // redraw the screen entirely... - glDisable(GL_TEXTURE_EXTERNAL_OES); - glDisable(GL_TEXTURE_2D); + glDisable(GL_SCISSOR_TEST); glClearColor(0,0,0,1); glClear(GL_COLOR_BUFFER_BIT); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ()); + glDisable(GL_TEXTURE_EXTERNAL_OES); + glDisable(GL_TEXTURE_2D); + + const LayerVector& layers( mDrawingState.layersSortedByZ ); const size_t count = layers.size(); for (size_t i=0 ; i<count ; ++i) { - const sp<LayerBase>& layer(layers[i]); - layer->draw(hw); + const sp<Layer>& layer(layers[i]); + const Layer::State& state(layer->drawingState()); + if (state.layerStack == hw->getLayerStack()) { + if (state.z >= minLayerZ && state.z <= maxLayerZ) { + if (layer->isVisible()) { + if (filtering) layer->setFiltering(true); + layer->draw(hw); + if (filtering) layer->setFiltering(false); + } + } + } } + // compositionComplete is needed for older driver hw->compositionComplete(); +} - // back to main framebuffer - glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); - glDeleteFramebuffersOES(1, &name); - *textureName = tname; - *uOut = u; - *vOut = v; +status_t SurfaceFlinger::captureScreenImplLocked( + const sp<const DisplayDevice>& hw, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ) +{ + ATRACE_CALL(); + + // get screen geometry + const uint32_t hw_w = hw->getWidth(); + const uint32_t hw_h = hw->getHeight(); + + // if we have secure windows on this display, never allow the screen capture + if (hw->getSecureLayerVisible()) { + ALOGW("FB is protected: PERMISSION_DENIED"); + return PERMISSION_DENIED; + } + + if ((reqWidth > hw_w) || (reqHeight > hw_h)) { + ALOGE("size mismatch (%d, %d) > (%d, %d)", + reqWidth, reqHeight, hw_w, hw_h); + return BAD_VALUE; + } + + reqWidth = (!reqWidth) ? hw_w : reqWidth; + reqHeight = (!reqHeight) ? hw_h : reqHeight; + + // Create a surface to render into + sp<Surface> surface = new Surface(producer); + ANativeWindow* const window = surface.get(); + + // set the buffer size to what the user requested + native_window_set_buffers_user_dimensions(window, reqWidth, reqHeight); + + // and create the corresponding EGLSurface + EGLSurface eglSurface = eglCreateWindowSurface( + mEGLDisplay, mEGLConfig, window, NULL); + if (eglSurface == EGL_NO_SURFACE) { + ALOGE("captureScreenImplLocked: eglCreateWindowSurface() failed 0x%4x", + eglGetError()); + return BAD_VALUE; + } + + if (!eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext)) { + ALOGE("captureScreenImplLocked: eglMakeCurrent() failed 0x%4x", + eglGetError()); + eglDestroySurface(mEGLDisplay, eglSurface); + return BAD_VALUE; + } + + renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, false); + + // and finishing things up... + if (eglSwapBuffers(mEGLDisplay, eglSurface) != EGL_TRUE) { + ALOGE("captureScreenImplLocked: eglSwapBuffers() failed 0x%4x", + eglGetError()); + eglDestroySurface(mEGLDisplay, eglSurface); + return BAD_VALUE; + } + + eglDestroySurface(mEGLDisplay, eglSurface); + return NO_ERROR; } -// --------------------------------------------------------------------------- -status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display, - sp<IMemoryHeap>* heap, - uint32_t* w, uint32_t* h, PixelFormat* f, - uint32_t sw, uint32_t sh, +status_t SurfaceFlinger::captureScreenImplCpuConsumerLocked( + const sp<const DisplayDevice>& hw, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, uint32_t maxLayerZ) { ATRACE_CALL(); - status_t result = PERMISSION_DENIED; - if (!GLExtensions::getInstance().haveFramebufferObject()) { return INVALID_OPERATION; } // get screen geometry - sp<const DisplayDevice> hw(getDisplayDevice(display)); const uint32_t hw_w = hw->getWidth(); const uint32_t hw_h = hw->getHeight(); @@ -2674,28 +2891,22 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display, return PERMISSION_DENIED; } - if ((sw > hw_w) || (sh > hw_h)) { - ALOGE("size mismatch (%d, %d) > (%d, %d)", sw, sh, hw_w, hw_h); + if ((reqWidth > hw_w) || (reqHeight > hw_h)) { + ALOGE("size mismatch (%d, %d) > (%d, %d)", + reqWidth, reqHeight, hw_w, hw_h); return BAD_VALUE; } - sw = (!sw) ? hw_w : sw; - sh = (!sh) ? hw_h : sh; - const size_t size = sw * sh * 4; - const bool filtering = sw != hw_w || sh != hw_h; - -// ALOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d", -// sw, sh, minLayerZ, maxLayerZ); + reqWidth = (!reqWidth) ? hw_w : reqWidth; + reqHeight = (!reqHeight) ? hw_h : reqHeight; - // make sure to clear all GL error flags - while ( glGetError() != GL_NO_ERROR ) ; - - // create a FBO - GLuint name, tname; + GLuint tname; glGenRenderbuffersOES(1, &tname); glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname); - glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh); + glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, reqWidth, reqHeight); + // create a FBO + GLuint name; glGenFramebuffersOES(1, &name); glBindFramebufferOES(GL_FRAMEBUFFER_OES, name); glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, @@ -2703,150 +2914,73 @@ status_t SurfaceFlinger::captureScreenImplLocked(const sp<IBinder>& display, GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); + status_t result = NO_ERROR; if (status == GL_FRAMEBUFFER_COMPLETE_OES) { - // invert everything, b/c glReadPixel() below will invert the FB - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - glViewport(0, 0, sw, sh); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrthof(0, hw_w, hw_h, 0, 0, 1); - glMatrixMode(GL_MODELVIEW); - - // redraw the screen entirely... - glClearColor(0,0,0,1); - glClear(GL_COLOR_BUFFER_BIT); - - const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ()); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; ++i) { - const sp<LayerBase>& layer(layers[i]); - const uint32_t z = layer->drawingState().z; - if (z >= minLayerZ && z <= maxLayerZ) { - if (filtering) layer->setFiltering(true); - layer->draw(hw); - if (filtering) layer->setFiltering(false); - } - } - - // check for errors and return screen capture - if (glGetError() != GL_NO_ERROR) { - // error while rendering - result = INVALID_OPERATION; - } else { - // allocate shared memory large enough to hold the - // screen capture - sp<MemoryHeapBase> base( - new MemoryHeapBase(size, 0, "screen-capture") ); - void* const ptr = base->getBase(); - if (ptr != MAP_FAILED) { - // capture the screen with glReadPixels() - ScopedTrace _t(ATRACE_TAG, "glReadPixels"); - glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr); - if (glGetError() == GL_NO_ERROR) { - *heap = base; - *w = sw; - *h = sh; - *f = PIXEL_FORMAT_RGBA_8888; - result = NO_ERROR; + renderScreenImplLocked(hw, reqWidth, reqHeight, minLayerZ, maxLayerZ, true); + + // Below we render the screenshot into the + // CpuConsumer using glReadPixels from our FBO. + // Some older drivers don't support the GL->CPU path so we + // have to wrap it with a CPU->CPU path, which is what + // glReadPixels essentially is. + + sp<Surface> sur = new Surface(producer); + ANativeWindow* window = sur.get(); + + if (native_window_api_connect(window, NATIVE_WINDOW_API_CPU) == NO_ERROR) { + int err = 0; + err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight); + err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); + err |= native_window_set_usage(window, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + + if (err == NO_ERROR) { + ANativeWindowBuffer* buffer; + if (native_window_dequeue_buffer_and_wait(window, &buffer) == NO_ERROR) { + sp<GraphicBuffer> buf = static_cast<GraphicBuffer*>(buffer); + void* vaddr; + if (buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &vaddr) == NO_ERROR) { + glReadPixels(0, 0, buffer->stride, reqHeight, + GL_RGBA, GL_UNSIGNED_BYTE, vaddr); + buf->unlock(); + } + window->queueBuffer(window, buffer, -1); } - } else { - result = NO_MEMORY; } + native_window_api_disconnect(window, NATIVE_WINDOW_API_CPU); } - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + } else { - result = BAD_VALUE; + ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES while taking screenshot"); + result = INVALID_OPERATION; } - // release FBO resources + // back to main framebuffer glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); glDeleteRenderbuffersOES(1, &tname); glDeleteFramebuffersOES(1, &name); - hw->compositionComplete(); - -// ALOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK"); + DisplayDevice::setViewportAndProjection(hw); return result; } - -status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, - sp<IMemoryHeap>* heap, - uint32_t* width, uint32_t* height, PixelFormat* format, - uint32_t sw, uint32_t sh, - uint32_t minLayerZ, uint32_t maxLayerZ) -{ - if (CC_UNLIKELY(display == 0)) - return BAD_VALUE; - - if (!GLExtensions::getInstance().haveFramebufferObject()) - return INVALID_OPERATION; - - class MessageCaptureScreen : public MessageBase { - SurfaceFlinger* flinger; - sp<IBinder> display; - sp<IMemoryHeap>* heap; - uint32_t* w; - uint32_t* h; - PixelFormat* f; - uint32_t sw; - uint32_t sh; - uint32_t minLayerZ; - uint32_t maxLayerZ; - status_t result; - public: - MessageCaptureScreen(SurfaceFlinger* flinger, const sp<IBinder>& display, - sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f, - uint32_t sw, uint32_t sh, - uint32_t minLayerZ, uint32_t maxLayerZ) - : flinger(flinger), display(display), - heap(heap), w(w), h(h), f(f), sw(sw), sh(sh), - minLayerZ(minLayerZ), maxLayerZ(maxLayerZ), - result(PERMISSION_DENIED) - { - } - status_t getResult() const { - return result; - } - virtual bool handler() { - Mutex::Autolock _l(flinger->mStateLock); - result = flinger->captureScreenImplLocked(display, - heap, w, h, f, sw, sh, minLayerZ, maxLayerZ); - return true; - } - }; - - sp<MessageBase> msg = new MessageCaptureScreen(this, - display, heap, width, height, format, sw, sh, minLayerZ, maxLayerZ); - status_t res = postMessageSync(msg); - if (res == NO_ERROR) { - res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult(); - } - return res; -} - // --------------------------------------------------------------------------- SurfaceFlinger::LayerVector::LayerVector() { } SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs) - : SortedVector<sp<LayerBase> >(rhs) { + : SortedVector<sp<Layer> >(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<LayerBase>& l(*reinterpret_cast<const sp<LayerBase>*>(lhs)); - const sp<LayerBase>& r(*reinterpret_cast<const sp<LayerBase>*>(rhs)); + const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs)); + const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs)); uint32_t ls = l->currentState().layerStack; uint32_t rs = r->currentState().layerStack; @@ -2868,7 +3002,7 @@ SurfaceFlinger::DisplayDeviceState::DisplayDeviceState() } SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type) - : type(type), layerStack(0), orientation(0) { + : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0) { viewport.makeInvalid(); frame.makeInvalid(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1b549e4..739099c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -45,8 +45,9 @@ #include <private/gui/LayerState.h> #include "Barrier.h" -#include "MessageQueue.h" #include "DisplayDevice.h" +#include "FrameTracker.h" +#include "MessageQueue.h" #include "DisplayHardware/HWComposer.h" @@ -59,11 +60,8 @@ class DisplayEventConnection; class EventThread; class IGraphicBufferAlloc; class Layer; -class LayerBase; -class LayerBaseClient; class LayerDim; -class LayerScreenshot; -class SurfaceTextureClient; +class Surface; // --------------------------------------------------------------------------- @@ -102,14 +100,6 @@ public: // force full composition on all displays void repaintEverything(); - // renders content on given display to a texture. thread-safe version. - status_t renderScreenToTexture(uint32_t layerStack, GLuint* textureName, - GLfloat* uOut, GLfloat* vOut); - - // renders content on given display to a texture, w/o acquiring main lock - status_t renderScreenToTextureLocked(uint32_t layerStack, GLuint* textureName, - GLfloat* uOut, GLfloat* vOut); - // returns the default Display sp<const DisplayDevice> getDefaultDisplayDevice() const { return getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]); @@ -118,9 +108,6 @@ public: // utility function to delete a texture on the main thread void deleteTextureAsync(GLuint texture); - // allocate a h/w composer display id - int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type); - // enable/disable h/w composer event // TODO: this should be made accessible only to EventThread void eventControl(int disp, int event, int enabled); @@ -132,15 +119,13 @@ public: // for debugging only // TODO: this should be made accessible only to HWComposer - const Vector< sp<LayerBase> >& getLayerSortedByZForHwcDisplay(int disp); + const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id); private: friend class Client; friend class DisplayEventConnection; - friend class LayerBase; - friend class LayerBaseClient; friend class Layer; - friend class LayerScreenshot; + friend class SurfaceTextureLayer; // We're reference counted, never destroy SurfaceFlinger directly virtual ~SurfaceFlinger(); @@ -149,7 +134,7 @@ private: * Internal data structures */ - class LayerVector : public SortedVector<sp<LayerBase> > { + class LayerVector : public SortedVector< sp<Layer> > { public: LayerVector(); LayerVector(const LayerVector& rhs); @@ -163,7 +148,7 @@ private: bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; } bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; } DisplayDevice::DisplayType type; - sp<ISurfaceTexture> surface; + sp<IGraphicBufferProducer> surface; uint32_t layerStack; Rect viewport; Rect frame; @@ -195,12 +180,12 @@ private: const Vector<DisplayState>& displays, uint32_t flags); virtual void bootFinished(); virtual bool authenticateSurfaceTexture( - const sp<ISurfaceTexture>& surface) const; + const sp<IGraphicBufferProducer>& bufferProducer) const; virtual sp<IDisplayEventConnection> createDisplayEventConnection(); - virtual status_t captureScreen(const sp<IBinder>& display, sp<IMemoryHeap>* heap, - uint32_t* width, uint32_t* height, PixelFormat* format, - uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, - uint32_t maxLayerZ); + virtual status_t captureScreen(const sp<IBinder>& display, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ, bool isCpuConsumer); // called when screen needs to turn off virtual void blank(const sp<IBinder>& display); // called when screen is turning back on @@ -266,39 +251,36 @@ private: /* ------------------------------------------------------------------------ * Layer management */ - sp<ISurface> createLayer(ISurfaceComposerClient::surface_data_t* params, - const String8& name, const sp<Client>& client, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags); - - sp<Layer> createNormalLayer(const sp<Client>& client, - uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format); + status_t createLayer(const String8& name, const sp<Client>& client, + uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp); - sp<LayerDim> createDimLayer(const sp<Client>& client, - uint32_t w, uint32_t h, uint32_t flags); + status_t createNormalLayer(const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, + sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp, + sp<Layer>* outLayer); - sp<LayerScreenshot> createScreenshotLayer(const sp<Client>& client, - uint32_t w, uint32_t h, uint32_t flags); + status_t createDimLayer(const sp<Client>& client, const String8& name, + uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle, + sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer); // called in response to the window-manager calling // ISurfaceComposerClient::destroySurface() - // The specified layer is first placed in a purgatory list - // until all references from the client are released. - status_t onLayerRemoved(const sp<Client>& client, SurfaceID sid); + status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle); // 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<LayerBaseClient>& layer); + status_t onLayerDestroyed(const wp<Layer>& layer); // remove a layer from SurfaceFlinger immediately - status_t removeLayer(const sp<LayerBase>& layer); + status_t removeLayer(const sp<Layer>& layer); // add a layer to SurfaceFlinger - ssize_t addClientLayer(const sp<Client>& client, - const sp<LayerBaseClient>& lbc); - - status_t removeLayer_l(const sp<LayerBase>& layer); - status_t purgatorizeLayer_l(const sp<LayerBase>& layer); + void addClientLayer(const sp<Client>& client, + const sp<IBinder>& handle, + const sp<IGraphicBufferProducer>& gbc, + const sp<Layer>& lbc); /* ------------------------------------------------------------------------ * Boot animation, on/off animations and screen capture @@ -306,10 +288,24 @@ private: void startBootAnim(); - status_t captureScreenImplLocked(const sp<IBinder>& display, sp<IMemoryHeap>* heap, - uint32_t* width, uint32_t* height, PixelFormat* format, - uint32_t reqWidth, uint32_t reqHeight, uint32_t minLayerZ, - uint32_t maxLayerZ); + void renderScreenImplLocked( + const sp<const DisplayDevice>& hw, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ, + bool yswap); + + status_t captureScreenImplLocked( + const sp<const DisplayDevice>& hw, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ); + + status_t captureScreenImplCpuConsumerLocked( + const sp<const DisplayDevice>& hw, + const sp<IGraphicBufferProducer>& producer, + uint32_t reqWidth, uint32_t reqHeight, + uint32_t minLayerZ, uint32_t maxLayerZ); + /* ------------------------------------------------------------------------ * EGL @@ -345,6 +341,9 @@ private: // region of all screens presenting this layer stack. void invalidateLayerStack(uint32_t layerStack, const Region& dirty); + // allocate a h/w composer display id + int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type); + /* ------------------------------------------------------------------------ * H/W composer */ @@ -390,7 +389,7 @@ private: void dumpStatsLocked(const Vector<String16>& args, size_t& index, String8& result, char* buffer, size_t SIZE) const; void clearStatsLocked(const Vector<String16>& args, size_t& index, - String8& result, char* buffer, size_t SIZE) const; + String8& result, char* buffer, size_t SIZE); void dumpAllLocked(String8& result, char* buffer, size_t SIZE) const; bool startDdmConnection(); static void appendSfConfigString(String8& result); @@ -404,10 +403,10 @@ private: State mCurrentState; volatile int32_t mTransactionFlags; Condition mTransactionCV; - SortedVector<sp<LayerBase> > mLayerPurgatory; bool mTransactionPending; bool mAnimTransactionPending; - Vector<sp<LayerBase> > mLayersPendingRemoval; + Vector< sp<Layer> > mLayersPendingRemoval; + SortedVector< wp<IBinder> > mGraphicBufferProducerList; // protected by mStateLock (but we could use another lock) bool mLayersRemoved; @@ -419,12 +418,14 @@ private: HWComposer* mHwc; GLuint mProtectedTexName; nsecs_t mBootTime; + bool mGpuToCpuSupported; sp<EventThread> mEventThread; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; EGLContext mEGLContext; EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; + EGLint mEGLNativeVisualId; sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_DISPLAY_TYPES]; // Can only accessed from the main thread, these members @@ -432,6 +433,7 @@ private: State mDrawingState; bool mVisibleRegionsDirty; bool mHwWorkListDirty; + bool mAnimCompositionPending; // this may only be written from the main thread with mStateLock held // it may be read from other threads with mStateLock held @@ -451,10 +453,11 @@ private: // these are thread safe mutable MessageQueue mEventQueue; mutable Barrier mReadyToRunBarrier; + FrameTracker mAnimFrameTracker; // protected by mDestroyedLayerLock; mutable Mutex mDestroyedLayerLock; - Vector<LayerBase const *> mDestroyedLayers; + Vector<Layer const *> mDestroyedLayers; /* ------------------------------------------------------------------------ * Feature prototyping diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp new file mode 100644 index 0000000..2869250 --- /dev/null +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 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. + */ + +#define ATRACE_TAG ATRACE_TAG_GRAPHICS +//#define LOG_NDEBUG 0 + +#include "SurfaceFlingerConsumer.h" + +#include <private/gui/SyncFeatures.h> + +#include <utils/Trace.h> +#include <utils/Errors.h> + +namespace android { + +// --------------------------------------------------------------------------- + +status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter) +{ + ATRACE_CALL(); + ALOGV("updateTexImage"); + Mutex::Autolock lock(mMutex); + + if (mAbandoned) { + ALOGE("updateTexImage: GLConsumer is abandoned!"); + return NO_INIT; + } + + // Make sure the EGL state is the same as in previous calls. + status_t err = checkAndUpdateEglStateLocked(); + if (err != NO_ERROR) { + return err; + } + + BufferQueue::BufferItem item; + + // Acquire the next buffer. + // In asynchronous mode the list is guaranteed to be one buffer + // deep, while in synchronous mode we use the oldest buffer. + err = acquireBufferLocked(&item); + if (err != NO_ERROR) { + if (err == BufferQueue::NO_BUFFER_AVAILABLE) { + // This variant of updateTexImage does not guarantee that the + // texture is bound, so no need to call glBindTexture. + err = NO_ERROR; + } else { + ALOGE("updateTexImage: acquire failed: %s (%d)", + strerror(-err), err); + } + return err; + } + + + // We call the rejecter here, in case the caller has a reason to + // not accept this buffer. This is used by SurfaceFlinger to + // reject buffers which have the wrong size + int buf = item.mBuf; + if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) { + releaseBufferLocked(buf, EGL_NO_SYNC_KHR); + return NO_ERROR; + } + + // Release the previous buffer. + err = releaseAndUpdateLocked(item); + if (err != NO_ERROR) { + return err; + } + + if (!SyncFeatures::getInstance().useNativeFenceSync()) { + // Bind the new buffer to the GL texture. + // + // Older devices require the "implicit" synchronization provided + // by glEGLImageTargetTexture2DOES, which this method calls. Newer + // devices will either call this in Layer::onDraw, or (if it's not + // a GL-composited layer) not at all. + err = bindTextureImageLocked(); + } + + return err; +} + +status_t SurfaceFlingerConsumer::bindTextureImage() +{ + Mutex::Autolock lock(mMutex); + + return bindTextureImageLocked(); +} + +// --------------------------------------------------------------------------- +}; // namespace android + diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h new file mode 100644 index 0000000..22eec81 --- /dev/null +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2012 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_SURFACEFLINGERCONSUMER_H +#define ANDROID_SURFACEFLINGERCONSUMER_H + +#include <gui/GLConsumer.h> + +namespace android { +// ---------------------------------------------------------------------------- + +/* + * This is a thin wrapper around GLConsumer. + */ +class SurfaceFlingerConsumer : public GLConsumer { +public: + SurfaceFlingerConsumer(GLuint tex, bool allowSynchronousMode = true, + GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true, + const sp<BufferQueue> &bufferQueue = 0) + : GLConsumer(tex, allowSynchronousMode, texTarget, useFenceSync, + bufferQueue) + {} + + class BufferRejecter { + friend class SurfaceFlingerConsumer; + virtual bool reject(const sp<GraphicBuffer>& buf, + const BufferQueue::BufferItem& item) = 0; + + protected: + virtual ~BufferRejecter() { } + }; + + // This version of updateTexImage() takes a functor that may be used to + // reject the newly acquired buffer. Unlike the GLConsumer version, + // this does not guarantee that the buffer has been bound to the GL + // texture. + status_t updateTexImage(BufferRejecter* rejecter); + + // See GLConsumer::bindTextureImageLocked(). + status_t bindTextureImage(); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + +#endif // ANDROID_SURFACEFLINGERCONSUMER_H diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index 0b638b4..d0f0dae 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -20,18 +20,35 @@ #include <utils/Errors.h> -#include "Layer.h" +#include "SurfaceFlinger.h" #include "SurfaceTextureLayer.h" namespace android { // --------------------------------------------------------------------------- -SurfaceTextureLayer::SurfaceTextureLayer() - : BufferQueue(true) { +SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger) + : BufferQueue(true), flinger(flinger) { } SurfaceTextureLayer::~SurfaceTextureLayer() { + // remove ourselves from SurfaceFlinger's list. We do this asynchronously + // because we don't know where this dtor is called from, it could be + // called with the mStateLock held, leading to a dead-lock (it actually + // happens). + class MessageCleanUpList : public MessageBase { + sp<SurfaceFlinger> flinger; + wp<IBinder> gbp; + public: + MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp) + : flinger(flinger), gbp(gbp) { } + virtual bool handler() { + Mutex::Autolock _l(flinger->mStateLock); + flinger->mGraphicBufferProducerList.remove(gbp); + return true; + } + }; + flinger->postMessageAsync( new MessageCleanUpList(flinger, this) ); } status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) { diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h index e892ea0..13cff2f 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.h +++ b/services/surfaceflinger/SurfaceTextureLayer.h @@ -28,15 +28,19 @@ namespace android { // --------------------------------------------------------------------------- class Layer; +class SurfaceFlinger; -// SurfaceTextureLayer is now a BufferQueue since SurfaceTexture has been -// refactored -class SurfaceTextureLayer : public BufferQueue -{ +/* + * This is a thin wrapper around BufferQueue, used by the Layer class. + */ +class SurfaceTextureLayer : public BufferQueue { + sp<SurfaceFlinger> flinger; public: - SurfaceTextureLayer(); - ~SurfaceTextureLayer(); + SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger); + virtual ~SurfaceTextureLayer(); + // After calling the superclass connect(), set or clear synchronous + // mode appropriately for the specified API. virtual status_t connect(int api, QueueBufferOutput* output); }; diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index aca90e0..315720e 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -298,6 +298,44 @@ uint32_t Transform::type() const return mType; } +Transform Transform::inverse() const { + // our 3x3 matrix is always of the form of a 2x2 transformation + // followed by a translation: T*M, therefore: + // (T*M)^-1 = M^-1 * T^-1 + Transform result; + if (mType <= TRANSLATE) { + // 1 0 x + // 0 1 y + // 0 0 1 + result = *this; + result.mMatrix[2][0] = -result.mMatrix[2][0]; + result.mMatrix[2][1] = -result.mMatrix[2][1]; + } else { + // a c x + // b d y + // 0 0 1 + const mat33& M(mMatrix); + const float a = M[0][0]; + const float b = M[1][0]; + const float c = M[0][1]; + const float d = M[1][1]; + const float x = M[2][0]; + const float y = M[2][1]; + + Transform R, T; + const float idet = 1.0 / (a*d - b*c); + R.mMatrix[0][0] = d*idet; R.mMatrix[0][1] = -c*idet; + R.mMatrix[1][0] = -b*idet; R.mMatrix[1][1] = a*idet; + R.mType = mType &= ~TRANSLATE; + + T.mMatrix[2][0] = -x; + T.mMatrix[2][1] = -y; + T.mType = TRANSLATE; + result = R * T; + } + return result; +} + uint32_t Transform::getType() const { return type() & 0xFF; } diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h index 4fe261a..c4efade 100644 --- a/services/surfaceflinger/Transform.h +++ b/services/surfaceflinger/Transform.h @@ -80,6 +80,8 @@ public: Rect transform(const Rect& bounds) const; Transform operator * (const Transform& rhs) const; + Transform inverse() const; + // for debugging void dump(const char* name) const; diff --git a/services/surfaceflinger/clz.cpp b/services/surfaceflinger/clz.cpp deleted file mode 100644 index 2456b86..0000000 --- a/services/surfaceflinger/clz.cpp +++ /dev/null @@ -1,37 +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 "clz.h" - -namespace android { - -int clz_impl(int32_t x) -{ -#if defined(__arm__) && !defined(__thumb__) - return __builtin_clz(x); -#else - if (!x) return 32; - int e = 31; - if (x&0xFFFF0000) { e -=16; x >>=16; } - if (x&0x0000FF00) { e -= 8; x >>= 8; } - if (x&0x000000F0) { e -= 4; x >>= 4; } - if (x&0x0000000C) { e -= 2; x >>= 2; } - if (x&0x00000002) { e -= 1; } - return e; -#endif -} - -}; // namespace android diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 0592c5b..4d363c8 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -31,14 +31,14 @@ namespace android { // Fill an RGBA_8888 formatted surface with a single color. static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, uint8_t r, uint8_t g, uint8_t b) { - Surface::SurfaceInfo info; + ANativeWindow_Buffer outBuffer; sp<Surface> s = sc->getSurface(); ASSERT_TRUE(s != NULL); - ASSERT_EQ(NO_ERROR, s->lock(&info)); - uint8_t* img = reinterpret_cast<uint8_t*>(info.bits); - for (uint32_t y = 0; y < info.h; y++) { - for (uint32_t x = 0; x < info.w; x++) { - uint8_t* pixel = img + (4 * (y*info.s + x)); + ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL)); + uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits); + for (uint32_t y = 0; y < outBuffer.height; y++) { + for (uint32_t x = 0; x < outBuffer.width; x++) { + uint8_t* pixel = img + (4 * (y*outBuffer.stride + x)); pixel[0] = r; pixel[1] = g; pixel[2] = b; diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp index d61ea70..8b051e8 100644 --- a/services/surfaceflinger/tests/resize/resize.cpp +++ b/services/surfaceflinger/tests/resize/resize.cpp @@ -38,26 +38,27 @@ int main(int argc, char** argv) // create a client to surfaceflinger sp<SurfaceComposerClient> client = new SurfaceComposerClient(); - sp<Surface> surface = client->createSurface(String8("resize"), + sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"), 160, 240, PIXEL_FORMAT_RGB_565, 0); + sp<Surface> surface = surfaceControl->getSurface(); SurfaceComposerClient::openGlobalTransaction(); - surface->setLayer(100000); + surfaceControl->setLayer(100000); SurfaceComposerClient::closeGlobalTransaction(); - Surface::SurfaceInfo info; - surface->lock(&info); - ssize_t bpr = info.s * bytesPerPixel(info.format); - android_memset16((uint16_t*)info.bits, 0xF800, bpr*info.h); + ANativeWindow_Buffer outBuffer; + surface->lock(&outBuffer, NULL); + ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format); + android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height); surface->unlockAndPost(); - surface->lock(&info); - android_memset16((uint16_t*)info.bits, 0x07E0, bpr*info.h); + surface->lock(&outBuffer); + android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height); surface->unlockAndPost(); SurfaceComposerClient::openGlobalTransaction(); - surface->setSize(320, 240); + surfaceControl->setSize(320, 240); SurfaceComposerClient::closeGlobalTransaction(); diff --git a/services/surfaceflinger/tests/surface/Android.mk b/services/surfaceflinger/tests/surface/Android.mk deleted file mode 100644 index c59060e..0000000 --- a/services/surfaceflinger/tests/surface/Android.mk +++ /dev/null @@ -1,18 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - surface.cpp - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - libutils \ - libbinder \ - libui \ - libgui - -LOCAL_MODULE:= test-surface - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) diff --git a/services/surfaceflinger/tests/surface/surface.cpp b/services/surfaceflinger/tests/surface/surface.cpp deleted file mode 100644 index 9c41cc3..0000000 --- a/services/surfaceflinger/tests/surface/surface.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2010 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 <cutils/memory.h> - -#include <utils/Log.h> - -#include <binder/IPCThreadState.h> -#include <binder/ProcessState.h> -#include <binder/IServiceManager.h> - -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> - -using namespace android; - -int main(int argc, char** argv) -{ - // set up the thread-pool - sp<ProcessState> proc(ProcessState::self()); - ProcessState::self()->startThreadPool(); - - // create a client to surfaceflinger - sp<SurfaceComposerClient> client = new SurfaceComposerClient(); - - sp<SurfaceControl> surfaceControl = client->createSurface( - String8("surface"), 160, 240, PIXEL_FORMAT_RGB_565, 0); - SurfaceComposerClient::openGlobalTransaction(); - surfaceControl->setLayer(100000); - SurfaceComposerClient::closeGlobalTransaction(); - - // pretend it went cross-process - Parcel parcel; - SurfaceControl::writeSurfaceToParcel(surfaceControl, &parcel); - parcel.setDataPosition(0); - sp<Surface> surface = Surface::readFromParcel(parcel); - ANativeWindow* window = surface.get(); - - printf("window=%p\n", window); - - int err = native_window_set_buffer_count(window, 8); - ANativeWindowBuffer* buffer; - - for (int i=0 ; i<8 ; i++) { - window->dequeueBuffer(window, &buffer); - printf("buffer %d: %p\n", i, buffer); - } - - printf("test complete. CTRL+C to finish.\n"); - - IPCThreadState::self()->joinThreadPool(); - return 0; -} |