diff options
author | Jesse Hall <jessehall@google.com> | 2013-03-22 15:13:48 -0700 |
---|---|---|
committer | Jesse Hall <jessehall@google.com> | 2013-03-22 15:27:58 -0700 |
commit | ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a (patch) | |
tree | e96e4d9d19a81ec6ee46052e54f3b2fda16465f3 /services | |
parent | 48bc05b56df9919fc39c5f2e3ea6535560eec98f (diff) | |
download | frameworks_native-ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a.zip frameworks_native-ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a.tar.gz frameworks_native-ffe1f19ca9707f84cb9fdb06209bf36cd8c2ef0a.tar.bz2 |
Fix virtual displays for HWC<=1.1
If we're using a HWC that doesn't support virtual displays, or we have
more virtual displays than HWC supports concurrently, the
VirtualDisplaySurface should simply be a passthrough from source
(GLES) to sink.
This change also tries to distinguish between display types and HWC
display IDs a little better, though there's more to do here. Probably
needs a higher-level rethink; it's too error-prone now.
Bug: 8446838
Change-Id: I708d2cf262ec30177042304f174ca5b8da701df1
Diffstat (limited to 'services')
-rw-r--r-- | services/surfaceflinger/DisplayDevice.cpp | 69 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp | 32 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h | 16 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 10 |
5 files changed, 73 insertions, 57 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index cdc16ed..6936a7f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -70,12 +70,13 @@ void checkGLErrors() DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, + int32_t hwcId, bool isSecure, const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, EGLConfig config) : mFlinger(flinger), - mType(type), mHwcDisplayId(-1), + mType(type), mHwcDisplayId(hwcId), mDisplayToken(displayToken), mDisplaySurface(displaySurface), mDisplay(EGL_NO_DISPLAY), @@ -91,38 +92,6 @@ DisplayDevice::DisplayDevice( mOrientation() { mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer()); - 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) -{ ANativeWindow* const window = mNativeWindow.get(); int format; @@ -146,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(). @@ -170,6 +136,33 @@ void DisplayDevice::init(EGLConfig config) setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); } +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::setDisplayName(const String8& displayName) { if (!displayName.isEmpty()) { // never override the name with an empty name diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index d8f55b4..d4a6daa 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -72,6 +72,7 @@ public: DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, + int32_t hwcId, // negative for non-HWC-composited displays bool isSecure, const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, @@ -152,8 +153,6 @@ public: void dump(String8& result, char* buffer, size_t SIZE) const; private: - void init(EGLConfig config); - /* * Constants, set during initialization */ diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index b28500e..d2b3edb 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -21,24 +21,30 @@ namespace android { // --------------------------------------------------------------------------- -VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int disp, +VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, const sp<IGraphicBufferProducer>& sink, const String8& name) : mHwc(hwc), - mDisplayId(disp), - mSource(new BufferQueueInterposer(sink, name)), + mDisplayId(dispId), mName(name) -{} +{ + if (mDisplayId >= 0) { + mInterposer = new BufferQueueInterposer(sink, name); + mSourceProducer = mInterposer; + } else { + mSourceProducer = sink; + } +} VirtualDisplaySurface::~VirtualDisplaySurface() { if (mAcquiredBuffer != NULL) { - status_t result = mSource->releaseBuffer(Fence::NO_FENCE); + status_t result = mInterposer->releaseBuffer(Fence::NO_FENCE); ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " "failed to release buffer: %d", mName.string(), result); } } sp<IGraphicBufferProducer> VirtualDisplaySurface::getIGraphicBufferProducer() const { - return mSource; + return mSourceProducer; } status_t VirtualDisplaySurface::compositionComplete() { @@ -46,6 +52,9 @@ status_t VirtualDisplaySurface::compositionComplete() { } status_t VirtualDisplaySurface::advanceFrame() { + if (mInterposer == NULL) + return NO_ERROR; + Mutex::Autolock lock(mMutex); status_t result = NO_ERROR; @@ -57,12 +66,12 @@ status_t VirtualDisplaySurface::advanceFrame() { } sp<Fence> fence; - result = mSource->acquireBuffer(&mAcquiredBuffer, &fence); + result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence); if (result == BufferQueueInterposer::NO_BUFFER_AVAILABLE) { - result = mSource->pullEmptyBuffer(); + result = mInterposer->pullEmptyBuffer(); if (result != NO_ERROR) return result; - result = mSource->acquireBuffer(&mAcquiredBuffer, &fence); + result = mInterposer->acquireBuffer(&mAcquiredBuffer, &fence); } if (result != NO_ERROR) return result; @@ -71,6 +80,9 @@ status_t VirtualDisplaySurface::advanceFrame() { } void VirtualDisplaySurface::onFrameCommitted() { + if (mInterposer == NULL) + return; + Mutex::Autolock lock(mMutex); if (mAcquiredBuffer != NULL) { // fbFence signals when reads from the framebuffer are finished @@ -85,7 +97,7 @@ void VirtualDisplaySurface::onFrameCommitted() { String8::format("HWC done: %.21s", mName.string()), fbFence, outFence); - status_t result = mSource->releaseBuffer(fence); + status_t result = mInterposer->releaseBuffer(fence); ALOGE_IF(result != NO_ERROR, "VirtualDisplaySurface \"%s\": " "failed to release buffer: %d", mName.string(), result); mAcquiredBuffer.clear(); diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index 61bafed..0706e75 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -45,12 +45,18 @@ class HWComposer; * eglSwapBuffers doesn't immediately dequeue a buffer for the next frame, * since we can't rely on being able to dequeue more than one buffer at a time. * + * This class also has a passthrough mode, where it doesn't use a + * BufferQueueInterposer and never sends buffers to HWC. Instead, OpenGL ES + * output buffers are queued directly to the virtual display sink; this class + * is inactive after construction. This mode is used when the HWC doesn't + * support compositing for virtual displays. + * * TODO(jessehall): Add a libgui test that ensures that EGL/GLES do lazy * dequeBuffers; we've wanted to require that for other reasons anyway. */ class VirtualDisplaySurface : public DisplaySurface { public: - VirtualDisplaySurface(HWComposer& hwc, int disp, + VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, const sp<IGraphicBufferProducer>& sink, const String8& name); @@ -66,10 +72,14 @@ private: // immutable after construction HWComposer& mHwc; - int mDisplayId; - sp<BufferQueueInterposer> mSource; + int32_t mDisplayId; String8 mName; + // with HWC support, both of these point to the same object. + // otherwise, mInterposer is NULL and mSourceProducer is the sink. + sp<BufferQueueInterposer> mInterposer; + sp<IGraphicBufferProducer> mSourceProducer; + // mutable, must be synchronized with mMutex Mutex mMutex; sp<GraphicBuffer> mAcquiredBuffer; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2df279a..0a210f7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -510,7 +510,8 @@ status_t SurfaceFlinger::readyToRun() wp<IBinder> token = mBuiltinDisplays[i]; sp<DisplayDevice> hw = new DisplayDevice(this, - type, isSecure, token, new FramebufferSurface(*mHwc, i), + type, allocateHwcDisplayId(type), isSecure, token, + new FramebufferSurface(*mHwc, i), mEGLConfig); if (i > DisplayDevice::DISPLAY_PRIMARY) { // FIXME: currently we don't get blank/unblank requests @@ -1149,10 +1150,11 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const DisplayDeviceState& state(curr[i]); sp<DisplaySurface> dispSurface; + int32_t hwcDisplayId = allocateHwcDisplayId(state.type); if (state.isVirtualDisplay()) { if (state.surface != NULL) { dispSurface = new VirtualDisplaySurface( - *mHwc, state.type, state.surface, + *mHwc, hwcDisplayId, state.surface, state.displayName); } } else { @@ -1169,8 +1171,8 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) const wp<IBinder>& display(curr.keyAt(i)); if (dispSurface != NULL) { sp<DisplayDevice> hw = new DisplayDevice(this, - state.type, state.isSecure, display, - dispSurface, mEGLConfig); + state.type, hwcDisplayId, state.isSecure, + display, dispSurface, mEGLConfig); hw->setLayerStack(state.layerStack); hw->setProjection(state.orientation, state.viewport, state.frame); |