Merge "Add GL Error logs (temporary)" into jb-mr1-dev
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 923845c..d970a33 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -46,7 +46,8 @@
LOCAL_CFLAGS += -DUSE_FENCE_SYNC
endif
ifeq ($(TARGET_BOARD_PLATFORM), exynos5)
- LOCAL_CFLAGS += -DUSE_FENCE_SYNC
+ LOCAL_CFLAGS += -DUSE_NATIVE_FENCE_SYNC
+ LOCAL_CFLAGS += -DUSE_WAIT_SYNC
endif
ifneq ($(filter generic%,$(TARGET_DEVICE)),)
# Emulator build
@@ -57,10 +58,6 @@
LOCAL_CFLAGS += -DUSE_NATIVE_FENCE_SYNC
endif
-ifeq ($(TARGET_BOARD_PLATFORM), tegra)
- LOCAL_CFLAGS += -DALLOW_DEQUEUE_CURRENT_BUFFER
-endif
-
include $(BUILD_SHARED_LIBRARY)
ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 8594b84..d408476 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -32,23 +32,6 @@
#include <gui/SurfaceTexture.h>
#include <utils/Trace.h>
-// This compile option causes SurfaceTexture to return the buffer that is currently
-// attached to the GL texture from dequeueBuffer when no other buffers are
-// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
-// implicit cross-process synchronization to prevent the buffer from being
-// written to before the buffer has (a) been detached from the GL texture and
-// (b) all GL reads from the buffer have completed.
-
-// During refactoring, do not support dequeuing the current buffer
-#undef ALLOW_DEQUEUE_CURRENT_BUFFER
-
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
-#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
-#else
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
-#endif
-
// Macros for including the BufferQueue name in log messages
#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
@@ -325,24 +308,16 @@
dequeuedCount++;
}
- // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
- // but dequeuing the current buffer is disabled.
- if (false) {
- // This functionality has been temporarily removed so
- // BufferQueue and SurfaceTexture can be refactored into
- // separate objects
- } else {
- if (state == BufferSlot::FREE) {
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- bool isOlder = mSlots[i].mFrameNumber <
- mSlots[found].mFrameNumber;
- if (found < 0 || isOlder) {
- found = i;
- }
+ if (state == BufferSlot::FREE) {
+ /* We return the oldest of the free buffers to avoid
+ * stalling the producer if possible. This is because
+ * the consumer may still have pending reads of the
+ * buffers in flight.
+ */
+ bool isOlder = mSlots[i].mFrameNumber <
+ mSlots[found].mFrameNumber;
+ if (found < 0 || isOlder) {
+ found = i;
}
}
}
diff --git a/libs/gui/CleanSpec.mk b/libs/gui/CleanSpec.mk
index 1713694..c062229 100644
--- a/libs/gui/CleanSpec.mk
+++ b/libs/gui/CleanSpec.mk
@@ -48,3 +48,4 @@
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
$(call add-clean-step, find $(PRODUCT_OUT) -type f -name "libgui*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libgui_intermediates)
diff --git a/libs/gui/GuiConfig.cpp b/libs/gui/GuiConfig.cpp
index 0744e4f..bafd21a 100644
--- a/libs/gui/GuiConfig.cpp
+++ b/libs/gui/GuiConfig.cpp
@@ -28,8 +28,8 @@
#ifdef USE_NATIVE_FENCE_SYNC
" USE_NATIVE_FENCE_SYNC"
#endif
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
- " ALLOW_DEQUEUE_CURRENT_BUFFER"
+#ifdef USE_WAIT_SYNC
+ " USE_WAIT_SYNC"
#endif
"]";
configStr.append(config);
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 8df1302..57bcd2c 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -63,16 +63,6 @@
static const bool useWaitSync = false;
#endif
-// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
-// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
-// waiting for the GL reads for the buffer being dequeued to complete before
-// allowing the buffer to be dequeued.
-#ifdef USE_FENCE_SYNC
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
-#endif
-#endif
-
// Macros for including the SurfaceTexture name in log messages
#define ST_LOGV(x, ...) ALOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
#define ST_LOGD(x, ...) ALOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index fb93c47..597e5d6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -147,7 +147,7 @@
// don't need a vsync thread if we have a hardware composer
needVSyncThread = false;
// always turn vsync off when we start
- mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+ eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
// these IDs are always reserved
for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
@@ -202,7 +202,7 @@
HWComposer::~HWComposer() {
if (mHwc) {
- mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+ eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
}
if (mVSyncThread != NULL) {
mVSyncThread->requestExitAndWait();
@@ -443,16 +443,32 @@
return mDisplayData[disp].connected;
}
-void HWComposer::eventControl(int event, int enabled) {
+void HWComposer::eventControl(int disp, int event, int enabled) {
+ if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
+ return;
+ }
status_t err = NO_ERROR;
- if (mHwc) {
- if (!mDebugForceFakeVSync) {
- err = mHwc->eventControl(mHwc, 0, event, enabled);
- // error here should not happen -- not sure what we should
- // do if it does.
- ALOGE_IF(err, "eventControl(%d, %d) failed %s",
- event, enabled, strerror(-err));
+ if (mHwc && !mDebugForceFakeVSync) {
+ // NOTE: we use our own internal lock here because we have to call
+ // into the HWC with the lock held, and we want to make sure
+ // that even if HWC blocks (which it shouldn't), it won't
+ // affect other threads.
+ Mutex::Autolock _l(mEventControlLock);
+ const int32_t eventBit = 1UL << event;
+ const int32_t newValue = enabled ? eventBit : 0;
+ const int32_t oldValue = mDisplayData[disp].events & eventBit;
+ if (newValue != oldValue) {
+ ATRACE_CALL();
+ err = mHwc->eventControl(mHwc, disp, event, enabled);
+ if (!err) {
+ int32_t& events(mDisplayData[disp].events);
+ events = (events & ~eventBit) | newValue;
+ }
}
+ // error here should not happen -- not sure what we should
+ // do if it does.
+ ALOGE_IF(err, "eventControl(%d, %d) failed %s",
+ event, enabled, strerror(-err));
}
if (err == NO_ERROR && mVSyncThread != NULL) {
@@ -540,8 +556,13 @@
// DO NOT reset the handle field to NULL, because it's possible
// that we have nothing to redraw (eg: eglSwapBuffers() not called)
// in which case, we should continue to use the same buffer.
+ LOG_FATAL_IF(disp.list == NULL);
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
}
+ if (!disp.connected && disp.list != NULL) {
+ ALOGW("WARNING: disp %d: connected, non-null list, layers=%d",
+ i, disp.list->numHwLayers);
+ }
mLists[i] = disp.list;
if (mLists[i]) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
@@ -647,16 +668,16 @@
return (status_t)err;
}
-status_t HWComposer::release(int disp) const {
+status_t HWComposer::release(int disp) {
LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
if (mHwc) {
- mHwc->eventControl(mHwc, disp, HWC_EVENT_VSYNC, 0);
+ eventControl(disp, HWC_EVENT_VSYNC, 0);
return (status_t)mHwc->blank(mHwc, disp, 1);
}
return NO_ERROR;
}
-status_t HWComposer::acquire(int disp) const {
+status_t HWComposer::acquire(int disp) {
LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
if (mHwc) {
return (status_t)mHwc->blank(mHwc, disp, 0);
@@ -664,6 +685,17 @@
return NO_ERROR;
}
+void HWComposer::disconnectDisplay(int disp) {
+ LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY ||
+ disp >= HWC_NUM_DISPLAY_TYPES);
+ DisplayData& dd(mDisplayData[disp]);
+ if (dd.list != NULL) {
+ free(dd.list);
+ dd.list = NULL;
+ dd.framebufferTarget = NULL; // points into dd.list
+ }
+}
+
int HWComposer::getVisualID() const {
if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
@@ -949,8 +981,10 @@
void HWComposer::VSyncThread::setEnabled(bool enabled) {
Mutex::Autolock _l(mLock);
- mEnabled = enabled;
- mCondition.signal();
+ if (mEnabled != enabled) {
+ mEnabled = enabled;
+ mCondition.signal();
+ }
}
void HWComposer::VSyncThread::onFirstRef() {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 633ca9c..269e147 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -92,10 +92,13 @@
status_t commit();
// release hardware resources and blank screen
- status_t release(int disp) const;
+ status_t release(int disp);
// acquire hardware resources and unblank screen
- status_t acquire(int disp) const;
+ status_t acquire(int disp);
+
+ // reset state when an external, non-virtual display is disconnected
+ void disconnectDisplay(int disp);
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
status_t createWorkList(int32_t id, size_t numLayers);
@@ -223,7 +226,7 @@
EVENT_VSYNC = HWC_EVENT_VSYNC
};
- void eventControl(int event, int enabled);
+ void eventControl(int disp, int event, int enabled);
// Query display parameters. Pass in a display index (e.g.
// HWC_DISPLAY_PRIMARY).
@@ -286,7 +289,7 @@
DisplayData() : xdpi(0), ydpi(0), refresh(0),
connected(false), hasFbComp(false), hasOvComp(false),
capacity(0), list(NULL),
- framebufferTarget(NULL), fbTargetHandle(NULL) { }
+ framebufferTarget(NULL), fbTargetHandle(NULL), events(0) { }
~DisplayData() {
free(list);
}
@@ -303,6 +306,8 @@
hwc_display_contents_1* list;
hwc_layer_1* framebufferTarget;
buffer_handle_t fbTargetHandle;
+ // protected by mEventControlLock
+ int32_t events;
};
sp<SurfaceFlinger> mFlinger;
@@ -324,6 +329,9 @@
// protected by mLock
mutable Mutex mLock;
mutable nsecs_t mLastHwVSync;
+
+ // thread-safe
+ mutable Mutex mEventControlLock;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 6b7c78b..edb9fa5 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -308,14 +308,14 @@
void EventThread::enableVSyncLocked() {
if (!mUseSoftwareVSync) {
// never enable h/w VSYNC when screen is off
- mFlinger->eventControl(SurfaceFlinger::EVENT_VSYNC, true);
+ mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mPowerHAL.vsyncHint(true);
}
mDebugVsyncEnabled = true;
}
void EventThread::disableVSyncLocked() {
- mFlinger->eventControl(SurfaceFlinger::EVENT_VSYNC, false);
+ mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
mPowerHAL.vsyncHint(false);
mDebugVsyncEnabled = false;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a8d20bb..1103175 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -777,8 +777,8 @@
}
}
-void SurfaceFlinger::eventControl(int event, int enabled) {
- getHwComposer().eventControl(event, enabled);
+void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
+ getHwComposer().eventControl(disp, event, enabled);
}
void SurfaceFlinger::onMessageReceived(int32_t what) {
@@ -1123,7 +1123,13 @@
if (j < 0) {
// in drawing state but not in current state
if (!draw[i].isMainDisplay()) {
+ // 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);
mDisplays.removeItem(draw.keyAt(i));
+ getHwComposer().disconnectDisplay(draw[i].type);
} else {
ALOGW("trying to remove the main display");
}
@@ -1701,8 +1707,12 @@
uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
{
+ ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
+ if (dpyIdx < 0)
+ return 0;
+
uint32_t flags = 0;
- DisplayDeviceState& disp(mCurrentState.displays.editValueFor(s.token));
+ DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
if (disp.isValid()) {
const uint32_t what = s.what;
if (what & DisplayState::eSurfaceChanged) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8272848..5bb3703 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -123,7 +123,7 @@
// enable/disable h/w composer event
// TODO: this should be made accessible only to EventThread
- void eventControl(int event, int enabled);
+ void eventControl(int disp, int event, int enabled);
// called on the main thread by MessageQueue when an internal message
// is received