Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_frameworks_native into replicant-6.0
This commit is contained in:
commit
d3ad4f1e64
25
build/phone-xxhdpi-3072-dalvik-heap.mk
Normal file
25
build/phone-xxhdpi-3072-dalvik-heap.mk
Normal file
@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (C) 2016 The CyanogenMod 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.
|
||||
#
|
||||
|
||||
# Provides overrides to configure the Dalvik heap for a 3G phone
|
||||
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
dalvik.vm.heapstartsize=8m \
|
||||
dalvik.vm.heapgrowthlimit=288m \
|
||||
dalvik.vm.heapsize=768m \
|
||||
dalvik.vm.heaptargetutilization=0.75 \
|
||||
dalvik.vm.heapminfree=512k \
|
||||
dalvik.vm.heapmaxfree=8m
|
30
build/phone-xxhdpi-3072-hwui-memory.mk
Normal file
30
build/phone-xxhdpi-3072-hwui-memory.mk
Normal file
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (C) 2016 The CyanogenMod 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.
|
||||
#
|
||||
|
||||
# Provides overrides to configure the HWUI memory limits
|
||||
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
ro.hwui.texture_cache_size=72 \
|
||||
ro.hwui.layer_cache_size=48 \
|
||||
ro.hwui.path_cache_size=32 \
|
||||
ro.hwui.gradient_cache_size=1 \
|
||||
ro.hwui.drop_shadow_cache_size=6 \
|
||||
ro.hwui.r_buffer_cache_size=8 \
|
||||
ro.hwui.texture_cache_flushrate=0.4 \
|
||||
ro.hwui.text_small_cache_width=1024 \
|
||||
ro.hwui.text_small_cache_height=1024 \
|
||||
ro.hwui.text_large_cache_width=2048 \
|
||||
ro.hwui.text_large_cache_height=1024
|
@ -18,8 +18,8 @@
|
||||
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
dalvik.vm.heapstartsize=8m \
|
||||
dalvik.vm.heapgrowthlimit=256m \
|
||||
dalvik.vm.heapsize=512m \
|
||||
dalvik.vm.heapgrowthlimit=288m \
|
||||
dalvik.vm.heapsize=768m \
|
||||
dalvik.vm.heaptargetutilization=0.75 \
|
||||
dalvik.vm.heapminfree=2m \
|
||||
dalvik.vm.heapmaxfree=8m
|
||||
|
25
build/phone-xxxhdpi-4096-dalvik-heap.mk
Normal file
25
build/phone-xxxhdpi-4096-dalvik-heap.mk
Normal file
@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (C) 2016 The CyanogenMod 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.
|
||||
#
|
||||
|
||||
# Provides overrides to configure the Dalvik heap for a 4G phone
|
||||
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
dalvik.vm.heapstartsize=8m \
|
||||
dalvik.vm.heapgrowthlimit=384m \
|
||||
dalvik.vm.heapsize=1024m \
|
||||
dalvik.vm.heaptargetutilization=0.75 \
|
||||
dalvik.vm.heapminfree=4m \
|
||||
dalvik.vm.heapmaxfree=16m
|
30
build/phone-xxxhdpi-4096-hwui-memory.mk
Normal file
30
build/phone-xxxhdpi-4096-hwui-memory.mk
Normal file
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (C) 2015 The CyanogenMod 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.
|
||||
#
|
||||
|
||||
# Provides overrides to configure the HWUI memory limits
|
||||
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
ro.hwui.texture_cache_size=72 \
|
||||
ro.hwui.layer_cache_size=48 \
|
||||
ro.hwui.r_buffer_cache_size=8 \
|
||||
ro.hwui.path_cache_size=32 \
|
||||
ro.hwui.gradient_cache_size=1 \
|
||||
ro.hwui.drop_shadow_cache_size=6 \
|
||||
ro.hwui.texture_cache_flushrate=0.4 \
|
||||
ro.hwui.text_small_cache_width=1024 \
|
||||
ro.hwui.text_small_cache_height=1024 \
|
||||
ro.hwui.text_large_cache_width=2048 \
|
||||
ro.hwui.text_large_cache_height=1024
|
@ -272,7 +272,9 @@ static void dumpstate() {
|
||||
char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
|
||||
char network[PROPERTY_VALUE_MAX], date[80];
|
||||
char build_type[PROPERTY_VALUE_MAX];
|
||||
char cm_version[PROPERTY_VALUE_MAX];
|
||||
|
||||
property_get("ro.cm.version", cm_version, "(unknown)");
|
||||
property_get("ro.build.display.id", build, "(unknown)");
|
||||
property_get("ro.build.fingerprint", fingerprint, "(unknown)");
|
||||
property_get("ro.build.type", build_type, "(unknown)");
|
||||
@ -286,6 +288,7 @@ static void dumpstate() {
|
||||
printf("========================================================\n");
|
||||
|
||||
printf("\n");
|
||||
printf("CM Version: %s\n", cm_version);
|
||||
printf("Build: %s\n", build);
|
||||
printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
|
||||
printf("Bootloader: %s\n", bootloader);
|
||||
@ -302,7 +305,7 @@ static void dumpstate() {
|
||||
dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
|
||||
dump_file("MEMORY INFO", "/proc/meminfo");
|
||||
run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
|
||||
run_command("PROCRANK", 20, "procrank", NULL);
|
||||
run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
|
||||
dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
|
||||
dump_file("VMALLOC INFO", "/proc/vmallocinfo");
|
||||
dump_file("SLAB INFO", "/proc/slabinfo");
|
||||
|
@ -18,7 +18,7 @@ LOCAL_MODULE_TAGS := optional
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SHARED_LIBRARIES := liblog libselinux
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libselinux
|
||||
LOCAL_SRC_FILES := service_manager.c binder.c
|
||||
LOCAL_CFLAGS += $(svc_c_flags)
|
||||
LOCAL_MODULE := servicemanager
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cutils/multiuser.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#include <selinux/android.h>
|
||||
@ -107,9 +109,14 @@ static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char
|
||||
return allowed;
|
||||
}
|
||||
|
||||
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
|
||||
static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
|
||||
{
|
||||
const char *perm = "add";
|
||||
|
||||
if (multiuser_get_app_id(uid) >= AID_APP) {
|
||||
return 0; /* Don't allow apps to register services */
|
||||
}
|
||||
|
||||
return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -204,7 +211,7 @@ int do_add_service(struct binder_state *bs,
|
||||
if (!handle || (len == 0) || (len > 127))
|
||||
return -1;
|
||||
|
||||
if (!svc_can_register(s, len, spid)) {
|
||||
if (!svc_can_register(s, len, spid, uid)) {
|
||||
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
|
||||
str8(s, len), handle, uid);
|
||||
return -1;
|
||||
|
@ -45,6 +45,19 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
/**
|
||||
* This flag indicates that the window that received this motion event is partly
|
||||
* or wholly obscured by another visible window above it. This flag is set to true
|
||||
* even if the event did not directly pass through the obscured area.
|
||||
* A security sensitive application can check this flag to identify situations in which
|
||||
* a malicious application may have covered up part of its content for the purpose
|
||||
* of misleading the user or hijacking touches. An appropriate response might be
|
||||
* to drop the suspect touches or to take additional precautions to confirm the user's
|
||||
* actual intent.
|
||||
*/
|
||||
AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2,
|
||||
|
||||
/* Motion event is inconsistent with previously sent motion events. */
|
||||
AMOTION_EVENT_FLAG_TAINTED = 0x80000000,
|
||||
};
|
||||
|
@ -25,6 +25,7 @@ namespace android {
|
||||
|
||||
class FrameStats : public LightFlattenable<FrameStats> {
|
||||
public:
|
||||
FrameStats() : refreshPeriodNano(0) {};
|
||||
|
||||
/*
|
||||
* Approximate refresh time, in nanoseconds.
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <binder/IMemory.h>
|
||||
#include <cutils/log.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Atomic.h>
|
||||
@ -191,15 +192,26 @@ sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const
|
||||
if (heap != 0) {
|
||||
mHeap = interface_cast<IMemoryHeap>(heap);
|
||||
if (mHeap != 0) {
|
||||
size_t heapSize = mHeap->getSize();
|
||||
if (s <= heapSize
|
||||
&& o >= 0
|
||||
&& (static_cast<size_t>(o) <= heapSize - s)) {
|
||||
mOffset = o;
|
||||
mSize = s;
|
||||
} else {
|
||||
// Hm.
|
||||
android_errorWriteWithInfoLog(0x534e4554,
|
||||
"26877992", -1, NULL, 0);
|
||||
mOffset = 0;
|
||||
mSize = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (offset) *offset = mOffset;
|
||||
if (size) *size = mSize;
|
||||
return mHeap;
|
||||
return (mSize > 0) ? mHeap : 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -1083,8 +1083,16 @@ status_t IPCThreadState::executeCommand(int32_t cmd)
|
||||
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
|
||||
}
|
||||
if (tr.target.ptr) {
|
||||
sp<BBinder> b((BBinder*)tr.cookie);
|
||||
error = b->transact(tr.code, buffer, &reply, tr.flags);
|
||||
// We only have a weak reference on the target object, so we must first try to
|
||||
// safely acquire a strong reference before doing anything else with it.
|
||||
if (reinterpret_cast<RefBase::weakref_type*>(
|
||||
tr.target.ptr)->attemptIncStrong(this)) {
|
||||
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
|
||||
&reply, tr.flags);
|
||||
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
|
||||
} else {
|
||||
error = UNKNOWN_TRANSACTION;
|
||||
}
|
||||
|
||||
} else {
|
||||
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
|
||||
|
@ -18,6 +18,8 @@
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <binder/Parcel.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/Binder.h>
|
||||
@ -42,6 +44,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX ((int32_t)(2147483647))
|
||||
@ -95,6 +100,32 @@ enum {
|
||||
BLOB_ASHMEM_MUTABLE = 2,
|
||||
};
|
||||
|
||||
static dev_t ashmem_rdev()
|
||||
{
|
||||
static dev_t __ashmem_rdev;
|
||||
static pthread_mutex_t __ashmem_rdev_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
pthread_mutex_lock(&__ashmem_rdev_lock);
|
||||
|
||||
dev_t rdev = __ashmem_rdev;
|
||||
if (!rdev) {
|
||||
int fd = TEMP_FAILURE_RETRY(open("/dev/ashmem", O_RDONLY));
|
||||
if (fd >= 0) {
|
||||
struct stat st;
|
||||
|
||||
int ret = TEMP_FAILURE_RETRY(fstat(fd, &st));
|
||||
close(fd);
|
||||
if ((ret >= 0) && S_ISCHR(st.st_mode)) {
|
||||
rdev = __ashmem_rdev = st.st_rdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&__ashmem_rdev_lock);
|
||||
|
||||
return rdev;
|
||||
}
|
||||
|
||||
void acquire_object(const sp<ProcessState>& proc,
|
||||
const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
|
||||
{
|
||||
@ -123,8 +154,10 @@ void acquire_object(const sp<ProcessState>& proc,
|
||||
return;
|
||||
}
|
||||
case BINDER_TYPE_FD: {
|
||||
if (obj.cookie != 0) {
|
||||
if (outAshmemSize != NULL) {
|
||||
if ((obj.cookie != 0) && (outAshmemSize != NULL)) {
|
||||
struct stat st;
|
||||
int ret = fstat(obj.handle, &st);
|
||||
if (!ret && S_ISCHR(st.st_mode) && (st.st_rdev == ashmem_rdev())) {
|
||||
// If we own an ashmem fd, keep track of how much memory it refers to.
|
||||
int size = ashmem_get_size_region(obj.handle);
|
||||
if (size > 0) {
|
||||
@ -173,15 +206,18 @@ static void release_object(const sp<ProcessState>& proc,
|
||||
return;
|
||||
}
|
||||
case BINDER_TYPE_FD: {
|
||||
if (obj.cookie != 0) { // owned
|
||||
if (outAshmemSize != NULL) {
|
||||
if (obj.cookie != 0) {
|
||||
struct stat st;
|
||||
int ret = fstat(obj.handle, &st);
|
||||
if (!ret && S_ISCHR(st.st_mode) && (st.st_rdev == ashmem_rdev())) {
|
||||
int size = ashmem_get_size_region(obj.handle);
|
||||
if (size > 0) {
|
||||
*outAshmemSize -= size;
|
||||
}
|
||||
|
||||
close(obj.handle);
|
||||
}
|
||||
}
|
||||
close(obj.handle);
|
||||
#ifdef DISABLE_ASHMEM_TRACKING
|
||||
} else if (obj.cookie != 0) {
|
||||
close(obj.handle);
|
||||
@ -1389,7 +1425,13 @@ native_handle* Parcel::readNativeHandle() const
|
||||
|
||||
for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
|
||||
h->data[i] = dup(readFileDescriptor());
|
||||
if (h->data[i] < 0) err = BAD_VALUE;
|
||||
if (h->data[i] < 0) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
close(h->data[j]);
|
||||
}
|
||||
native_handle_delete(h);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
err = read(h->data + numFds, sizeof(int)*numInts);
|
||||
if (err != NO_ERROR) {
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include <gui/IConsumerListener.h>
|
||||
#include <gui/IProducerListener.h>
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/PermissionCache.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
|
||||
@ -572,7 +576,18 @@ sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
|
||||
}
|
||||
|
||||
void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
|
||||
const IPCThreadState* ipc = IPCThreadState::self();
|
||||
const pid_t pid = ipc->getCallingPid();
|
||||
const uid_t uid = ipc->getCallingUid();
|
||||
if ((uid != AID_SHELL)
|
||||
&& !PermissionCache::checkPermission(String16(
|
||||
"android.permission.DUMP"), pid, uid)) {
|
||||
result.appendFormat("Permission Denial: can't dump BufferQueueConsumer "
|
||||
"from pid=%d, uid=%d\n", pid, uid);
|
||||
android_errorWriteWithInfoLog(0x534e4554, "27046057", uid, NULL, 0);
|
||||
} else {
|
||||
mCore->dump(result, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
@ -349,7 +349,7 @@ status_t BnGraphicBufferConsumer::onTransact(
|
||||
}
|
||||
case GET_RELEASED_BUFFERS: {
|
||||
CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
|
||||
uint64_t slotMask;
|
||||
uint64_t slotMask = 0;
|
||||
status_t result = getReleasedBuffers(&slotMask);
|
||||
reply->writeInt64(static_cast<int64_t>(slotMask));
|
||||
reply->writeInt32(result);
|
||||
|
@ -435,6 +435,7 @@ status_t BnGraphicBufferProducer::onTransact(
|
||||
QueueBufferOutput* const output =
|
||||
reinterpret_cast<QueueBufferOutput *>(
|
||||
reply->writeInplace(sizeof(QueueBufferOutput)));
|
||||
memset(output, 0, sizeof(QueueBufferOutput));
|
||||
status_t res = connect(listener, api, producerControlledByApp, output);
|
||||
reply->writeInt32(res);
|
||||
return NO_ERROR;
|
||||
|
@ -795,6 +795,11 @@ status_t Region::unflatten(void const* buffer, size_t size) {
|
||||
return NO_MEMORY;
|
||||
}
|
||||
|
||||
if (numRects > (UINT32_MAX / sizeof(Rect))) {
|
||||
android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, NULL, 0);
|
||||
return NO_MEMORY;
|
||||
}
|
||||
|
||||
Region result;
|
||||
result.mStorage.clear();
|
||||
for (size_t r = 0; r < numRects; ++r) {
|
||||
|
@ -65,6 +65,10 @@ ifneq ($(MAX_EGL_CACHE_SIZE),)
|
||||
LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD_USE_BGRA_8888), true)
|
||||
LOCAL_CFLAGS += -DUSE_BGRA_8888
|
||||
endif
|
||||
|
||||
LOCAL_REQUIRED_MODULES := $(egl.cfg_config_module)
|
||||
egl.cfg_config_module :=
|
||||
|
||||
|
@ -1225,6 +1225,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
|
||||
int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
|
||||
if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
|
||||
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
|
||||
} else if (isWindowObscuredLocked(windowHandle)) {
|
||||
outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
|
||||
}
|
||||
|
||||
mTempTouchState.addOrUpdateWindow(
|
||||
@ -1262,6 +1264,8 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
|
||||
}
|
||||
if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
|
||||
targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
|
||||
} else if (isWindowObscuredLocked(newTouchedWindowHandle)) {
|
||||
targetFlags |= InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
|
||||
}
|
||||
|
||||
// Update hover state.
|
||||
@ -1437,6 +1441,7 @@ int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
|
||||
== InputWindowInfo::TYPE_WALLPAPER) {
|
||||
mTempTouchState.addOrUpdateWindow(windowHandle,
|
||||
InputTarget::FLAG_WINDOW_IS_OBSCURED
|
||||
| InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED
|
||||
| InputTarget::FLAG_DISPATCH_AS_IS,
|
||||
BitSet32(0));
|
||||
}
|
||||
@ -1631,6 +1636,27 @@ bool InputDispatcher::isWindowObscuredAtPointLocked(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool InputDispatcher::isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const {
|
||||
int32_t displayId = windowHandle->getInfo()->displayId;
|
||||
const InputWindowInfo* windowInfo = windowHandle->getInfo();
|
||||
size_t numWindows = mWindowHandles.size();
|
||||
for (size_t i = 0; i < numWindows; i++) {
|
||||
sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
|
||||
if (otherHandle == windowHandle) {
|
||||
break;
|
||||
}
|
||||
|
||||
const InputWindowInfo* otherInfo = otherHandle->getInfo();
|
||||
if (otherInfo->displayId == displayId
|
||||
&& otherInfo->visible && !otherInfo->isTrustedOverlay()
|
||||
&& otherInfo->overlaps(windowInfo)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String8 InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
|
||||
const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
|
||||
const char* targetType) {
|
||||
@ -1905,6 +1931,9 @@ void InputDispatcher::enqueueDispatchEntryLocked(
|
||||
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
|
||||
dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
|
||||
}
|
||||
if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_PARTIALLY_OBSCURED) {
|
||||
dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
|
||||
}
|
||||
|
||||
if (!connection->inputState.trackMotion(motionEntry,
|
||||
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
|
||||
|
@ -89,7 +89,7 @@ struct InputTarget {
|
||||
/* This flag indicates that the event is being delivered to a foreground application. */
|
||||
FLAG_FOREGROUND = 1 << 0,
|
||||
|
||||
/* This flag indicates that the target of a MotionEvent is partly or wholly
|
||||
/* This flag indicates that the MotionEvent falls within the area of the target
|
||||
* obscured by another visible window above it. The motion event should be
|
||||
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
|
||||
FLAG_WINDOW_IS_OBSCURED = 1 << 1,
|
||||
@ -139,6 +139,12 @@ struct InputTarget {
|
||||
| FLAG_DISPATCH_AS_HOVER_EXIT
|
||||
| FLAG_DISPATCH_AS_SLIPPERY_EXIT
|
||||
| FLAG_DISPATCH_AS_SLIPPERY_ENTER,
|
||||
|
||||
/* This flag indicates that the target of a MotionEvent is partly or wholly
|
||||
* obscured by another visible window above it. The motion event should be
|
||||
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
|
||||
FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
|
||||
|
||||
};
|
||||
|
||||
// The input channel to be targeted.
|
||||
@ -1048,6 +1054,7 @@ private:
|
||||
const InjectionState* injectionState);
|
||||
bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
|
||||
int32_t x, int32_t y) const;
|
||||
bool isWindowObscuredLocked(const sp<InputWindowHandle>& windowHandle) const;
|
||||
String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
|
||||
const sp<InputWindowHandle>& windowHandle);
|
||||
|
||||
|
@ -6167,7 +6167,8 @@ nsecs_t TouchInputMapper::mLastStylusTime = 0;
|
||||
|
||||
bool TouchInputMapper::rejectPalm(nsecs_t when) {
|
||||
return (when - mLastStylusTime < mConfig.stylusPalmRejectionTime) &&
|
||||
mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS;
|
||||
mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS &&
|
||||
mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_ERASER;
|
||||
}
|
||||
|
||||
void TouchInputMapper::cancelTouch(nsecs_t when) {
|
||||
|
@ -36,14 +36,16 @@ bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
|
||||
}
|
||||
|
||||
bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
|
||||
return x >= frameLeft && x <= frameRight
|
||||
&& y >= frameTop && y <= frameBottom;
|
||||
return x >= frameLeft && x < frameRight
|
||||
&& y >= frameTop && y < frameBottom;
|
||||
}
|
||||
|
||||
bool InputWindowInfo::isTrustedOverlay() const {
|
||||
return layoutParamsType == TYPE_INPUT_METHOD
|
||||
|| layoutParamsType == TYPE_INPUT_METHOD_DIALOG
|
||||
|| layoutParamsType == TYPE_MAGNIFICATION_OVERLAY
|
||||
|| layoutParamsType == TYPE_STATUS_BAR
|
||||
|| layoutParamsType == TYPE_NAVIGATION_BAR
|
||||
|| layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
|
||||
}
|
||||
|
||||
@ -51,6 +53,11 @@ bool InputWindowInfo::supportsSplitTouch() const {
|
||||
return layoutParamsFlags & FLAG_SPLIT_TOUCH;
|
||||
}
|
||||
|
||||
bool InputWindowInfo::overlaps(const InputWindowInfo* other) const {
|
||||
return frameLeft < other->frameRight && frameRight > other->frameLeft
|
||||
&& frameTop < other->frameBottom && frameBottom > other->frameTop;
|
||||
}
|
||||
|
||||
|
||||
// --- InputWindowHandle ---
|
||||
|
||||
|
@ -146,6 +146,8 @@ struct InputWindowInfo {
|
||||
bool isTrustedOverlay() const;
|
||||
|
||||
bool supportsSplitTouch() const;
|
||||
|
||||
bool overlaps(const InputWindowInfo* other) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -359,6 +359,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
|
||||
result.appendFormat("non-wakeUp | ");
|
||||
}
|
||||
|
||||
result.appendFormat("%.4f mA | ", s.getPowerUsage());
|
||||
|
||||
int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
|
||||
if (bufIndex >= 0) {
|
||||
const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex);
|
||||
@ -1118,7 +1120,7 @@ bool SensorService::canAccessSensor(const Sensor& sensor, const char* operation,
|
||||
AppOpsManager appOps;
|
||||
if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName)
|
||||
!= AppOpsManager::MODE_ALLOWED) {
|
||||
ALOGE("%s a sensor (%s) without enabled required app op: %D",
|
||||
ALOGE("%s a sensor (%s) without enabled required app op: %d",
|
||||
operation, sensor.getName().string(), opCode);
|
||||
return false;
|
||||
}
|
||||
|
@ -95,6 +95,10 @@ else
|
||||
LOCAL_CFLAGS += -DMAX_VIRTUAL_DISPLAY_DIMENSION=0
|
||||
endif
|
||||
|
||||
ifeq ($(BOARD_USE_BGRA_8888),true)
|
||||
LOCAL_CFLAGS += -DUSE_BGRA_8888
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
|
||||
LOCAL_CFLAGS += -std=c++11
|
||||
|
||||
@ -116,7 +120,11 @@ ifeq ($(TARGET_USES_QCOM_BSP), true)
|
||||
LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libgralloc
|
||||
LOCAL_C_INCLUDES += $(call project-path-for,qcom-display)/libqdutils
|
||||
LOCAL_SHARED_LIBRARIES += libqdutils
|
||||
LOCAL_SHARED_LIBRARIES += libqdMetaData
|
||||
LOCAL_CFLAGS += -DQTI_BSP
|
||||
ifeq ($(call is-board-platform-in-list,msm8996),true)
|
||||
LOCAL_CFLAGS += -DSDM_TARGET
|
||||
endif
|
||||
LOCAL_SRC_FILES += \
|
||||
ExSurfaceFlinger/ExLayer.cpp \
|
||||
ExSurfaceFlinger/ExSurfaceFlinger.cpp \
|
||||
@ -124,10 +132,22 @@ ifeq ($(TARGET_USES_QCOM_BSP), true)
|
||||
ExSurfaceFlinger/ExHWComposer.cpp
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_HAVE_UI_BLUR),true)
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/ui
|
||||
LOCAL_SHARED_LIBRARIES += libuiblur
|
||||
LOCAL_CFLAGS += -DUI_BLUR
|
||||
ifeq ($(BOARD_USES_HWC_SERVICES), true)
|
||||
LOCAL_CFLAGS += -DUSES_HWC_SERVICES
|
||||
LOCAL_SHARED_LIBRARIES += libExynosHWCService
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/$(TARGET_BOARD_PLATFORM)/libhwcService \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/$(TARGET_BOARD_PLATFORM)/include \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/$(TARGET_SOC)/include \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/$(TARGET_SOC)/libhwcmodule \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/exynos/libhwc \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/exynos/include \
|
||||
$(TOP)/hardware/samsung_slsi-$(TARGET_SLSI_VARIANT)/exynos/libexynosutils \
|
||||
$(TOP)/system/core/libsync/include
|
||||
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := \
|
||||
$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
endif
|
||||
|
||||
LOCAL_MODULE := libsurfaceflinger
|
||||
|
51
services/surfaceflinger/CleanSpec.mk
Normal file
51
services/surfaceflinger/CleanSpec.mk
Normal file
@ -0,0 +1,51 @@
|
||||
# Copyright (C) 2016 The CyanogenMod 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.
|
||||
#
|
||||
|
||||
# If you don't need to do a full clean build but would like to touch
|
||||
# a file or delete some intermediate files, add a clean step to the end
|
||||
# of the list. These steps will only be run once, if they haven't been
|
||||
# run before.
|
||||
#
|
||||
# E.g.:
|
||||
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
|
||||
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
|
||||
#
|
||||
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
|
||||
# files that are missing or have been moved.
|
||||
#
|
||||
# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
|
||||
# Use $(OUT_DIR) to refer to the "out" directory.
|
||||
#
|
||||
# If you need to re-do something that's already mentioned, just copy
|
||||
# the command and add it to the bottom of the list. E.g., if a change
|
||||
# that you made last week required touching a file and a change you
|
||||
# made today requires touching the same file, just copy the old
|
||||
# touch step and add it to the end of the list.
|
||||
#
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
|
||||
# For example:
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
|
||||
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
|
||||
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
|
||||
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libsurfaceflinger_intermediates)
|
||||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libsurfaceflinger_ddmconnection_intermediates)
|
@ -57,15 +57,17 @@ public:
|
||||
mStop(false),
|
||||
mPeriod(0),
|
||||
mPhase(0),
|
||||
mReferenceTime(0),
|
||||
mWakeupLatency(0) {
|
||||
}
|
||||
|
||||
virtual ~DispSyncThread() {}
|
||||
|
||||
void updateModel(nsecs_t period, nsecs_t phase) {
|
||||
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
mPeriod = period;
|
||||
mPhase = phase;
|
||||
mReferenceTime = referenceTime;
|
||||
mCond.signal();
|
||||
}
|
||||
|
||||
@ -247,7 +249,7 @@ private:
|
||||
ref = lastEventTime;
|
||||
}
|
||||
|
||||
nsecs_t phase = mPhase + listener.mPhase;
|
||||
nsecs_t phase = mReferenceTime + mPhase + listener.mPhase;
|
||||
nsecs_t t = (((ref - phase) / mPeriod) + 1) * mPeriod + phase;
|
||||
|
||||
if (t - listener.mLastEventTime < mPeriod / 2) {
|
||||
@ -267,6 +269,7 @@ private:
|
||||
|
||||
nsecs_t mPeriod;
|
||||
nsecs_t mPhase;
|
||||
nsecs_t mReferenceTime;
|
||||
nsecs_t mWakeupLatency;
|
||||
|
||||
Vector<EventListener> mEventListeners;
|
||||
@ -315,6 +318,9 @@ DispSync::~DispSync() {}
|
||||
void DispSync::reset() {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
mPhase = 0;
|
||||
mReferenceTime = 0;
|
||||
mModelUpdated = false;
|
||||
mNumResyncSamples = 0;
|
||||
mFirstResyncSample = 0;
|
||||
mNumResyncSamplesSincePresent = 0;
|
||||
@ -342,12 +348,13 @@ bool DispSync::addPresentFence(const sp<Fence>& fence) {
|
||||
|
||||
updateErrorLocked();
|
||||
|
||||
return mPeriod == 0 || mError > kErrorThreshold;
|
||||
return !mModelUpdated || mError > kErrorThreshold;
|
||||
}
|
||||
|
||||
void DispSync::beginResync() {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
mModelUpdated = false;
|
||||
mNumResyncSamples = 0;
|
||||
}
|
||||
|
||||
@ -356,6 +363,10 @@ bool DispSync::addResyncSample(nsecs_t timestamp) {
|
||||
|
||||
size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
|
||||
mResyncSamples[idx] = timestamp;
|
||||
if (mNumResyncSamples == 0) {
|
||||
mPhase = 0;
|
||||
mReferenceTime = timestamp;
|
||||
}
|
||||
|
||||
if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
|
||||
mNumResyncSamples++;
|
||||
@ -378,7 +389,7 @@ bool DispSync::addResyncSample(nsecs_t timestamp) {
|
||||
return mThread->hasAnyEventListeners();
|
||||
}
|
||||
|
||||
return mPeriod == 0 || mError > kErrorThreshold;
|
||||
return !mModelUpdated || mError > kErrorThreshold;
|
||||
}
|
||||
|
||||
void DispSync::endResync() {
|
||||
@ -407,7 +418,8 @@ void DispSync::setPeriod(nsecs_t period) {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
mPeriod = period;
|
||||
mPhase = 0;
|
||||
mThread->updateModel(mPeriod, mPhase);
|
||||
mReferenceTime = 0;
|
||||
mThread->updateModel(mPeriod, mPhase, mReferenceTime);
|
||||
}
|
||||
|
||||
nsecs_t DispSync::getPeriod() {
|
||||
@ -432,7 +444,7 @@ void DispSync::updateModelLocked() {
|
||||
double scale = 2.0 * M_PI / double(mPeriod);
|
||||
for (size_t i = 0; i < mNumResyncSamples; i++) {
|
||||
size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
|
||||
nsecs_t sample = mResyncSamples[idx];
|
||||
nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
|
||||
double samplePhase = double(sample % mPeriod) * scale;
|
||||
sampleAvgX += cos(samplePhase);
|
||||
sampleAvgY += sin(samplePhase);
|
||||
@ -455,12 +467,13 @@ void DispSync::updateModelLocked() {
|
||||
// Artificially inflate the period if requested.
|
||||
mPeriod += mPeriod * mRefreshSkipCount;
|
||||
|
||||
mThread->updateModel(mPeriod, mPhase);
|
||||
mThread->updateModel(mPeriod, mPhase, mReferenceTime);
|
||||
mModelUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DispSync::updateErrorLocked() {
|
||||
if (mPeriod == 0) {
|
||||
if (!mModelUpdated) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -472,7 +485,7 @@ void DispSync::updateErrorLocked() {
|
||||
nsecs_t sqErrSum = 0;
|
||||
|
||||
for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
|
||||
nsecs_t sample = mPresentTimes[i];
|
||||
nsecs_t sample = mPresentTimes[i] - mReferenceTime;
|
||||
if (sample > mPhase) {
|
||||
nsecs_t sampleErr = (sample - mPhase) % period;
|
||||
if (sampleErr > period / 2) {
|
||||
@ -506,7 +519,8 @@ void DispSync::resetErrorLocked() {
|
||||
nsecs_t DispSync::computeNextRefresh(int periodOffset) const {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
return (((now - mPhase) / mPeriod) + periodOffset + 1) * mPeriod + mPhase;
|
||||
nsecs_t phase = mReferenceTime + mPhase;
|
||||
return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
|
||||
}
|
||||
|
||||
void DispSync::dump(String8& result) const {
|
||||
|
@ -146,11 +146,18 @@ private:
|
||||
// number of nanoseconds from time 0 to the first vsync event.
|
||||
nsecs_t mPhase;
|
||||
|
||||
// mReferenceTime is the reference time of the modeled vsync events.
|
||||
// It is the nanosecond timestamp of the first vsync event after a resync.
|
||||
nsecs_t mReferenceTime;
|
||||
|
||||
// mError is the computed model error. It is based on the difference
|
||||
// between the estimated vsync event times and those observed in the
|
||||
// mPresentTimes array.
|
||||
nsecs_t mError;
|
||||
|
||||
// Whether we have updated the vsync event model since the last resync.
|
||||
bool mModelUpdated;
|
||||
|
||||
// These member variables are the state used during the resynchronization
|
||||
// process to store information about the hardware vsync event times used
|
||||
// to compute the model.
|
||||
|
@ -142,10 +142,10 @@ DisplayDevice::DisplayDevice(
|
||||
break;
|
||||
}
|
||||
|
||||
mPanelInverseMounted = false;
|
||||
// Check if panel is inverse mounted (contents show up HV flipped)
|
||||
property_get("persist.panel.inversemounted", property, "0");
|
||||
mPanelInverseMounted = !!atoi(property);
|
||||
mPanelMountFlip = 0;
|
||||
// 1: H-Flip, 2: V-Flip, 3: 180 (HV Flip)
|
||||
property_get("persist.panel.mountflip", property, "0");
|
||||
mPanelMountFlip = atoi(property);
|
||||
|
||||
// initialize the display orientation transform.
|
||||
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
|
||||
@ -401,7 +401,7 @@ status_t DisplayDevice::orientationToTransfrom(
|
||||
property_get("ro.sf.hwrotation", value, "0");
|
||||
int additionalRot = atoi(value);
|
||||
|
||||
if (additionalRot) {
|
||||
if (additionalRot && mType == DISPLAY_PRIMARY) {
|
||||
additionalRot /= 90;
|
||||
if (orientation == DisplayState::eOrientationUnchanged) {
|
||||
orientation = additionalRot;
|
||||
@ -428,8 +428,8 @@ status_t DisplayDevice::orientationToTransfrom(
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
if (DISPLAY_PRIMARY == mHwcDisplayId && isPanelInverseMounted()) {
|
||||
flags = flags ^ Transform::ROT_180;
|
||||
if (DISPLAY_PRIMARY == mHwcDisplayId) {
|
||||
flags = flags ^ getPanelMountFlip();
|
||||
}
|
||||
|
||||
tr->set(flags, w, h);
|
||||
|
@ -126,8 +126,8 @@ public:
|
||||
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
|
||||
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
|
||||
|
||||
bool isPanelInverseMounted() const {
|
||||
return mPanelInverseMounted;
|
||||
uint32_t getPanelMountFlip() const {
|
||||
return mPanelMountFlip;
|
||||
}
|
||||
|
||||
// We pass in mustRecompose so we can keep VirtualDisplaySurface's state
|
||||
@ -230,8 +230,8 @@ private:
|
||||
int mPowerMode;
|
||||
// Current active config
|
||||
int mActiveConfig;
|
||||
// Panel is inverse mounted
|
||||
int mPanelInverseMounted;
|
||||
// Panel's mount flip, H, V or 180 (HV)
|
||||
uint32_t mPanelMountFlip;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
@ -435,7 +435,11 @@ status_t HWComposer::queryDisplayProperties(int disp) {
|
||||
}
|
||||
|
||||
// FIXME: what should we set the format to?
|
||||
#ifdef USE_BGRA_8888
|
||||
mDisplayData[disp].format = HAL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
#endif
|
||||
mDisplayData[disp].connected = true;
|
||||
return NO_ERROR;
|
||||
}
|
||||
@ -497,7 +501,11 @@ sp<Fence> HWComposer::getDisplayFence(int disp) const {
|
||||
|
||||
uint32_t HWComposer::getFormat(int disp) const {
|
||||
if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
|
||||
#ifdef USE_BGRA_8888
|
||||
return HAL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
return HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
#endif
|
||||
} else {
|
||||
return mDisplayData[disp].format;
|
||||
}
|
||||
@ -879,7 +887,11 @@ int HWComposer::getVisualID() const {
|
||||
// FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
|
||||
// is supported by the implementation. we can only be in this case
|
||||
// if we have HWC 1.1
|
||||
#ifdef USE_BGRA_8888
|
||||
return HAL_PIXEL_FORMAT_BGRA_8888;
|
||||
#else
|
||||
return HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
#endif
|
||||
//return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
|
||||
} else {
|
||||
return mFbDev->format;
|
||||
@ -1367,7 +1379,11 @@ bool HWComposer::VSyncThread::threadLoop() {
|
||||
HWComposer::DisplayData::DisplayData()
|
||||
: configs(),
|
||||
currentConfig(0),
|
||||
#ifdef USE_BGRA_8888
|
||||
format(HAL_PIXEL_FORMAT_BGRA_8888),
|
||||
#else
|
||||
format(HAL_PIXEL_FORMAT_RGBA_8888),
|
||||
#endif
|
||||
connected(false),
|
||||
hasFbComp(false), hasOvComp(false),
|
||||
capacity(0), list(NULL),
|
||||
|
@ -306,6 +306,7 @@ public:
|
||||
};
|
||||
|
||||
friend class VSyncThread;
|
||||
friend class ExHWComposer;
|
||||
|
||||
// for debugging ----------------------------------------------------------
|
||||
void dump(String8& out) const;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
@ -45,6 +45,10 @@
|
||||
#include <ExSurfaceFlinger/ExHWComposer.h>
|
||||
#include <ExSurfaceFlinger/ExVirtualDisplaySurface.h>
|
||||
#include <gralloc_priv.h>
|
||||
#ifdef SDM_TARGET
|
||||
#include <qd_utils.h>
|
||||
#include <display_config.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
#include <cutils/properties.h>
|
||||
@ -176,8 +180,25 @@ bool DisplayUtils::canAllocateHwcDisplayIdForVDS(int usage) {
|
||||
|
||||
#ifdef QTI_BSP
|
||||
#ifdef FORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
|
||||
#ifdef SDM_TARGET
|
||||
int hdmi_node = qdutils::getHDMINode();
|
||||
if(hdmi_node == HWC_DISPLAY_PRIMARY) {
|
||||
int active_config = qdutils::getActiveConfig(HWC_DISPLAY_PRIMARY);
|
||||
if(active_config >= 0) {
|
||||
qdutils::DisplayAttributes attr = qdutils::getDisplayAttributes(active_config,
|
||||
HWC_DISPLAY_PRIMARY);
|
||||
if(!attr.is_yuv) {
|
||||
// Reserve hardware acceleration for WFD use-case
|
||||
flag_mask = GRALLOC_USAGE_PRIVATE_WFD;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
// Reserve hardware acceleration for WFD use-case
|
||||
flag_mask = GRALLOC_USAGE_PRIVATE_WFD;
|
||||
#ifdef SDM_TARGET
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// Don't allocate HWC display unless we force HWC copy, otherwise
|
||||
// incompatible buffers are sent to the media stack
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "ExHWComposer.h"
|
||||
#ifdef QTI_BSP
|
||||
#include <hardware/display_defs.h>
|
||||
#include <gralloc_priv.h>
|
||||
#include <qdMetaData.h>
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
@ -74,4 +76,32 @@ bool ExHWComposer::isCompositionTypeBlit(const int32_t compType) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(QTI_BSP) && defined(SDM_TARGET)
|
||||
uint32_t ExHWComposer::getS3DFlag(int disp) const {
|
||||
if (disp < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mHwc || uint32_t(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp))
|
||||
return 0;
|
||||
|
||||
const DisplayData& disp_data(mDisplayData[disp]);
|
||||
|
||||
for (size_t i=0 ; i<disp_data.list->numHwLayers-1; i++) {
|
||||
const hwc_layer_1_t &l = disp_data.list->hwLayers[i];
|
||||
private_handle_t *pvt_handle = static_cast<private_handle_t *>
|
||||
(const_cast<native_handle_t*>(l.handle));
|
||||
|
||||
if (pvt_handle != NULL) {
|
||||
struct S3DSFRender_t s3dRender;
|
||||
getMetaData(pvt_handle, GET_S3D_RENDER, &s3dRender);
|
||||
if (s3dRender.DisplayId == static_cast<uint32_t>(disp) && s3dRender.GpuRender) {
|
||||
return s3dRender.GpuS3dFormat;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}; // namespace android
|
||||
|
@ -43,6 +43,10 @@ public:
|
||||
|
||||
virtual ~ExHWComposer();
|
||||
|
||||
#ifdef QTI_BSP
|
||||
uint32_t getS3DFlag(int disp) const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool mVDSEnabled;
|
||||
inline bool isVDSEnabled() const { return mVDSEnabled; };
|
||||
|
@ -36,10 +36,12 @@
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#ifdef QTI_BSP
|
||||
#include <gralloc_priv.h>
|
||||
#include <qdMetaData.h>
|
||||
#include <hardware/display_defs.h>
|
||||
#endif
|
||||
|
||||
#include "ExLayer.h"
|
||||
#include "RenderEngine/RenderEngine.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
@ -70,12 +72,18 @@ static Rect getAspectRatio(const sp<const DisplayDevice>& hw,
|
||||
|
||||
ExLayer::ExLayer(SurfaceFlinger* flinger, const sp<Client>& client,
|
||||
const String8& name, uint32_t w, uint32_t h, uint32_t flags)
|
||||
#ifdef QTI_BSP
|
||||
: Layer(flinger, client, name, w, h, flags),
|
||||
mMeshLeftTop(Mesh::TRIANGLE_FAN, 4, 2, 2),
|
||||
mMeshRightBottom(Mesh::TRIANGLE_FAN, 4, 2, 2) {
|
||||
#else
|
||||
: Layer(flinger, client, name, w, h, flags) {
|
||||
|
||||
#endif
|
||||
char property[PROPERTY_VALUE_MAX] = {0};
|
||||
|
||||
mDebugLogs = false;
|
||||
mIsGPUAllowedForProtected = false;
|
||||
mIsHDMIPrimary = false;
|
||||
if((property_get("persist.debug.qdframework.logs", property, NULL) > 0) &&
|
||||
(!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
|
||||
(!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
|
||||
@ -88,6 +96,12 @@ ExLayer::ExLayer(SurfaceFlinger* flinger, const sp<Client>& client,
|
||||
(atoi(property) == 1)) {
|
||||
mIsGPUAllowedForProtected = true;
|
||||
}
|
||||
|
||||
if ((property_get("persist.sys.is_hdmi_primary", property, NULL) > 0) &&
|
||||
(atoi(property) == 1)) {
|
||||
mIsHDMIPrimary = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ExLayer::~ExLayer() {
|
||||
@ -204,4 +218,172 @@ bool ExLayer::canAllowGPUForProtected() const {
|
||||
}
|
||||
}
|
||||
|
||||
void ExLayer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
|
||||
const Region& /* clip */, bool useIdentityTransform) const {
|
||||
const State& s(getDrawingState());
|
||||
#if defined(QTI_BSP) && defined(SDM_TARGET)
|
||||
uint32_t s3d_fmt = 0;
|
||||
private_handle_t *pvt_handle = static_cast<private_handle_t *>
|
||||
(const_cast<native_handle_t*>(mActiveBuffer->handle));
|
||||
if (pvt_handle != NULL) {
|
||||
struct S3DSFRender_t s3dRender;
|
||||
getMetaData(pvt_handle, GET_S3D_RENDER, &s3dRender);
|
||||
|
||||
if ((s3dRender.DisplayId == static_cast<uint32_t>(hw->getHwcDisplayId()) ||
|
||||
mIsHDMIPrimary) && s3dRender.GpuRender) {
|
||||
clearMetaData(pvt_handle, SET_S3D_RENDER);
|
||||
s3d_fmt = s3dRender.GpuS3dFormat;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
computeGeometry(hw, mMesh, useIdentityTransform);
|
||||
|
||||
/*
|
||||
* 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 whether 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.
|
||||
*/
|
||||
Rect win(s.active.w, s.active.h);
|
||||
if(!s.active.crop.isEmpty()) {
|
||||
win = s.active.crop;
|
||||
}
|
||||
#ifdef QTI_BSP
|
||||
win = s.transform.transform(win);
|
||||
win.intersect(hw->getViewport(), &win);
|
||||
win = s.transform.inverse().transform(win);
|
||||
win.intersect(Rect(s.active.w, s.active.h), &win);
|
||||
win = reduce(win, s.activeTransparentRegion);
|
||||
#else
|
||||
win = reduce(win, s.activeTransparentRegion);
|
||||
#endif
|
||||
float left = float(win.left) / float(s.active.w);
|
||||
float top = float(win.top) / float(s.active.h);
|
||||
float right = float(win.right) / float(s.active.w);
|
||||
float bottom = float(win.bottom) / float(s.active.h);
|
||||
|
||||
// TODO: we probably want to generate the texture coords with the mesh
|
||||
// here we assume that we only have 4 vertices
|
||||
Mesh::VertexArray<vec2> texCoords(mMesh.getTexCoordArray<vec2>());
|
||||
texCoords[0] = vec2(left, 1.0f - top);
|
||||
texCoords[1] = vec2(left, 1.0f - bottom);
|
||||
texCoords[2] = vec2(right, 1.0f - bottom);
|
||||
texCoords[3] = vec2(right, 1.0f - top);
|
||||
|
||||
#if defined(QTI_BSP) && defined(SDM_TARGET)
|
||||
computeGeometryS3D(hw, mMesh, mMeshLeftTop, mMeshRightBottom, s3d_fmt);
|
||||
#endif
|
||||
|
||||
RenderEngine& engine(mFlinger->getRenderEngine());
|
||||
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
|
||||
|
||||
#if defined(QTI_BSP) && defined(SDM_TARGET)
|
||||
if (s3d_fmt != HWC_S3DMODE_NONE) {
|
||||
engine.setScissor(0, 0, hw->getWidth(), hw->getHeight());
|
||||
engine.drawMesh(mMeshLeftTop);
|
||||
engine.drawMesh(mMeshRightBottom);
|
||||
} else {
|
||||
#endif
|
||||
engine.drawMesh(mMesh);
|
||||
#if defined(QTI_BSP) && defined(SDM_TARGET)
|
||||
}
|
||||
#endif
|
||||
|
||||
engine.disableBlending();
|
||||
}
|
||||
|
||||
#ifdef QTI_BSP
|
||||
void ExLayer::computeGeometryS3D(const sp<const DisplayDevice>& hw, Mesh& mesh,
|
||||
Mesh& meshLeftTop, Mesh &meshRightBottom, uint32_t s3d_fmt) const
|
||||
{
|
||||
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
|
||||
Mesh::VertexArray<vec2> positionLeftTop(meshLeftTop.getPositionArray<vec2>());
|
||||
Mesh::VertexArray<vec2> positionRightBottom(meshRightBottom.getPositionArray<vec2>());
|
||||
Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
|
||||
Mesh::VertexArray<vec2> texCoordsLeftTop(meshLeftTop.getTexCoordArray<vec2>());
|
||||
Mesh::VertexArray<vec2> texCoordsRightBottom(meshRightBottom.getTexCoordArray<vec2>());
|
||||
|
||||
Rect scissor = hw->getBounds();
|
||||
|
||||
if(s3d_fmt == HWC_S3DMODE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t count = mesh.getVertexCount();
|
||||
while(count--) {
|
||||
positionLeftTop[count] = positionRightBottom[count] = position[count];
|
||||
texCoordsLeftTop[count] = texCoordsRightBottom[count] = texCoords[count];
|
||||
}
|
||||
|
||||
switch (s3d_fmt) {
|
||||
case HWC_S3DMODE_LR:
|
||||
case HWC_S3DMODE_RL:
|
||||
{
|
||||
positionLeftTop[0].x = (position[0].x - scissor.left) / 2.0f + scissor.left;
|
||||
positionLeftTop[1].x = (position[1].x - scissor.left) / 2.0f + scissor.left;
|
||||
positionLeftTop[2].x = (position[2].x - scissor.left) / 2.0f + scissor.left;
|
||||
positionLeftTop[3].x = (position[3].x - scissor.left) / 2.0f + scissor.left;
|
||||
|
||||
positionRightBottom[0].x = positionLeftTop[0].x + scissor.getWidth()/2;
|
||||
positionRightBottom[1].x = positionLeftTop[1].x + scissor.getWidth()/2;
|
||||
positionRightBottom[2].x = positionLeftTop[2].x + scissor.getWidth()/2;
|
||||
positionRightBottom[3].x = positionLeftTop[3].x + scissor.getWidth()/2;
|
||||
|
||||
if(isYuvLayer()) {
|
||||
texCoordsLeftTop[0].x = texCoords[0].x / 2.0f;
|
||||
texCoordsLeftTop[1].x = texCoords[1].x / 2.0f;
|
||||
texCoordsLeftTop[2].x = texCoords[2].x / 2.0f;
|
||||
texCoordsLeftTop[3].x = texCoords[3].x / 2.0f;
|
||||
|
||||
texCoordsRightBottom[0].x = texCoordsLeftTop[0].x + 0.5f;
|
||||
texCoordsRightBottom[1].x = texCoordsLeftTop[1].x + 0.5f;
|
||||
texCoordsRightBottom[2].x = texCoordsLeftTop[2].x + 0.5f;
|
||||
texCoordsRightBottom[3].x = texCoordsLeftTop[3].x + 0.5f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HWC_S3DMODE_TB:
|
||||
{
|
||||
positionRightBottom[0].y = (position[0].y - scissor.top) / 2.0f + scissor.top;
|
||||
positionRightBottom[1].y = (position[1].y - scissor.top) / 2.0f + scissor.top;
|
||||
positionRightBottom[2].y = (position[2].y - scissor.top) / 2.0f + scissor.top;
|
||||
positionRightBottom[3].y = (position[3].y - scissor.top) / 2.0f + scissor.top;
|
||||
|
||||
positionLeftTop[0].y = positionRightBottom[0].y + scissor.getHeight() / 2.0f;
|
||||
positionLeftTop[1].y = positionRightBottom[1].y + scissor.getHeight() / 2.0f;
|
||||
positionLeftTop[2].y = positionRightBottom[2].y + scissor.getHeight() / 2.0f;
|
||||
positionLeftTop[3].y = positionRightBottom[3].y + scissor.getHeight() / 2.0f;
|
||||
|
||||
positionLeftTop[0].x = positionRightBottom[0].x = position[0].x;
|
||||
positionLeftTop[1].x = positionRightBottom[1].x = position[1].x;
|
||||
positionLeftTop[2].x = positionRightBottom[2].x = position[2].x;
|
||||
positionLeftTop[3].x = positionRightBottom[3].x = position[3].x;
|
||||
|
||||
if(isYuvLayer()) {
|
||||
texCoordsRightBottom[0].y = texCoords[0].y / 2.0f;
|
||||
texCoordsRightBottom[1].y = texCoords[1].y / 2.0f;
|
||||
texCoordsRightBottom[2].y = texCoords[2].y / 2.0f;
|
||||
texCoordsRightBottom[3].y = texCoords[3].y / 2.0f;
|
||||
|
||||
texCoordsLeftTop[0].y = texCoordsRightBottom[0].y + 0.5f;
|
||||
texCoordsLeftTop[1].y = texCoordsRightBottom[1].y + 0.5f;
|
||||
texCoordsLeftTop[2].y = texCoordsRightBottom[2].y + 0.5f;
|
||||
texCoordsLeftTop[3].y = texCoordsRightBottom[3].y + 0.5f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}; // namespace android
|
||||
|
@ -43,6 +43,22 @@ class ExSurfaceFlinger;
|
||||
class ExLayer : public Layer
|
||||
{
|
||||
public:
|
||||
#ifdef QTI_BSP
|
||||
enum {
|
||||
/*
|
||||
* HWC S3D_MODE is set by HWC driver to indicate that HWC driver can not support
|
||||
* S3D standalone, need surfaceflinger help to draw layers twice to construct
|
||||
* S3D framebuffer target.
|
||||
*/
|
||||
HWC_S3DMODE_NONE = 0x00000000,
|
||||
HWC_S3DMODE_LR = 0x00000001,
|
||||
HWC_S3DMODE_RL = 0x00000002,
|
||||
HWC_S3DMODE_TB = 0x00000003,
|
||||
HWC_S3DMODE_FP = 0x00000004,
|
||||
HWC_S3DMODE_MAX = 0x00000005,
|
||||
};
|
||||
#endif
|
||||
|
||||
ExLayer(SurfaceFlinger* flinger, const sp<Client>& client,
|
||||
const String8& name, uint32_t w, uint32_t h, uint32_t flags);
|
||||
virtual ~ExLayer();
|
||||
@ -57,11 +73,27 @@ public:
|
||||
HWComposer::HWCLayerInterface& layer);
|
||||
virtual bool canAllowGPUForProtected() const;
|
||||
|
||||
#ifdef QTI_BSP
|
||||
virtual void computeGeometryS3D(const sp<const DisplayDevice>& hw, Mesh& mesh,
|
||||
Mesh& meshLeftTop, Mesh &meshRightBottom, uint32_t s3d_fmt) const;
|
||||
#endif
|
||||
protected:
|
||||
bool mDebugLogs;
|
||||
bool isDebug() { return mDebugLogs; }
|
||||
bool mIsGPUAllowedForProtected;
|
||||
bool mIsHDMIPrimary;
|
||||
|
||||
private:
|
||||
#ifdef QTI_BSP
|
||||
// The mesh used to draw the layer in GLES composition mode for s3d left/top
|
||||
mutable Mesh mMeshLeftTop;
|
||||
// The mesh used to draw the layer in GLES composition mode for s3d right/bottom
|
||||
mutable Mesh mMeshRightBottom;
|
||||
|
||||
virtual void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
bool useIdentityTransform) const;
|
||||
};
|
||||
#endif
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
@ -335,6 +335,10 @@ void ExSurfaceFlinger::dumpDrawCycle(bool prePrepare) {
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
ptm = localtime(&tv.tv_sec);
|
||||
if (ptm == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
strftime (hms, sizeof (hms), "%H:%M:%S", ptm);
|
||||
millis = tv.tv_usec / 1000;
|
||||
snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03ld", hms, millis);
|
||||
|
@ -104,9 +104,12 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
|
||||
|
||||
mName = name;
|
||||
|
||||
mCurrentState.active.x = 0;
|
||||
mCurrentState.active.y = 0;
|
||||
mCurrentState.active.w = w;
|
||||
mCurrentState.active.h = h;
|
||||
mCurrentState.active.crop.makeInvalid();
|
||||
mCurrentState.active.isPositionPending = false;
|
||||
mCurrentState.z = 0;
|
||||
mCurrentState.alpha = 0xFF;
|
||||
mCurrentState.blur = 0xFF;
|
||||
@ -464,7 +467,11 @@ void Layer::setGeometry(
|
||||
|
||||
// this gives us only the "orientation" component of the transform
|
||||
const State& s(getDrawingState());
|
||||
#if defined(QTI_BSP) && !defined(QCOM_BSP_LEGACY)
|
||||
if (!isOpaque(s)) {
|
||||
#else
|
||||
if (!isOpaque(s) || s.alpha != 0xFF) {
|
||||
#endif
|
||||
layer.setBlending(mPremultipliedAlpha ?
|
||||
HWC_BLENDING_PREMULT :
|
||||
HWC_BLENDING_COVERAGE);
|
||||
@ -1027,6 +1034,17 @@ uint32_t Layer::doTransaction(uint32_t flags) {
|
||||
if (flags & eDontUpdateGeometryState) {
|
||||
} else {
|
||||
Layer::State& editCurrentState(getCurrentState());
|
||||
// If a position change was requested, and we have the correct
|
||||
// buffer size, no need to delay, update state now.
|
||||
if (editCurrentState.requested.isPositionPending) {
|
||||
float requestedX = editCurrentState.requested.x;
|
||||
float requestedY = editCurrentState.requested.y;
|
||||
if (requestedX != editCurrentState.active.x ||
|
||||
requestedY != editCurrentState.active.y) {
|
||||
editCurrentState.requested.isPositionPending = false;
|
||||
editCurrentState.transform.set(requestedX, requestedY);
|
||||
}
|
||||
}
|
||||
editCurrentState.active = c.requested;
|
||||
}
|
||||
|
||||
@ -1064,10 +1082,15 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) {
|
||||
}
|
||||
|
||||
bool Layer::setPosition(float x, float y) {
|
||||
if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
|
||||
if ((mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y
|
||||
&& !mCurrentState.requested.isPositionPending) ||
|
||||
(mCurrentState.requested.isPositionPending && mCurrentState.requested.x == x
|
||||
&& mCurrentState.requested.y == y))
|
||||
return false;
|
||||
mCurrentState.sequence++;
|
||||
mCurrentState.transform.set(x, y);
|
||||
mCurrentState.requested.x = x;
|
||||
mCurrentState.requested.y = y;
|
||||
mCurrentState.requested.isPositionPending = true;
|
||||
setTransactionFlags(eTransactionNeeded);
|
||||
return true;
|
||||
}
|
||||
@ -1290,6 +1313,19 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
||||
(bufWidth == front.requested.w &&
|
||||
bufHeight == front.requested.h))
|
||||
{
|
||||
|
||||
// If a position change was requested along with a resize.
|
||||
// Now that we have the correct buffer size, update the position as well.
|
||||
if (current.requested.isPositionPending) {
|
||||
float requestedX = current.requested.x;
|
||||
float requestedY = current.requested.y;
|
||||
if (requestedX != current.active.x || requestedY != current.active.y) {
|
||||
front.transform.set(requestedX, requestedY);
|
||||
current.transform.set(requestedX, requestedY);
|
||||
current.requested.isPositionPending = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Here we pretend the transaction happened by updating the
|
||||
// current and drawing states. Drawing state is only accessed
|
||||
// in this thread, no need to have it locked
|
||||
@ -1412,11 +1448,16 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
|
||||
|
||||
// Remove any stale buffers that have been dropped during
|
||||
// updateTexImage
|
||||
while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
|
||||
while ((mQueuedFrames > 0) && (mQueueItems[0].mFrameNumber != currentFrameNumber)) {
|
||||
mQueueItems.removeAt(0);
|
||||
android_atomic_dec(&mQueuedFrames);
|
||||
}
|
||||
|
||||
if (mQueuedFrames == 0) {
|
||||
ALOGE("[%s] mQueuedFrames is zero !!", mName.string());
|
||||
return outDirtyRegion;
|
||||
}
|
||||
|
||||
mQueueItems.removeAt(0);
|
||||
}
|
||||
|
||||
|
@ -95,11 +95,15 @@ public:
|
||||
};
|
||||
|
||||
struct Geometry {
|
||||
float x;
|
||||
float y;
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
bool isPositionPending;
|
||||
Rect crop;
|
||||
inline bool operator ==(const Geometry& rhs) const {
|
||||
return (w == rhs.w && h == rhs.h && crop == rhs.crop);
|
||||
return (w == rhs.w && h == rhs.h && crop == rhs.crop && x == rhs.x && y == rhs.y
|
||||
&& isPositionPending == rhs.isPositionPending);
|
||||
}
|
||||
inline bool operator !=(const Geometry& rhs) const {
|
||||
return !operator ==(rhs);
|
||||
@ -158,8 +162,13 @@ public:
|
||||
uint32_t getTransactionFlags(uint32_t flags);
|
||||
uint32_t setTransactionFlags(uint32_t flags);
|
||||
|
||||
#ifdef QTI_BSP
|
||||
virtual void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
|
||||
bool useIdentityTransform) const;
|
||||
#else
|
||||
void computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
|
||||
bool useIdentityTransform) const;
|
||||
#endif
|
||||
Rect computeBounds(const Region& activeTransparentRegion) const;
|
||||
Rect computeBounds() const;
|
||||
|
||||
@ -388,9 +397,14 @@ private:
|
||||
// drawing
|
||||
void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
float r, float g, float b, float alpha) const;
|
||||
#ifdef QTI_BSP
|
||||
virtual void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
bool useIdentityTransform) const;
|
||||
#else
|
||||
void drawWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||
bool useIdentityTransform) const;
|
||||
|
||||
#endif
|
||||
// Temporary - Used only for LEGACY camera mode.
|
||||
uint32_t getProducerStickyTransform() const;
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
@ -90,16 +91,11 @@ static void setupMesh(Mesh& mesh, int width, int height, int viewportHeight) {
|
||||
texCoords[3] = vec2(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
|
||||
LayerBlur::LayerBlur(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), mBlurMaskSampling(1), mBlurMaskAlphaThreshold(0.0f)
|
||||
,mLastFrameSequence(0)
|
||||
: Layer(flinger, client, name, w, h, flags), mBlurMaskSampling(1),
|
||||
mBlurMaskAlphaThreshold(0.0f) ,mLastFrameSequence(0)
|
||||
{
|
||||
#ifdef UI_BLUR
|
||||
mBlurToken = qtiblur::initBlurToken();
|
||||
#endif
|
||||
|
||||
GLuint texnames[3];
|
||||
mFlinger->getRenderEngine().genTextures(3, texnames);
|
||||
mTextureCapture.init(Texture::TEXTURE_2D, texnames[0]);
|
||||
@ -108,9 +104,6 @@ LayerBlur::LayerBlur(SurfaceFlinger* flinger, const sp<Client>& client,
|
||||
}
|
||||
|
||||
LayerBlur::~LayerBlur() {
|
||||
#ifdef UI_BLUR
|
||||
qtiblur::releaseBlurToken(mBlurToken);
|
||||
#endif
|
||||
|
||||
releaseFbo(mFboCapture);
|
||||
releaseFbo(mFboMasking);
|
||||
@ -168,18 +161,15 @@ void LayerBlur::onDraw(const sp<const DisplayDevice>& hw, const Region& /*clip*/
|
||||
// blur
|
||||
size_t outTexWidth = mTextureBlur.getWidth();
|
||||
size_t outTexHeight = mTextureBlur.getHeight();
|
||||
#ifdef UI_BLUR
|
||||
if (!qtiblur::blur(mBlurToken,
|
||||
s.blur,
|
||||
if (mBlurImpl.blur(s.blur,
|
||||
mTextureCapture.getTextureName(),
|
||||
mTextureCapture.getWidth(),
|
||||
mTextureCapture.getHeight(),
|
||||
mTextureBlur.getTextureName(),
|
||||
&outTexWidth,
|
||||
&outTexHeight)) {
|
||||
&outTexHeight) != OK) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// mTextureBlur now has "Blurred image"
|
||||
mTextureBlur.setDimensions(outTexWidth, outTexHeight);
|
||||
@ -238,8 +228,7 @@ bool LayerBlur::captureScreen(const sp<const DisplayDevice>& hw, FBO& fbo, Textu
|
||||
texture.getTextureName(), 0);
|
||||
|
||||
mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
if (hw->isPanelInverseMounted())
|
||||
rotation = Transform::ROT_180;
|
||||
rotation = (Transform::orientation_flags)(rotation ^ hw->getPanelMountFlip());
|
||||
mFlinger->renderScreenImplLocked(
|
||||
hw,
|
||||
Rect(0,0,width,height),
|
||||
@ -412,6 +401,86 @@ void LayerBlur::ensureFbo(FBO& fbo, int width, int height, int textureName) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void* LayerBlur::BlurImpl::sLibHandle = NULL;
|
||||
bool LayerBlur::BlurImpl::sUnsupported = false;
|
||||
|
||||
LayerBlur::BlurImpl::initBlurTokenFn LayerBlur::BlurImpl::initBlurToken = NULL;
|
||||
LayerBlur::BlurImpl::releaseBlurTokenFn LayerBlur::BlurImpl::releaseBlurToken = NULL;
|
||||
LayerBlur::BlurImpl::blurFn LayerBlur::BlurImpl::doBlur = NULL;
|
||||
Mutex LayerBlur::BlurImpl::sLock;
|
||||
|
||||
void LayerBlur::BlurImpl::closeBlurImpl() {
|
||||
if (sLibHandle != NULL) {
|
||||
dlclose(sLibHandle);
|
||||
sLibHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
status_t LayerBlur::BlurImpl::initBlurImpl() {
|
||||
if (sLibHandle != NULL) {
|
||||
return OK;
|
||||
}
|
||||
if (sUnsupported) {
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
sLibHandle = dlopen("libuiblur.so", RTLD_NOW);
|
||||
if (sLibHandle == NULL) {
|
||||
sUnsupported = true;
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
// happy happy joy joy!
|
||||
|
||||
initBlurToken = (initBlurTokenFn)dlsym(sLibHandle,
|
||||
"_ZN7qtiblur13initBlurTokenEv");
|
||||
releaseBlurToken = (releaseBlurTokenFn)dlsym(sLibHandle,
|
||||
"_ZN7qtiblur16releaseBlurTokenEPv");
|
||||
|
||||
if (sizeof(size_t) == 4) {
|
||||
doBlur = (blurFn)dlsym(sLibHandle,
|
||||
"_ZN7qtiblur4blurEPvijjjjPjS1_");
|
||||
} else if (sizeof(size_t) == 8) {
|
||||
doBlur = (blurFn)dlsym(sLibHandle,
|
||||
"_ZN7qtiblur4blurEPvijmmjPmS1_");
|
||||
}
|
||||
|
||||
if (!initBlurToken || !releaseBlurToken || !doBlur) {
|
||||
ALOGE("dlsym failed for blur impl!: %s", dlerror());
|
||||
closeBlurImpl();
|
||||
sUnsupported = true;
|
||||
return NO_INIT;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
LayerBlur::BlurImpl::BlurImpl() : mToken(NULL) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
if (initBlurImpl() == OK) {
|
||||
mToken = initBlurToken();
|
||||
}
|
||||
}
|
||||
|
||||
LayerBlur::BlurImpl::~BlurImpl() {
|
||||
Mutex::Autolock _l(sLock);
|
||||
if (mToken != NULL) {
|
||||
releaseBlurToken(mToken);
|
||||
}
|
||||
}
|
||||
|
||||
status_t LayerBlur::BlurImpl::blur(int level, uint32_t inId, size_t inWidth, size_t inHeight,
|
||||
uint32_t outId, size_t* outWidth, size_t* outHeight) {
|
||||
Mutex::Autolock _l(sLock);
|
||||
if (mToken == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
return doBlur(mToken, level, inId, inWidth, inHeight,
|
||||
outId, outWidth, outHeight) ? OK : NO_INIT;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
@ -20,15 +20,12 @@
|
||||
#ifndef ANDROID_LAYER_BLUR_H
|
||||
#define ANDROID_LAYER_BLUR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
#ifdef UI_BLUR
|
||||
#include "Blur.h" // libuiblur.so
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
@ -58,9 +55,37 @@ public:
|
||||
virtual bool setBlurMaskAlphaThreshold(float alpha) { mBlurMaskAlphaThreshold = alpha; return true; }
|
||||
|
||||
private:
|
||||
#ifdef UI_BLUR
|
||||
qtiblur::BLUR_TOKEN mBlurToken;
|
||||
#endif
|
||||
class BlurImpl {
|
||||
public:
|
||||
|
||||
BlurImpl();
|
||||
~BlurImpl();
|
||||
|
||||
status_t blur(int level, uint32_t inId, size_t inWidth, size_t inheight,
|
||||
uint32_t outId, size_t* outWidth, size_t* outHeight);
|
||||
|
||||
protected:
|
||||
static status_t initBlurImpl();
|
||||
static void closeBlurImpl();
|
||||
static void* sLibHandle;
|
||||
static bool sUnsupported;
|
||||
|
||||
typedef void* (*initBlurTokenFn)();
|
||||
typedef void* (*releaseBlurTokenFn)(void*);
|
||||
typedef void* (*blurFn)(void*, int, uint32_t, size_t, size_t, uint32_t, size_t*, size_t*);
|
||||
|
||||
static initBlurTokenFn initBlurToken;
|
||||
static releaseBlurTokenFn releaseBlurToken;
|
||||
static blurFn doBlur;
|
||||
|
||||
static Mutex sLock;
|
||||
|
||||
private:
|
||||
void* mToken;
|
||||
};
|
||||
|
||||
BlurImpl mBlurImpl;
|
||||
|
||||
wp<Layer> mBlurMaskLayer;
|
||||
int32_t mBlurMaskSampling;
|
||||
float mBlurMaskAlphaThreshold;
|
||||
|
@ -74,6 +74,7 @@
|
||||
|
||||
#include "DisplayHardware/FramebufferSurface.h"
|
||||
#include "DisplayHardware/HWComposer.h"
|
||||
#include "ExSurfaceFlinger/ExHWComposer.h"
|
||||
#include "DisplayHardware/VirtualDisplaySurface.h"
|
||||
|
||||
#include "Effects/Daltonizer.h"
|
||||
@ -82,6 +83,10 @@
|
||||
#include <cutils/compiler.h>
|
||||
#include "DisplayUtils.h"
|
||||
|
||||
#ifdef USES_HWC_SERVICES
|
||||
#include "ExynosHWCService.h"
|
||||
#endif
|
||||
|
||||
#define DISPLAY_COUNT 1
|
||||
|
||||
/*
|
||||
@ -130,6 +135,10 @@ static sp<Layer> lastSurfaceViewLayer;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#ifdef USES_HWC_SERVICES
|
||||
static bool notifyPSRExit = true;
|
||||
#endif
|
||||
|
||||
SurfaceFlinger::SurfaceFlinger()
|
||||
: BnSurfaceComposer(),
|
||||
mTransactionFlags(0),
|
||||
@ -156,6 +165,7 @@ SurfaceFlinger::SurfaceFlinger()
|
||||
mHWVsyncAvailable(false),
|
||||
mDaltonize(false),
|
||||
mHasColorMatrix(false),
|
||||
mHasSecondaryColorMatrix(false),
|
||||
mHasPoweredOff(false),
|
||||
mFrameBuckets(),
|
||||
mTotalTime(0),
|
||||
@ -311,6 +321,14 @@ void SurfaceFlinger::bootFinished()
|
||||
// formerly we would just kill the process, but we now ask it to exit so it
|
||||
// can choose where to stop the animation.
|
||||
property_set("service.bootanim.exit", "1");
|
||||
|
||||
#ifdef USES_HWC_SERVICES
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
sp<android::IExynosHWCService> hwc =
|
||||
interface_cast<android::IExynosHWCService>(sm->getService(String16("Exynos.HWCService")));
|
||||
ALOGD("boot finished. Inform HWC");
|
||||
hwc->setBootFinished();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
|
||||
@ -797,6 +815,19 @@ void SurfaceFlinger::signalTransaction() {
|
||||
}
|
||||
|
||||
void SurfaceFlinger::signalLayerUpdate() {
|
||||
#ifdef USES_HWC_SERVICES
|
||||
if (notifyPSRExit) {
|
||||
notifyPSRExit = false;
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
sp<IExynosHWCService> hwcService =
|
||||
interface_cast<android::IExynosHWCService>(
|
||||
sm->getService(String16("Exynos.HWCService")));
|
||||
if (hwcService != NULL)
|
||||
hwcService->notifyPSRExit();
|
||||
else
|
||||
ALOGE("HWCService::notifyPSRExit failed");
|
||||
}
|
||||
#endif
|
||||
mEventQueue.invalidate();
|
||||
}
|
||||
|
||||
@ -981,6 +1012,9 @@ void SurfaceFlinger::handleMessageRefresh() {
|
||||
doDebugFlashRegions();
|
||||
doComposition();
|
||||
postComposition();
|
||||
#ifdef USES_HWC_SERVICES
|
||||
notifyPSRExit = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
|
||||
@ -1193,7 +1227,7 @@ void SurfaceFlinger::setUpHWComposer() {
|
||||
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
|
||||
const sp<Layer>& layer(currentLayers[i]);
|
||||
layer->setGeometry(hw, *cur);
|
||||
if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
|
||||
if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix || mHasSecondaryColorMatrix) {
|
||||
cur->setSkip(true);
|
||||
}
|
||||
}
|
||||
@ -1958,11 +1992,14 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
|
||||
if (CC_LIKELY(!mDaltonize && !mHasColorMatrix && !mHasSecondaryColorMatrix)) {
|
||||
if (!doComposeSurfaces(hw, dirtyRegion)) return;
|
||||
} else {
|
||||
RenderEngine& engine(getRenderEngine());
|
||||
mat4 colorMatrix = mColorMatrix;
|
||||
if (mHasSecondaryColorMatrix) {
|
||||
colorMatrix = mHasColorMatrix ? (colorMatrix * mSecondaryColorMatrix) : mSecondaryColorMatrix;
|
||||
}
|
||||
if (mDaltonize) {
|
||||
colorMatrix = colorMatrix * mDaltonizer();
|
||||
}
|
||||
@ -1999,7 +2036,12 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
|
||||
}
|
||||
|
||||
// Never touch the framebuffer if we don't have any framebuffer layers
|
||||
#if defined(QTI_BSP) && defined(SDM_TARGET)
|
||||
const bool hasHwcComposition = hwc.hasHwcComposition(id) |
|
||||
(reinterpret_cast<ExHWComposer*>(&hwc))->getS3DFlag(id);
|
||||
#else
|
||||
const bool hasHwcComposition = hwc.hasHwcComposition(id);
|
||||
#endif
|
||||
if (hasHwcComposition) {
|
||||
// when using overlays, we assume a fully transparent framebuffer
|
||||
// NOTE: we could reduce how much we need to clear, for instance
|
||||
@ -2948,7 +2990,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
|
||||
result.appendFormat(" h/w composer %s and %s\n",
|
||||
hwc.initCheck()==NO_ERROR ? "present" : "not present",
|
||||
(mDebugDisableHWC || mDebugRegion || mDaltonize
|
||||
|| mHasColorMatrix) ? "disabled" : "enabled");
|
||||
|| mHasColorMatrix
|
||||
|| mHasSecondaryColorMatrix) ? "disabled" : "enabled");
|
||||
hwc.dump(result);
|
||||
|
||||
/*
|
||||
@ -3158,6 +3201,28 @@ status_t SurfaceFlinger::onTransact(
|
||||
mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
|
||||
return NO_ERROR;
|
||||
}
|
||||
case 1030: {
|
||||
// apply a secondary color matrix
|
||||
// this will be combined with any other transformations
|
||||
n = data.readInt32();
|
||||
mHasSecondaryColorMatrix = n ? 1 : 0;
|
||||
if (n) {
|
||||
// color matrix is sent as mat3 matrix followed by vec3
|
||||
// offset, then packed into a mat4 where the last row is
|
||||
// the offset and extra values are 0
|
||||
for (size_t i = 0 ; i < 4; i++) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
mSecondaryColorMatrix[i][j] = data.readFloat();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mSecondaryColorMatrix = mat4();
|
||||
}
|
||||
invalidateHwcGeometry();
|
||||
repaintEverything();
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return err;
|
||||
@ -3436,10 +3501,9 @@ void SurfaceFlinger::renderScreenImplLocked(
|
||||
// make sure to clear all GL error flags
|
||||
engine.checkErrors();
|
||||
|
||||
if (DisplayDevice::DISPLAY_PRIMARY == hw->getDisplayType() &&
|
||||
hw->isPanelInverseMounted()) {
|
||||
if (DisplayDevice::DISPLAY_PRIMARY == hw->getDisplayType()) {
|
||||
rotation = (Transform::orientation_flags)
|
||||
(rotation ^ Transform::ROT_180);
|
||||
(rotation ^ hw->getPanelMountFlip());
|
||||
}
|
||||
|
||||
// set-up our viewport
|
||||
|
@ -146,6 +146,9 @@ private:
|
||||
friend class DisplayEventConnection;
|
||||
friend class Layer;
|
||||
friend class LayerDim;
|
||||
#ifdef QTI_BSP
|
||||
friend class ExLayer;
|
||||
#endif
|
||||
friend class MonitoredProducer;
|
||||
friend class LayerBlur;
|
||||
|
||||
@ -553,6 +556,9 @@ private:
|
||||
mat4 mColorMatrix;
|
||||
bool mHasColorMatrix;
|
||||
|
||||
mat4 mSecondaryColorMatrix;
|
||||
bool mHasSecondaryColorMatrix;
|
||||
|
||||
// Static screen stats
|
||||
bool mHasPoweredOff;
|
||||
static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
|
||||
|
@ -249,4 +249,50 @@ TEST_F(LayerUpdateTest, LayerResizeWorks) {
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that if we move and resize a surface in the same
|
||||
// transaction, we don't reposition the surface and draw
|
||||
// using the incorrect buffer size
|
||||
TEST_F(LayerUpdateTest, LayerMoveAndResizeWorks) {
|
||||
sp<ScreenCapture> sc;
|
||||
{
|
||||
SCOPED_TRACE("before resize and reposition");
|
||||
ScreenCapture::captureScreen(&sc);
|
||||
sc->checkPixel( 0, 12, 63, 63, 195);
|
||||
sc->checkPixel( 75, 75, 195, 63, 63);
|
||||
sc->checkPixel(145, 145, 63, 63, 195);
|
||||
}
|
||||
|
||||
ALOGD("resizing and repositioning");
|
||||
SurfaceComposerClient::openGlobalTransaction();
|
||||
ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 0));
|
||||
ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(64, 128));
|
||||
SurfaceComposerClient::closeGlobalTransaction(true);
|
||||
|
||||
ALOGD("resized and repositioned");
|
||||
{
|
||||
// This should not reflect the new size, position or color because SurfaceFlinger
|
||||
// has not yet received a buffer of the correct size.
|
||||
SCOPED_TRACE("after resize, before redraw");
|
||||
ScreenCapture::captureScreen(&sc);
|
||||
sc->checkPixel( 0, 12, 63, 63, 195);
|
||||
sc->checkPixel( 75, 75, 195, 63, 63);
|
||||
sc->checkPixel(145, 145, 63, 63, 195);
|
||||
}
|
||||
|
||||
ALOGD("drawing");
|
||||
fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
|
||||
waitForPostedBuffers();
|
||||
ALOGD("drawn");
|
||||
{
|
||||
// This should reflect the new size, position and the new color.
|
||||
SCOPED_TRACE("after redraw");
|
||||
ScreenCapture::captureScreen(&sc);
|
||||
sc->checkPixel( 64, 0, 63, 195, 63);
|
||||
// This should pass to imply that we didn't have a frame where the
|
||||
// surface was moved but not yet resized even though the operations
|
||||
// were part of the same transaction
|
||||
sc->checkPixel( 64, 75, 63, 195, 63);
|
||||
sc->checkPixel(145, 145, 63, 63, 195);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user