Merge "Bugreport broadcasts are only useful to owners." into jb-mr2-dev
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index e16abef..6936a7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -70,12 +70,13 @@
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,7 +92,48 @@
mOrientation()
{
mNativeWindow = new Surface(mDisplaySurface->getIGraphicBufferProducer());
- init(config);
+ ANativeWindow* const window = mNativeWindow.get();
+
+ int format;
+ window->query(window, NATIVE_WINDOW_FORMAT, &format);
+
+ /*
+ * Create our display's surface
+ */
+
+ EGLSurface surface;
+ EGLint w, h;
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ surface = eglCreateWindowSurface(display, config, window, NULL);
+ eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
+ eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
+
+ mDisplay = display;
+ mSurface = surface;
+ mFormat = format;
+ mPageFlipCount = 0;
+ mViewport.makeInvalid();
+ mFrame.makeInvalid();
+
+ // 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().
+ switch (mType) {
+ case DISPLAY_PRIMARY:
+ mDisplayName = "Built-in Screen";
+ break;
+ case DISPLAY_EXTERNAL:
+ mDisplayName = "HDMI Screen";
+ break;
+ default:
+ mDisplayName = "Virtual Screen"; // e.g. Overlay #n
+ break;
+ }
+
+ // initialize the display orientation transform.
+ setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
DisplayDevice::~DisplayDevice() {
@@ -121,55 +163,6 @@
return mSurface;
}
-void DisplayDevice::init(EGLConfig config)
-{
- ANativeWindow* const window = mNativeWindow.get();
-
- int format;
- window->query(window, NATIVE_WINDOW_FORMAT, &format);
-
- /*
- * Create our display's surface
- */
-
- EGLSurface surface;
- EGLint w, h;
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- surface = eglCreateWindowSurface(display, config, window, NULL);
- eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
- eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
-
- mDisplay = display;
- mSurface = surface;
- mFormat = format;
- mPageFlipCount = 0;
- 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);
-
- // Name the display. The name will be replaced shortly if the display
- // was created with createDisplay().
- switch (mType) {
- case DISPLAY_PRIMARY:
- mDisplayName = "Built-in Screen";
- break;
- case DISPLAY_EXTERNAL:
- mDisplayName = "HDMI Screen";
- break;
- default:
- mDisplayName = "Virtual Screen"; // e.g. Overlay #n
- break;
- }
-
- // initialize the display orientation transform.
- setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
-}
-
void DisplayDevice::setDisplayName(const String8& displayName) {
if (!displayName.isEmpty()) {
// never override the name with an empty name
@@ -235,8 +228,7 @@
void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
if (hwc.initCheck() == NO_ERROR) {
- sp<Fence> fence = hwc.getAndResetReleaseFence(mType);
- mDisplaySurface->onFrameCommitted(fence);
+ mDisplaySurface->onFrameCommitted();
}
}
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 @@
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 @@
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/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index bc717a9..2eca3cb 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -49,10 +49,9 @@
virtual status_t advanceFrame() = 0;
// onFrameCommitted is called after the frame has been committed to the
- // hardware composer and a release fence is available for the buffer.
- // Further operations on the buffer can be queued as long as they wait for
- // the fence to signal.
- virtual void onFrameCommitted(const sp<Fence>& fence) = 0;
+ // hardware composer. The surface collects the release fence for this
+ // frame's buffer.
+ virtual void onFrameCommitted() = 0;
virtual void dump(String8& result) const = 0;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index c35ac95..1936893 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -140,7 +140,8 @@
}
}
-void FramebufferSurface::onFrameCommitted(const sp<Fence>& fence) {
+void FramebufferSurface::onFrameCommitted() {
+ sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
if (fence->isValid() &&
mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
status_t err = addReleaseFence(mCurrentBufferSlot, fence);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 164f81f..2fde789 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -43,7 +43,7 @@
virtual status_t compositionComplete();
virtual status_t advanceFrame();
- virtual void onFrameCommitted(const sp<Fence>& fence);
+ virtual void onFrameCommitted();
// Implementation of DisplaySurface::dump(). Note that ConsumerBase also
// has a non-virtual dump() with the same signature.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 9d32410..497593b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -657,15 +657,12 @@
mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
}
- // For virtual displays, the framebufferTarget buffer also serves as
- // the HWC output buffer, so we need to copy the buffer handle and
- // dup() the acquire fence.
for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
DisplayData& disp(mDisplayData[i]);
- if (disp.framebufferTarget) {
- mLists[i]->outbuf = disp.framebufferTarget->handle;
+ if (disp.outbufHandle) {
+ mLists[i]->outbuf = disp.outbufHandle;
mLists[i]->outbufAcquireFenceFd =
- dup(disp.framebufferTarget->acquireFenceFd);
+ disp.outbufAcquireFence->dup();
}
}
@@ -706,17 +703,15 @@
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 {
@@ -765,6 +760,25 @@
}
}
+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
@@ -1071,6 +1085,7 @@
capacity(0), list(NULL),
framebufferTarget(NULL), fbTargetHandle(0),
lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
+ outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
events(0)
{}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 346526a..58f7e8f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -128,6 +128,17 @@
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
@@ -306,6 +317,8 @@
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
index 255b77f..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::advanceFrame() {
+ if (mInterposer == NULL)
+ return NO_ERROR;
+
Mutex::Autolock lock(mMutex);
status_t result = NO_ERROR;
@@ -57,12 +66,12 @@
}
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;
@@ -70,10 +79,25 @@
return mHwc.fbPost(mDisplayId, fence, mAcquiredBuffer);
}
-void VirtualDisplaySurface::onFrameCommitted(const sp<Fence>& fence) {
+void VirtualDisplaySurface::onFrameCommitted() {
+ if (mInterposer == NULL)
+ return;
+
Mutex::Autolock lock(mMutex);
if (mAcquiredBuffer != NULL) {
- status_t result = mSource->releaseBuffer(fence);
+ // fbFence signals when reads from the framebuffer are finished
+ // outFence signals when writes to the output buffer are finished
+ // It's unlikely that there will be an implementation where fbFence
+ // signals after outFence (in fact they'll typically be the same
+ // sync_pt), but just to be pedantic we merge them so the sink will
+ // be sure to wait until both are complete.
+ sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
+ sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
+ sp<Fence> fence = Fence::merge(
+ String8::format("HWC done: %.21s", mName.string()),
+ fbFence, outFence);
+
+ 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 1347680..0706e75 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -45,12 +45,18 @@
* 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);
@@ -58,7 +64,7 @@
virtual status_t compositionComplete();
virtual status_t advanceFrame();
- virtual void onFrameCommitted(const sp<Fence>& fence);
+ virtual void onFrameCommitted();
virtual void dump(String8& result) const;
private:
@@ -66,10 +72,14 @@
// 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 0e5d602..0a210f7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -510,7 +510,8 @@
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 @@
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 @@
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);
@@ -2381,9 +2383,21 @@
}
const Vector< sp<Layer> >&
-SurfaceFlinger::getLayerSortedByZForHwcDisplay(int disp) {
+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()
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1017560..f0e6deb 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -122,7 +122,7 @@
// for debugging only
// TODO: this should be made accessible only to HWComposer
- const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int disp);
+ const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
private:
friend class Client;