Merge "[MIPS] Avoid unaligned load/store for 64-bit doubles."
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 8718bb6..55a36c2 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -25,7 +25,7 @@
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
-#include <linux/capability.h>
+#include <sys/capability.h>
#include <linux/prctl.h>
#include <cutils/properties.h>
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
index 8f132d5..eaef3d4 100644
--- a/cmds/dumpstate/utils.c
+++ b/cmds/dumpstate/utils.c
@@ -31,6 +31,7 @@
#include <sys/klog.h>
#include <time.h>
#include <unistd.h>
+#include <sys/prctl.h>
#include <cutils/debugger.h>
#include <cutils/properties.h>
@@ -199,6 +200,9 @@
const char *args[1024] = {command};
size_t arg;
+ /* make sure the child dies when dumpstate dies */
+ prctl(PR_SET_PDEATHSIG, SIGKILL);
+
va_list ap;
va_start(ap, command);
if (title) printf("------ %s (%s", title, command);
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
new file mode 100644
index 0000000..d53b04a
--- /dev/null
+++ b/include/gui/GLConsumer.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GUI_CONSUMER_H
+#define ANDROID_GUI_CONSUMER_H
+
+#include <gui/BufferQueue.h>
+#include <gui/ConsumerBase.h>
+#include <gui/ISurfaceTexture.h>
+
+namespace android {
+
+class GLConsumer : public ConsumerBase {
+public:
+ GLConsumer(GLuint, bool = false, GLenum = 0, bool = false, const sp<BufferQueue>& = 0) :
+ ConsumerBase(0) {}
+ void incStrong(const void*) const {}
+ void decStrong(const void*) const {}
+ status_t updateTexImage() { return 0; }
+ void abandon() {}
+ sp<ISurfaceTexture> getBufferQueue() const { return 0; }
+ GLenum getCurrentTextureTarget() const { return 0; }
+ status_t setSynchronousMode(bool) { return 0; }
+ void getTransformMatrix(float[16]) {}
+ int64_t getTimestamp() {}
+ void setFrameAvailableListener(const wp<FrameAvailableListener>&) {}
+ sp<GraphicBuffer> getCurrentBuffer() const { return 0; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_GUI_CONSUMER_H
+
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 2288fe7..3411f0a 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -121,6 +121,8 @@
explicit Surface(const sp<ISurfaceTexture>& st);
+ Surface (sp<BufferQueue>&) {}
+
static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);
static sp<Surface> readFromParcel(const Parcel& data);
@@ -134,6 +136,7 @@
// the lock/unlock APIs must be used from the same thread
status_t lock(SurfaceInfo* info, Region* dirty = NULL);
+ int lock(ANativeWindow_Buffer*, ARect*) { return 0; }
status_t unlockAndPost();
sp<IBinder> asBinder() const;
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index dffa788..479cd3e 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -84,6 +84,7 @@
static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;
friend class Singleton<GraphicBufferAllocator>;
+ friend class BufferLiberatorThread;
GraphicBufferAllocator();
~GraphicBufferAllocator();
diff --git a/include/utils/LinearAllocator.h b/include/utils/LinearAllocator.h
new file mode 100644
index 0000000..cd2521d
--- /dev/null
+++ b/include/utils/LinearAllocator.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_LINEARALLOCATOR_H
+#define ANDROID_LINEARALLOCATOR_H
+
+#include <stddef.h>
+
+namespace android {
+
+class LinearAllocator {
+public:
+ void* alloc(size_t size) { return 0; }
+ void rewindIfLastAlloc(void* ptr, size_t allocSize) {}
+ void dumpMemoryStats(const char* prefix = "") {}
+};
+
+}; // namespace android
+
+#endif // ANDROID_LINEARALLOCATOR_H
diff --git a/libs/binder/MemoryBase.cpp b/libs/binder/MemoryBase.cpp
index 033066b..5c82330 100644
--- a/libs/binder/MemoryBase.cpp
+++ b/libs/binder/MemoryBase.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_TAG "MemoryBase"
#include <stdlib.h>
#include <stdint.h>
@@ -44,3 +45,11 @@
// ---------------------------------------------------------------------------
}; // namespace android
+
+// Backwards compatibility for libdatabase_sqlcipher (http://b/8253769).
+extern "C" void _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEEij(void*, void*, ssize_t, size_t);
+extern "C" void _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEElj(void* obj, void* h, long o, unsigned int size) {
+ _ZN7android10MemoryBaseC1ERKNS_2spINS_11IMemoryHeapEEEij(obj, h, o, size);
+ ALOGW("Using temporary compatibility workaround for usage of MemoryBase "
+ "private API. Please fix your application!");
+}
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 590946a..086e298 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -314,9 +314,8 @@
* the consumer may still have pending reads of the
* buffers in flight.
*/
- bool isOlder = mSlots[i].mFrameNumber <
- mSlots[found].mFrameNumber;
- if (found < 0 || isOlder) {
+ if ((found < 0) ||
+ mSlots[i].mFrameNumber < mSlots[found].mFrameNumber) {
found = i;
}
}
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index ff550d9..fb43410 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -90,6 +90,105 @@
ALOGD("%s", s.string());
}
+class BufferLiberatorThread : public Thread {
+public:
+
+ static void queueCaptiveBuffer(buffer_handle_t handle) {
+ size_t queueSize;
+ {
+ Mutex::Autolock lock(sMutex);
+ if (sThread == NULL) {
+ sThread = new BufferLiberatorThread;
+ sThread->run("BufferLiberator");
+ }
+
+ sThread->mQueue.push_back(handle);
+ sThread->mQueuedCondition.signal();
+ queueSize = sThread->mQueue.size();
+ }
+ }
+
+ static void waitForLiberation() {
+ Mutex::Autolock lock(sMutex);
+
+ waitForLiberationLocked();
+ }
+
+ static void maybeWaitForLiberation() {
+ Mutex::Autolock lock(sMutex);
+ if (sThread != NULL) {
+ if (sThread->mQueue.size() > 8) {
+ waitForLiberationLocked();
+ }
+ }
+ }
+
+private:
+
+ BufferLiberatorThread() {}
+
+ virtual bool threadLoop() {
+ buffer_handle_t handle;
+ { // Scope for mutex
+ Mutex::Autolock lock(sMutex);
+ while (mQueue.isEmpty()) {
+ mQueuedCondition.wait(sMutex);
+ }
+ handle = mQueue[0];
+ }
+
+ status_t err;
+ GraphicBufferAllocator& gba(GraphicBufferAllocator::get());
+ { // Scope for tracing
+ ATRACE_NAME("gralloc::free");
+ err = gba.mAllocDev->free(gba.mAllocDev, handle);
+ }
+ ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
+
+ if (err == NO_ERROR) {
+ Mutex::Autolock _l(GraphicBufferAllocator::sLock);
+ KeyedVector<buffer_handle_t, GraphicBufferAllocator::alloc_rec_t>&
+ list(GraphicBufferAllocator::sAllocList);
+ list.removeItem(handle);
+ }
+
+ { // Scope for mutex
+ Mutex::Autolock lock(sMutex);
+ mQueue.removeAt(0);
+ mFreedCondition.broadcast();
+ }
+
+ return true;
+ }
+
+ static void waitForLiberationLocked() {
+ if (sThread == NULL) {
+ return;
+ }
+
+ const nsecs_t timeout = 500 * 1000 * 1000;
+ nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ nsecs_t timeToStop = now + timeout;
+ while (!sThread->mQueue.isEmpty() && now < timeToStop) {
+ sThread->mFreedCondition.waitRelative(sMutex, timeToStop - now);
+ now = systemTime(SYSTEM_TIME_MONOTONIC);
+ }
+
+ if (!sThread->mQueue.isEmpty()) {
+ ALOGW("waitForLiberationLocked timed out");
+ }
+ }
+
+ static Mutex sMutex;
+ static sp<BufferLiberatorThread> sThread;
+ Vector<buffer_handle_t> mQueue;
+ Condition mQueuedCondition;
+ Condition mFreedCondition;
+};
+
+Mutex BufferLiberatorThread::sMutex;
+sp<BufferLiberatorThread> BufferLiberatorThread::sThread;
+
status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
int usage, buffer_handle_t* handle, int32_t* stride)
{
@@ -100,13 +199,24 @@
w = h = 1;
// we have a h/w allocator and h/w buffer is requested
- status_t err;
-
+ status_t err;
+
+ // If too many async frees are queued up then wait for some of them to
+ // complete before attempting to allocate more memory. This is exercised
+ // by the android.opengl.cts.GLSurfaceViewTest CTS test.
+ BufferLiberatorThread::maybeWaitForLiberation();
+
err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
+ if (err != NO_ERROR) {
+ ALOGW("WOW! gralloc alloc failed, waiting for pending frees!");
+ BufferLiberatorThread::waitForLiberation();
+ err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride);
+ }
+
ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
w, h, format, usage, err, strerror(-err));
-
+
if (err == NO_ERROR) {
Mutex::Autolock _l(sLock);
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
@@ -129,21 +239,11 @@
return err;
}
+
status_t GraphicBufferAllocator::free(buffer_handle_t handle)
{
- ATRACE_CALL();
- status_t err;
-
- err = mAllocDev->free(mAllocDev, handle);
-
- ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
- if (err == NO_ERROR) {
- Mutex::Autolock _l(sLock);
- KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
- list.removeItem(handle);
- }
-
- return err;
+ BufferLiberatorThread::queueCaptiveBuffer(handle);
+ return NO_ERROR;
}
// ---------------------------------------------------------------------------
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 639c4d7..1b3d6ed 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -34,16 +34,7 @@
LOCAL_CFLAGS += -fstrict-aliasing
endif
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
-
# we need to access the private Bionic header <bionic_tls.h>
-# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
-# behavior from the bionic Android.mk file
-ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 31bfcd7..d025ae8 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -23,11 +23,6 @@
LOCAL_MODULE:= libEGL
LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
LOCAL_SHARED_LIBRARIES += libdl
-# Bionic's private TLS header relies on the ARCH_ARM_HAVE_TLS_REGISTER to
-# select the appropriate TLS codepath
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
# we need to access the private Bionic header <bionic_tls.h>
LOCAL_C_INCLUDES += bionic/libc/private
@@ -49,10 +44,6 @@
LOCAL_CFLAGS += -DSYSTEMUI_PBSIZE_HACK=1
endif
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
-
ifneq ($(MAX_EGL_CACHE_ENTRY_SIZE),)
LOCAL_CFLAGS += -DMAX_EGL_CACHE_ENTRY_SIZE=$(MAX_EGL_CACHE_ENTRY_SIZE)
endif
@@ -100,19 +91,12 @@
LOCAL_SHARED_LIBRARIES += libdl
# we need to access the private Bionic header <bionic_tls.h>
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv1\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
-
include $(BUILD_SHARED_LIBRARY)
@@ -132,19 +116,12 @@
LOCAL_SHARED_LIBRARIES += libdl
# we need to access the private Bionic header <bionic_tls.h>
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv2\"
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
-
include $(BUILD_SHARED_LIBRARY)
###############################################################################
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 96e1cba..0d4bed5 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -124,6 +124,12 @@
void initEglDebugLevel() {
int propertyLevel = 0;
char value[PROPERTY_VALUE_MAX];
+
+ // check system property only on userdebug or eng builds
+ property_get("ro.debuggable", value, "0");
+ if (value[0] == '0')
+ return;
+
property_get("debug.egl.debug_proc", value, "");
if (strlen(value) > 0) {
long pid = getpid();
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 4e44941..065faf2 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -760,8 +760,8 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && cnx->egl.eglGetProcAddress) {
- found = true;
// Extensions are independent of the bound context
+ addr =
cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
#if EGL_TRACE
@@ -769,10 +769,13 @@
gHooksTrace.ext.extensions[slot] =
#endif
cnx->egl.eglGetProcAddress(procname);
+ if (addr) found = true;
}
if (found) {
+#if USE_FAST_TLS_KEY
addr = gExtensionForwarders[slot];
+#endif
sGLExtentionMap.add(name, addr);
sGLExtentionSlot++;
}
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 8dcf38d..f453176 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -37,14 +37,7 @@
#if USE_FAST_TLS_KEY
- #ifdef HAVE_ARM_TLS_REGISTER
- #define GET_TLS(reg) \
- "mrc p15, 0, " #reg ", c13, c0, 3 \n"
- #else
- #define GET_TLS(reg) \
- "mov " #reg ", #0xFFFF0FFF \n" \
- "ldr " #reg ", [" #reg ", #-15] \n"
- #endif
+ #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 55ef499..fca42ec 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -41,14 +41,7 @@
#if USE_FAST_TLS_KEY
- #ifdef HAVE_ARM_TLS_REGISTER
- #define GET_TLS(reg) \
- "mrc p15, 0, " #reg ", c13, c0, 3 \n"
- #else
- #define GET_TLS(reg) \
- "mov " #reg ", #0xFFFF0FFF \n" \
- "ldr " #reg ", [" #reg ", #-15] \n"
- #endif
+ #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index adcb60d..48fd278 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -97,14 +97,7 @@
#if USE_FAST_TLS_KEY && !CHECK_FOR_GL_ERRORS
- #ifdef HAVE_ARM_TLS_REGISTER
- #define GET_TLS(reg) \
- "mrc p15, 0, " #reg ", c13, c0, 3 \n"
- #else
- #define GET_TLS(reg) \
- "mov " #reg ", #0xFFFF0FFF \n" \
- "ldr " #reg ", [" #reg ", #-15] \n"
- #endif
+ #define GET_TLS(reg) "mrc p15, 0, " #reg ", c13, c0, 3 \n"
#define API_ENTRY(_api) __attribute__((naked)) _api
diff --git a/opengl/libs/GLES_trace/Android.mk b/opengl/libs/GLES_trace/Android.mk
index 465b6b2..9dec020 100644
--- a/opengl/libs/GLES_trace/Android.mk
+++ b/opengl/libs/GLES_trace/Android.mk
@@ -24,18 +24,9 @@
LOCAL_STATIC_LIBRARIES := libprotobuf-cpp-2.3.0-lite liblzf
LOCAL_SHARED_LIBRARIES := libcutils libutils libstlport
-ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
-
LOCAL_CFLAGS += -DLOG_TAG=\"libGLES_trace\"
# we need to access the private Bionic header <bionic_tls.h>
-# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
-# behavior from the bionic Android.mk file
-ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
- LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
-endif
LOCAL_C_INCLUDES += bionic/libc/private
LOCAL_MODULE:= libGLES_trace
diff --git a/opengl/specs/EGL_ANDROID_native_fence_sync.txt b/opengl/specs/EGL_ANDROID_native_fence_sync.txt
index 8273be4..ee05b40 100644
--- a/opengl/specs/EGL_ANDROID_native_fence_sync.txt
+++ b/opengl/specs/EGL_ANDROID_native_fence_sync.txt
@@ -100,10 +100,10 @@
EGL_SYNC_TYPE_KHR EGL_SYNC_NATIVE_FENCE_ANDROID
EGL_SYNC_STATUS_KHR EGL_UNSIGNALED_KHR
EGL_SYNC_CONDITION_KHR EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR
- EGL_SYNC_NATIVE_FENCE_FD_ANDROID EGL_NO_NATIVE_FENCE_ANDROID
+ EGL_SYNC_NATIVE_FENCE_FD_ANDROID EGL_NO_NATIVE_FENCE_FD_ANDROID
If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute is not
- EGL_NO_NATIVE_FENCE_ANDROID then the EGL_SYNC_CONDITION_KHR attribute is
+ EGL_NO_NATIVE_FENCE_FD_ANDROID then the EGL_SYNC_CONDITION_KHR attribute is
set to EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
attribute is set to reflect the signal status of the native fence object.
Additionally, the EGL implementation assumes ownership of the file
@@ -114,7 +114,7 @@
"When a fence sync object is created or when an EGL native fence sync
object is created with the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute set
- to EGL_NO_NATIVE_FENCE_ANDROID, eglCreateSyncKHR also inserts a fence
+ to EGL_NO_NATIVE_FENCE_FD_ANDROID, eglCreateSyncKHR also inserts a fence
command into the command stream of the bound client API's current context
(i.e., the context returned by eglGetCurrentContext), and associates it
with the newly created sync object.
@@ -157,8 +157,9 @@
empty (containing only EGL_NONE), EGL_NO_SYNC_KHR is returned and an
EGL_BAD_ATTRIBUTE error is generated.
* If <type> is EGL_SYNC_NATIVE_FENCE_ANDROID and <attrib_list> contains
- an attribute other than EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_SYNC_KHR is
- returned and an EGL_BAD_ATTRIBUTE error is generated.
+ an attribute other than EGL_SYNC_NATIVE_FENCE_FD_ANDROID,
+ EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is
+ generated.
* If <type> is not a supported type of sync object,
EGL_NO_SYNC_KHR is returned and an EGL_BAD_ATTRIBUTE error is
generated.
@@ -193,8 +194,8 @@
"If no errors are generated, EGL_TRUE is returned, and <sync> will no
longer be the handle of a valid sync object. Additionally, if <sync> is an
EGL native fence sync object and the EGL_SYNC_NATIVE_FENCE_FD_ANDROID
- attribute is not EGL_NO_NATIVE_FENCE_ANDROID then that file descriptor is
- closed."
+ attribute is not EGL_NO_NATIVE_FENCE_FD_ANDROID then that file descriptor
+ is closed."
Add the following after the last paragraph of Section 3.8.1 (Sync
Objects), added by KHR_fence_sync
@@ -213,11 +214,11 @@
------
* If <sync> is not a valid sync object for <dpy>,
- EGL_NO_NATIVE_FENCE_ANDROID is returned and an EGL_BAD_PARAMETER
+ EGL_NO_NATIVE_FENCE_FD_ANDROID is returned and an EGL_BAD_PARAMETER
error is generated.
* If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute of <sync> is
- EGL_NO_NATIVE_FENCE_ANDROID, EGL_NO_NATIVE_FENCE_ANDROID is returned
- and an EGL_BAD_PARAMETER error is generated.
+ EGL_NO_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID is
+ returned and an EGL_BAD_PARAMETER error is generated.
* If <dpy> does not match the display passed to eglCreateSyncKHR
when <sync> was created, the behaviour is undefined."
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 8d92bd3..068fdcd 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -793,7 +793,9 @@
virtual void setAcquireFenceFd(int fenceFd) {
getLayer()->acquireFenceFd = fenceFd;
}
-
+ virtual void setPerFrameDefaultState() {
+ //getLayer()->compositionType = HWC_FRAMEBUFFER;
+ }
virtual void setDefaultState() {
getLayer()->compositionType = HWC_FRAMEBUFFER;
getLayer()->hints = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a78ffac..7c67407 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -141,6 +141,7 @@
virtual int32_t getCompositionType() const = 0;
virtual uint32_t getHints() const = 0;
virtual int getAndResetReleaseFenceFd() = 0;
+ virtual void setPerFrameDefaultState() = 0;
virtual void setDefaultState() = 0;
virtual void setSkip(bool skip) = 0;
virtual void setBlending(uint32_t blending) = 0;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 064f689..7edbdc5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -110,7 +110,8 @@
mSurfaceTexture->setDefaultMaxBufferCount(3);
#endif
- updateTransformHint();
+ const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
+ updateTransformHint(hw);
}
Layer::~Layer()
@@ -767,15 +768,12 @@
return usage;
}
-void Layer::updateTransformHint() const {
+void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
uint32_t orientation = 0;
if (!mFlinger->mDebugDisableTransformHint) {
- // The transform hint is used to improve performance on the main
- // display -- we can only have a single transform hint, it cannot
+ // The transform hint is used to improve performance, but we can
+ // only have a single transform hint, it cannot
// apply to all displays.
- // This is why we use the default display here. This is not an
- // oversight.
- sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
const Transform& planeTransform(hw->getTransform());
orientation = planeTransform.getOrientation();
if (orientation & Transform::ROT_INVALID) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6f75d8c..c5eb26b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -91,8 +91,8 @@
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
// Updates the transform hint in our SurfaceTexture to match
- // the current orientation of the default display device.
- virtual void updateTransformHint() const;
+ // the current orientation of the display device.
+ virtual void updateTransformHint(const sp<const DisplayDevice>& hw) const;
protected:
virtual void onFirstRef();
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index db4ef87..9b03c74 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -300,6 +300,7 @@
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.
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 00c4ffe..4d5a5b0 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -246,7 +246,7 @@
* Updates the SurfaceTexture's transform hint, for layers that have
* a SurfaceTexture.
*/
- virtual void updateTransformHint() const { }
+ 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;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3097965..9afa4c1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1076,7 +1076,7 @@
if (transactionFlags & eTraversalNeeded) {
for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer = currentLayers[i];
+ const sp<LayerBase>& layer(currentLayers[i]);
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) continue;
@@ -1149,18 +1149,6 @@
disp->setProjection(state.orientation,
state.viewport, state.frame);
}
-
- // Walk through all the layers in currentLayers,
- // and update their transform hint.
- //
- // TODO: we could be much more clever about which
- // layers we touch and how often we do these updates
- // (e.g. only touch the layers associated with this
- // display, and only on a rotation).
- for (size_t i = 0; i < count; i++) {
- const sp<LayerBase>& layerBase = currentLayers[i];
- layerBase->updateTransformHint();
- }
}
}
}
@@ -1209,6 +1197,61 @@
}
}
+ if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
+ // The transform hint might have changed for some layers
+ // (either because a display has changed, or because a layer
+ // as changed).
+ //
+ // Walk through all the layers in currentLayers,
+ // and update their transform hint.
+ //
+ // If a layer is visible only on a single display, then that
+ // display is used to calculate the hint, otherwise we use the
+ // default display.
+ //
+ // NOTE: we do this here, rather than in rebuildLayerStacks() so that
+ // the hint is set before we acquire a buffer from the surface texture.
+ //
+ // NOTE: layer transactions have taken place already, so we use their
+ // drawing state. However, SurfaceFlinger's own transaction has not
+ // happened yet, so we must use the current state layer list
+ // (soon to become the drawing state list).
+ //
+ sp<const DisplayDevice> disp;
+ uint32_t currentlayerStack = 0;
+ for (size_t i=0; i<count; i++) {
+ // 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;
+ if (i==0 || currentlayerStack != layerStack) {
+ currentlayerStack = layerStack;
+ // figure out if this layerstack is mirrored
+ // (more than one display) if so, pick the default display,
+ // if not, pick the only display it's on.
+ disp.clear();
+ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ sp<const DisplayDevice> hw(mDisplays[dpy]);
+ if (hw->getLayerStack() == currentlayerStack) {
+ if (disp == NULL) {
+ disp = hw;
+ } else {
+ disp = getDefaultDisplayDevice();
+ break;
+ }
+ }
+ }
+ }
+ if (disp != NULL) {
+ // presumably this means this layer is using a layerStack
+ // that is not visible on any display
+ layerBase->updateTransformHint(disp);
+ }
+ }
+ }
+
+
/*
* Perform our own transaction if needed
*/