Merge "Fix sanitizer in ISensorService list functions."
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 07a6adb..1b90579 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -152,6 +152,8 @@
{ "freq", "CPU Frequency", 0, {
{ REQ, "events/power/cpu_frequency/enable" },
{ OPT, "events/power/clock_set_rate/enable" },
+ { OPT, "events/power/clock_disable/enable" },
+ { OPT, "events/power/clock_enable/enable" },
{ OPT, "events/power/cpu_frequency_limits/enable" },
} },
{ "membus", "Memory Bus Utilization", 0, {
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 380921d..b94d3d5 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -690,6 +690,7 @@
printf("Kernel: ");
DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
+ ds.RunCommand("UPTIME", {"uptime"}, CommandOptions::DEFAULT);
printf("Bugreport format version: %s\n", version_.c_str());
printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
@@ -1092,6 +1093,7 @@
DurationReporter duration_reporter("DUMPSTATE");
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
+ /* TODO: Remove duplicate uptime call when tools use it from header */
RunCommand("UPTIME", {"uptime"});
DumpBlockStatFiles();
dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
diff --git a/cmds/flatland/Android.mk b/cmds/flatland/Android.mk
index c295167..7aa111c 100644
--- a/cmds/flatland/Android.mk
+++ b/cmds/flatland/Android.mk
@@ -8,6 +8,8 @@
Renderers.cpp \
Main.cpp \
+LOCAL_CFLAGS := -Wall -Werror
+
LOCAL_MODULE:= flatland
LOCAL_MODULE_TAGS := tests
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index ec1e543..3d7cac0 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -284,7 +284,6 @@
public:
Layer() :
- mFirstFrame(true),
mGLHelper(NULL),
mSurface(EGL_NO_SURFACE) {
}
@@ -358,8 +357,6 @@
}
private:
- bool mFirstFrame;
-
LayerDesc mDesc;
GLHelper* mGLHelper;
@@ -389,7 +386,6 @@
ATRACE_CALL();
bool result;
- EGLint resulte;
float scaleFactor = float(mDesc.runHeights[mInstance]) /
float(mDesc.height);
@@ -465,7 +461,6 @@
ATRACE_CALL();
bool result;
- status_t err;
resetColorGenerator();
diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk
index 36bbdf5..e1e2204 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/cmds/ip-up-vpn/Android.mk
@@ -18,6 +18,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := ip-up-vpn.c
+LOCAL_CFLAGS := -Wall -Werror
LOCAL_SHARED_LIBRARIES := libcutils liblog
LOCAL_MODULE := ip-up-vpn
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
diff --git a/cmds/rawbu/Android.mk b/cmds/rawbu/Android.mk
index b580390..9322151 100644
--- a/cmds/rawbu/Android.mk
+++ b/cmds/rawbu/Android.mk
@@ -5,6 +5,8 @@
LOCAL_SRC_FILES:= backup.cpp
+LOCAL_CFLAGS := -Wall -Werror
+
LOCAL_SHARED_LIBRARIES := libcutils libc
LOCAL_MODULE:= rawbu
diff --git a/cmds/rawbu/backup.cpp b/cmds/rawbu/backup.cpp
index ff6719f..0072281 100644
--- a/cmds/rawbu/backup.cpp
+++ b/cmds/rawbu/backup.cpp
@@ -129,7 +129,6 @@
}
if(S_ISDIR(statBuffer.st_mode)) {
- int i;
char *newpath;
newpath = strdup(nameBuffer);
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
index dda80bb..71a5e23 100644
--- a/cmds/surfacereplayer/proto/Android.bp
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -3,6 +3,10 @@
srcs: [
"src/trace.proto",
],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
proto: {
type: "lite",
export_proto_headers: true,
diff --git a/libs/hwc2onfbadapter/Android.bp b/libs/hwc2onfbadapter/Android.bp
new file mode 100644
index 0000000..73a41f7
--- /dev/null
+++ b/libs/hwc2onfbadapter/Android.bp
@@ -0,0 +1,33 @@
+// Copyright 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.
+
+cc_library_shared {
+ name: "libhwc2onfbadapter",
+ vendor: true,
+
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+
+ srcs: [
+ "HWC2OnFbAdapter.cpp",
+ ],
+
+ header_libs: ["libhardware_headers"],
+ shared_libs: ["liblog", "libsync"],
+ export_include_dirs: ["include"],
+}
diff --git a/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp b/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp
new file mode 100644
index 0000000..7c9e651
--- /dev/null
+++ b/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp
@@ -0,0 +1,887 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#define LOG_TAG "HWC2OnFbAdapter"
+
+//#define LOG_NDEBUG 0
+
+#include "hwc2onfbadapter/HWC2OnFbAdapter.h"
+
+#include <algorithm>
+#include <type_traits>
+
+#include <inttypes.h>
+#include <time.h>
+#include <sys/prctl.h>
+#include <unistd.h> // for close
+
+#include <hardware/fb.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+namespace android {
+
+namespace {
+
+void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (outBuffer) {
+ *outSize = adapter.getDebugString().copy(outBuffer, *outSize);
+ } else {
+ adapter.updateDebugString();
+ *outSize = adapter.getDebugString().size();
+ }
+}
+
+int32_t registerCallbackHook(hwc2_device_t* device, int32_t descriptor,
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ switch (descriptor) {
+ case HWC2_CALLBACK_HOTPLUG:
+ if (pointer) {
+ reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer)(callbackData, adapter.getDisplayId(),
+ HWC2_CONNECTION_CONNECTED);
+ }
+ break;
+ case HWC2_CALLBACK_REFRESH:
+ break;
+ case HWC2_CALLBACK_VSYNC:
+ adapter.setVsyncCallback(reinterpret_cast<HWC2_PFN_VSYNC>(pointer), callbackData);
+ break;
+ default:
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* /*device*/) {
+ return 0;
+}
+
+int32_t createVirtualDisplayHook(hwc2_device_t* /*device*/, uint32_t /*width*/, uint32_t /*height*/,
+ int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) {
+ return HWC2_ERROR_NO_RESOURCES;
+}
+
+int32_t destroyVirtualDisplayHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/) {
+ return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t setOutputBufferHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/,
+ buffer_handle_t /*buffer*/, int32_t /*releaseFence*/) {
+ return HWC2_ERROR_BAD_DISPLAY;
+}
+
+int32_t getDisplayNameHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize,
+ char* outName) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ const auto& info = adapter.getInfo();
+ if (outName) {
+ *outSize = info.name.copy(outName, *outSize);
+ } else {
+ *outSize = info.name.size();
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayTypeHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outType) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outType = HWC2_DISPLAY_TYPE_PHYSICAL;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDozeSupportHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outSupport = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getHdrCapabilitiesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+ int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outNumTypes = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*mode*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // pretend that it works
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setVsyncEnabledHook(hwc2_device_t* device, hwc2_display_t display, int32_t enabled) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ adapter.enableVsync(enabled == HWC2_VSYNC_ENABLE);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getColorModesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes,
+ int32_t* outModes) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (outModes) {
+ if (*outNumModes > 0) {
+ outModes[0] = HAL_COLOR_MODE_NATIVE;
+ *outNumModes = 1;
+ }
+ } else {
+ *outNumModes = 1;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t mode) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (mode != HAL_COLOR_MODE_NATIVE) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setColorTransformHook(hwc2_device_t* device, hwc2_display_t display,
+ const float* /*matrix*/, int32_t /*hint*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // we always force client composition
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getClientTargetSupportHook(hwc2_device_t* device, hwc2_display_t display, uint32_t width,
+ uint32_t height, int32_t format, int32_t dataspace) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (dataspace != HAL_DATASPACE_UNKNOWN) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
+ const auto& info = adapter.getInfo();
+ return (info.width == width && info.height == height && info.format == format)
+ ? HWC2_ERROR_NONE
+ : HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t setClientTargetHook(hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target,
+ int32_t acquireFence, int32_t dataspace, hwc_region_t /*damage*/) {
+ if (acquireFence >= 0) {
+ sync_wait(acquireFence, -1);
+ close(acquireFence);
+ }
+
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (dataspace != HAL_DATASPACE_UNKNOWN) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ // no state change
+ adapter.setBuffer(target);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayConfigsHook(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* outNumConfigs, hwc2_config_t* outConfigs) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (outConfigs) {
+ if (*outNumConfigs > 0) {
+ outConfigs[0] = adapter.getConfigId();
+ *outNumConfigs = 1;
+ }
+ } else {
+ *outNumConfigs = 1;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayAttributeHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config,
+ int32_t attribute, int32_t* outValue) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getConfigId() != config) {
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+
+ const auto& info = adapter.getInfo();
+ switch (attribute) {
+ case HWC2_ATTRIBUTE_WIDTH:
+ *outValue = int32_t(info.width);
+ break;
+ case HWC2_ATTRIBUTE_HEIGHT:
+ *outValue = int32_t(info.height);
+ break;
+ case HWC2_ATTRIBUTE_VSYNC_PERIOD:
+ *outValue = int32_t(info.vsync_period_ns);
+ break;
+ case HWC2_ATTRIBUTE_DPI_X:
+ *outValue = int32_t(info.xdpi_scaled);
+ break;
+ case HWC2_ATTRIBUTE_DPI_Y:
+ *outValue = int32_t(info.ydpi_scaled);
+ break;
+ default:
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getActiveConfigHook(hwc2_device_t* device, hwc2_display_t display,
+ hwc2_config_t* outConfig) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outConfig = adapter.getConfigId();
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getConfigId() != config) {
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t validateDisplayHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes,
+ uint32_t* outNumRequests) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ const auto& dirtyLayers = adapter.getDirtyLayers();
+ *outNumTypes = dirtyLayers.size();
+ *outNumRequests = 0;
+
+ if (*outNumTypes > 0) {
+ adapter.setState(HWC2OnFbAdapter::State::VALIDATED_WITH_CHANGES);
+ return HWC2_ERROR_HAS_CHANGES;
+ } else {
+ adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+ return HWC2_ERROR_NONE;
+ }
+}
+
+int32_t getChangedCompositionTypesHook(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* outNumElements, hwc2_layer_t* outLayers,
+ int32_t* outTypes) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ // request client composition for all layers
+ const auto& dirtyLayers = adapter.getDirtyLayers();
+ if (outLayers && outTypes) {
+ *outNumElements = std::min(*outNumElements, uint32_t(dirtyLayers.size()));
+ auto iter = dirtyLayers.cbegin();
+ for (uint32_t i = 0; i < *outNumElements; i++) {
+ outLayers[i] = *iter++;
+ outTypes[i] = HWC2_COMPOSITION_CLIENT;
+ }
+ } else {
+ *outNumElements = dirtyLayers.size();
+ }
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getDisplayRequestsHook(hwc2_device_t* device, hwc2_display_t display,
+ int32_t* outDisplayRequests, uint32_t* outNumElements,
+ hwc2_layer_t* /*outLayers*/, int32_t* /*outLayerRequests*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ *outDisplayRequests = 0;
+ *outNumElements = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t acceptDisplayChangesHook(hwc2_device_t* device, hwc2_display_t display) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ adapter.clearDirtyLayers();
+ adapter.setState(HWC2OnFbAdapter::State::VALIDATED);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t presentDisplayHook(hwc2_device_t* device, hwc2_display_t display,
+ int32_t* outPresentFence) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (adapter.getState() != HWC2OnFbAdapter::State::VALIDATED) {
+ return HWC2_ERROR_NOT_VALIDATED;
+ }
+
+ adapter.postBuffer();
+ *outPresentFence = -1;
+
+ return HWC2_ERROR_NONE;
+}
+
+int32_t getReleaseFencesHook(hwc2_device_t* device, hwc2_display_t display,
+ uint32_t* outNumElements, hwc2_layer_t* /*outLayers*/,
+ int32_t* /*outFences*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outNumElements = 0;
+ return HWC2_ERROR_NONE;
+}
+
+int32_t createLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t* outLayer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ *outLayer = adapter.addLayer();
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+int32_t destroyLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ if (adapter.removeLayer(layer)) {
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+ } else {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+}
+
+int32_t setCursorPositionHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t /*layer*/,
+ int32_t /*x*/, int32_t /*y*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // always an error
+ return HWC2_ERROR_BAD_LAYER;
+}
+
+int32_t setLayerBufferHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+ buffer_handle_t /*buffer*/, int32_t acquireFence) {
+ if (acquireFence >= 0) {
+ sync_wait(acquireFence, -1);
+ close(acquireFence);
+ }
+
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.hasLayer(layer)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ // no state change
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerSurfaceDamageHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+ hwc_region_t /*damage*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.hasLayer(layer)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ // no state change
+ return HWC2_ERROR_NONE;
+}
+
+int32_t setLayerCompositionTypeHook(hwc2_device_t* device, hwc2_display_t display,
+ hwc2_layer_t layer, int32_t type) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.markLayerDirty(layer, type != HWC2_COMPOSITION_CLIENT)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+template <typename... Args>
+int32_t setLayerStateHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer,
+ Args... /*args*/) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ if (adapter.getDisplayId() != display) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+ if (!adapter.hasLayer(layer)) {
+ return HWC2_ERROR_BAD_LAYER;
+ }
+
+ adapter.setState(HWC2OnFbAdapter::State::MODIFIED);
+ return HWC2_ERROR_NONE;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function) {
+ static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+ return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+hwc2_function_pointer_t getFunctionHook(hwc2_device_t* /*device*/, int32_t descriptor) {
+ switch (descriptor) {
+ // global functions
+ case HWC2_FUNCTION_DUMP:
+ return asFP<HWC2_PFN_DUMP>(dumpHook);
+ case HWC2_FUNCTION_REGISTER_CALLBACK:
+ return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+ // virtual display functions
+ case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT:
+ return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(getMaxVirtualDisplayCountHook);
+ case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY:
+ return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(createVirtualDisplayHook);
+ case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY:
+ return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(destroyVirtualDisplayHook);
+ case HWC2_FUNCTION_SET_OUTPUT_BUFFER:
+ return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(setOutputBufferHook);
+
+ // display functions
+ case HWC2_FUNCTION_GET_DISPLAY_NAME:
+ return asFP<HWC2_PFN_GET_DISPLAY_NAME>(getDisplayNameHook);
+ case HWC2_FUNCTION_GET_DISPLAY_TYPE:
+ return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(getDisplayTypeHook);
+ case HWC2_FUNCTION_GET_DOZE_SUPPORT:
+ return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(getDozeSupportHook);
+ case HWC2_FUNCTION_GET_HDR_CAPABILITIES:
+ return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(getHdrCapabilitiesHook);
+ case HWC2_FUNCTION_SET_POWER_MODE:
+ return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+ case HWC2_FUNCTION_SET_VSYNC_ENABLED:
+ return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+ case HWC2_FUNCTION_GET_COLOR_MODES:
+ return asFP<HWC2_PFN_GET_COLOR_MODES>(getColorModesHook);
+ case HWC2_FUNCTION_SET_COLOR_MODE:
+ return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
+ case HWC2_FUNCTION_SET_COLOR_TRANSFORM:
+ return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+ case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT:
+ return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(getClientTargetSupportHook);
+ case HWC2_FUNCTION_SET_CLIENT_TARGET:
+ return asFP<HWC2_PFN_SET_CLIENT_TARGET>(setClientTargetHook);
+
+ // config functions
+ case HWC2_FUNCTION_GET_DISPLAY_CONFIGS:
+ return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(getDisplayConfigsHook);
+ case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE:
+ return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(getDisplayAttributeHook);
+ case HWC2_FUNCTION_GET_ACTIVE_CONFIG:
+ return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(getActiveConfigHook);
+ case HWC2_FUNCTION_SET_ACTIVE_CONFIG:
+ return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(setActiveConfigHook);
+
+ // validate/present functions
+ case HWC2_FUNCTION_VALIDATE_DISPLAY:
+ return asFP<HWC2_PFN_VALIDATE_DISPLAY>(validateDisplayHook);
+ case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES:
+ return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(getChangedCompositionTypesHook);
+ case HWC2_FUNCTION_GET_DISPLAY_REQUESTS:
+ return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(getDisplayRequestsHook);
+ case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES:
+ return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(acceptDisplayChangesHook);
+ case HWC2_FUNCTION_PRESENT_DISPLAY:
+ return asFP<HWC2_PFN_PRESENT_DISPLAY>(presentDisplayHook);
+ case HWC2_FUNCTION_GET_RELEASE_FENCES:
+ return asFP<HWC2_PFN_GET_RELEASE_FENCES>(getReleaseFencesHook);
+
+ // layer create/destroy
+ case HWC2_FUNCTION_CREATE_LAYER:
+ return asFP<HWC2_PFN_CREATE_LAYER>(createLayerHook);
+ case HWC2_FUNCTION_DESTROY_LAYER:
+ return asFP<HWC2_PFN_DESTROY_LAYER>(destroyLayerHook);
+
+ // layer functions; validateDisplay not required
+ case HWC2_FUNCTION_SET_CURSOR_POSITION:
+ return asFP<HWC2_PFN_SET_CURSOR_POSITION>(setCursorPositionHook);
+ case HWC2_FUNCTION_SET_LAYER_BUFFER:
+ return asFP<HWC2_PFN_SET_LAYER_BUFFER>(setLayerBufferHook);
+ case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE:
+ return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(setLayerSurfaceDamageHook);
+
+ // layer state functions; validateDisplay required
+ case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE:
+ return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(setLayerCompositionTypeHook);
+ case HWC2_FUNCTION_SET_LAYER_BLEND_MODE:
+ return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(setLayerStateHook<int32_t>);
+ case HWC2_FUNCTION_SET_LAYER_COLOR:
+ return asFP<HWC2_PFN_SET_LAYER_COLOR>(setLayerStateHook<hwc_color_t>);
+ case HWC2_FUNCTION_SET_LAYER_DATASPACE:
+ return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerStateHook<int32_t>);
+ case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME:
+ return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(setLayerStateHook<hwc_rect_t>);
+ case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA:
+ return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(setLayerStateHook<float>);
+ case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM:
+ return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(setLayerStateHook<buffer_handle_t>);
+ case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP:
+ return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(setLayerStateHook<hwc_frect_t>);
+ case HWC2_FUNCTION_SET_LAYER_TRANSFORM:
+ return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerStateHook<int32_t>);
+ case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION:
+ return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(setLayerStateHook<hwc_region_t>);
+ case HWC2_FUNCTION_SET_LAYER_Z_ORDER:
+ return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerStateHook<uint32_t>);
+
+ default:
+ ALOGE("unknown function descriptor %d", descriptor);
+ return nullptr;
+ }
+}
+
+void getCapabilitiesHook(hwc2_device_t* /*device*/, uint32_t* outCount,
+ int32_t* /*outCapabilities*/) {
+ *outCount = 0;
+}
+
+int closeHook(hw_device_t* device) {
+ auto& adapter = HWC2OnFbAdapter::cast(device);
+ adapter.close();
+ return 0;
+}
+
+} // anonymous namespace
+
+HWC2OnFbAdapter::HWC2OnFbAdapter(framebuffer_device_t* fbDevice)
+ : hwc2_device_t(), mFbDevice(fbDevice) {
+ common.close = closeHook;
+ hwc2_device::getCapabilities = getCapabilitiesHook;
+ hwc2_device::getFunction = getFunctionHook;
+
+ mFbInfo.name = "fbdev";
+ mFbInfo.width = mFbDevice->width;
+ mFbInfo.height = mFbDevice->height;
+ mFbInfo.format = mFbDevice->format;
+ mFbInfo.vsync_period_ns = int(1e9 / mFbDevice->fps);
+ mFbInfo.xdpi_scaled = int(mFbDevice->xdpi * 1000.0f);
+ mFbInfo.ydpi_scaled = int(mFbDevice->ydpi * 1000.0f);
+
+ mVsyncThread.start(0, mFbInfo.vsync_period_ns);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hw_device_t* device) {
+ return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hwc2_device_t* device) {
+ return *reinterpret_cast<HWC2OnFbAdapter*>(device);
+}
+
+hwc2_display_t HWC2OnFbAdapter::getDisplayId() {
+ return 0;
+}
+
+hwc2_config_t HWC2OnFbAdapter::getConfigId() {
+ return 0;
+}
+
+void HWC2OnFbAdapter::close() {
+ mVsyncThread.stop();
+ framebuffer_close(mFbDevice);
+}
+
+const HWC2OnFbAdapter::Info& HWC2OnFbAdapter::getInfo() const {
+ return mFbInfo;
+}
+
+void HWC2OnFbAdapter::updateDebugString() {
+ if (mFbDevice->common.version >= 1 && mFbDevice->dump) {
+ char buffer[4096];
+ mFbDevice->dump(mFbDevice, buffer, sizeof(buffer));
+ buffer[sizeof(buffer) - 1] = '\0';
+
+ mDebugString = buffer;
+ }
+}
+
+const std::string& HWC2OnFbAdapter::getDebugString() const {
+ return mDebugString;
+}
+
+void HWC2OnFbAdapter::setState(State state) {
+ mState = state;
+}
+
+HWC2OnFbAdapter::State HWC2OnFbAdapter::getState() const {
+ return mState;
+}
+
+hwc2_layer_t HWC2OnFbAdapter::addLayer() {
+ hwc2_layer_t id = ++mNextLayerId;
+
+ mLayers.insert(id);
+ mDirtyLayers.insert(id);
+
+ return id;
+}
+
+bool HWC2OnFbAdapter::removeLayer(hwc2_layer_t layer) {
+ mDirtyLayers.erase(layer);
+ return mLayers.erase(layer);
+}
+
+bool HWC2OnFbAdapter::hasLayer(hwc2_layer_t layer) const {
+ return mLayers.count(layer) > 0;
+}
+
+bool HWC2OnFbAdapter::markLayerDirty(hwc2_layer_t layer, bool dirty) {
+ if (mLayers.count(layer) == 0) {
+ return false;
+ }
+
+ if (dirty) {
+ mDirtyLayers.insert(layer);
+ } else {
+ mDirtyLayers.erase(layer);
+ }
+
+ return true;
+}
+
+const std::unordered_set<hwc2_layer_t>& HWC2OnFbAdapter::getDirtyLayers() const {
+ return mDirtyLayers;
+}
+
+void HWC2OnFbAdapter::clearDirtyLayers() {
+ mDirtyLayers.clear();
+}
+
+/*
+ * For each frame, SurfaceFlinger
+ *
+ * - peforms GLES composition
+ * - calls eglSwapBuffers
+ * - calls setClientTarget, which maps to setBuffer below
+ * - calls presentDisplay, which maps to postBuffer below
+ *
+ * setBuffer should be a good place to call compositionComplete.
+ *
+ * As for post, it
+ *
+ * - schedules the buffer for presentation on the next vsync
+ * - locks the buffer and blocks all other users trying to lock it
+ *
+ * It does not give us a way to return a present fence, and we need to live
+ * with that. The implication is that, when we are double-buffered,
+ * SurfaceFlinger assumes the front buffer is available for rendering again
+ * immediately after the back buffer is posted. The locking semantics
+ * hopefully are strong enough that the rendering will be blocked.
+ */
+void HWC2OnFbAdapter::setBuffer(buffer_handle_t buffer) {
+ if (mFbDevice->compositionComplete) {
+ mFbDevice->compositionComplete(mFbDevice);
+ }
+ mBuffer = buffer;
+}
+
+bool HWC2OnFbAdapter::postBuffer() {
+ int error = 0;
+ if (mBuffer) {
+ error = mFbDevice->post(mFbDevice, mBuffer);
+ }
+
+ return error == 0;
+}
+
+void HWC2OnFbAdapter::setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+ mVsyncThread.setCallback(callback, data);
+}
+
+void HWC2OnFbAdapter::enableVsync(bool enable) {
+ mVsyncThread.enableCallback(enable);
+}
+
+int64_t HWC2OnFbAdapter::VsyncThread::now() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return int64_t(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec;
+}
+
+bool HWC2OnFbAdapter::VsyncThread::sleepUntil(int64_t t) {
+ struct timespec ts;
+ ts.tv_sec = t / 1'000'000'000;
+ ts.tv_nsec = t % 1'000'000'000;
+
+ while (true) {
+ int error = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr);
+ if (error) {
+ if (error == EINTR) {
+ continue;
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+}
+
+void HWC2OnFbAdapter::VsyncThread::start(int64_t firstVsync, int64_t period) {
+ mNextVsync = firstVsync;
+ mPeriod = period;
+ mStarted = true;
+ mThread = std::thread(&VsyncThread::vsyncLoop, this);
+}
+
+void HWC2OnFbAdapter::VsyncThread::stop() {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mStarted = false;
+ }
+ mCondition.notify_all();
+ mThread.join();
+}
+
+void HWC2OnFbAdapter::VsyncThread::setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mCallback = callback;
+ mCallbackData = data;
+}
+
+void HWC2OnFbAdapter::VsyncThread::enableCallback(bool enable) {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mCallbackEnabled = enable;
+ }
+ mCondition.notify_all();
+}
+
+void HWC2OnFbAdapter::VsyncThread::vsyncLoop() {
+ prctl(PR_SET_NAME, "VsyncThread", 0, 0, 0);
+
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (!mStarted) {
+ return;
+ }
+
+ while (true) {
+ if (!mCallbackEnabled) {
+ mCondition.wait(lock, [this] { return mCallbackEnabled || !mStarted; });
+ if (!mStarted) {
+ break;
+ }
+ }
+
+ lock.unlock();
+
+ // adjust mNextVsync if necessary
+ int64_t t = now();
+ if (mNextVsync < t) {
+ int64_t n = (t - mNextVsync + mPeriod - 1) / mPeriod;
+ mNextVsync += mPeriod * n;
+ }
+ bool fire = sleepUntil(mNextVsync);
+
+ lock.lock();
+
+ if (fire) {
+ ALOGV("VsyncThread(%" PRId64 ")", mNextVsync);
+ if (mCallback) {
+ mCallback(mCallbackData, getDisplayId(), mNextVsync);
+ }
+ mNextVsync += mPeriod;
+ }
+ }
+}
+
+} // namespace android
diff --git a/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h b/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
new file mode 100644
index 0000000..d6272fd
--- /dev/null
+++ b/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017 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_SF_HWC2_ON_FB_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_FB_ADAPTER_H
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+#include <thread>
+#include <unordered_set>
+
+#include <hardware/hwcomposer2.h>
+
+struct framebuffer_device_t;
+
+namespace android {
+
+class HWC2OnFbAdapter : public hwc2_device_t {
+public:
+ HWC2OnFbAdapter(framebuffer_device_t* fbDevice);
+
+ static HWC2OnFbAdapter& cast(hw_device_t* device);
+ static HWC2OnFbAdapter& cast(hwc2_device_t* device);
+
+ static hwc2_display_t getDisplayId();
+ static hwc2_config_t getConfigId();
+
+ void close();
+
+ struct Info {
+ std::string name;
+ uint32_t width;
+ uint32_t height;
+ int format;
+ int vsync_period_ns;
+ int xdpi_scaled;
+ int ydpi_scaled;
+ };
+ const Info& getInfo() const;
+
+ void updateDebugString();
+ const std::string& getDebugString() const;
+
+ enum class State {
+ MODIFIED,
+ VALIDATED_WITH_CHANGES,
+ VALIDATED,
+ };
+ void setState(State state);
+ State getState() const;
+
+ hwc2_layer_t addLayer();
+ bool removeLayer(hwc2_layer_t layer);
+ bool hasLayer(hwc2_layer_t layer) const;
+ bool markLayerDirty(hwc2_layer_t layer, bool dirty);
+ const std::unordered_set<hwc2_layer_t>& getDirtyLayers() const;
+ void clearDirtyLayers();
+
+ void setBuffer(buffer_handle_t buffer);
+ bool postBuffer();
+
+ void setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+ void enableVsync(bool enable);
+
+private:
+ framebuffer_device_t* mFbDevice{nullptr};
+ Info mFbInfo{};
+
+ std::string mDebugString;
+
+ State mState{State::MODIFIED};
+
+ uint64_t mNextLayerId{0};
+ std::unordered_set<hwc2_layer_t> mLayers;
+ std::unordered_set<hwc2_layer_t> mDirtyLayers;
+
+ buffer_handle_t mBuffer{nullptr};
+
+ class VsyncThread {
+ public:
+ static int64_t now();
+ static bool sleepUntil(int64_t t);
+
+ void start(int64_t first, int64_t period);
+ void stop();
+ void setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data);
+ void enableCallback(bool enable);
+
+ private:
+ void vsyncLoop();
+ bool waitUntilNextVsync();
+
+ std::thread mThread;
+ int64_t mNextVsync{0};
+ int64_t mPeriod{0};
+
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ bool mStarted{false};
+ HWC2_PFN_VSYNC mCallback{nullptr};
+ hwc2_callback_data_t mCallbackData{nullptr};
+ bool mCallbackEnabled{false};
+ };
+ VsyncThread mVsyncThread;
+};
+
+} // namespace android
+
+#endif // ANDROID_SF_HWC2_ON_FB_ADAPTER_H
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 57eee12..e54f147 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -107,7 +107,7 @@
// this is the strategy that applications will actually use. Be very careful
// when adjusting the default strategy because it can dramatically affect
// (often in a bad way) the user experience.
-const char* VelocityTracker::DEFAULT_STRATEGY = "impulse";
+const char* VelocityTracker::DEFAULT_STRATEGY = "lsq2";
VelocityTracker::VelocityTracker(const char* strategy) :
mLastEventTime(0), mCurrentPointerIdBits(0), mActivePointerId(-1) {
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 3c99f99..a5cf9ae 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -33,6 +33,7 @@
const int kUsage = 0;
const uint64_t kContext = 42;
const size_t kMaxConsumerCount = 63;
+const int kPollTimeoutMs = 100;
using LibBufferHubTest = ::testing::Test;
@@ -51,51 +52,51 @@
// Producer state mask is unique, i.e. 1.
EXPECT_EQ(p->buffer_state_bit(), kProducerStateBit);
// Consumer state mask cannot have producer bit on.
- EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0);
+ EXPECT_EQ(c->buffer_state_bit() & kProducerStateBit, 0U);
// Consumer state mask must be a single, i.e. power of 2.
- EXPECT_NE(c->buffer_state_bit(), 0);
- EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0);
+ EXPECT_NE(c->buffer_state_bit(), 0U);
+ EXPECT_EQ(c->buffer_state_bit() & (c->buffer_state_bit() - 1), 0U);
// Consumer state mask cannot have producer bit on.
- EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0);
+ EXPECT_EQ(c2->buffer_state_bit() & kProducerStateBit, 0U);
// Consumer state mask must be a single, i.e. power of 2.
- EXPECT_NE(c2->buffer_state_bit(), 0);
- EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0);
+ EXPECT_NE(c2->buffer_state_bit(), 0U);
+ EXPECT_EQ(c2->buffer_state_bit() & (c2->buffer_state_bit() - 1), 0U);
// Each consumer should have unique bit.
- EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0);
+ EXPECT_EQ(c->buffer_state_bit() & c2->buffer_state_bit(), 0U);
// Initial state: producer not available, consumers not available.
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
// New state: producer not available, consumers available.
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
- EXPECT_EQ(1, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
uint64_t context;
LocalHandle fence;
EXPECT_EQ(0, c->Acquire(&fence, &context));
EXPECT_EQ(kContext, context);
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(1, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c2->Acquire(&fence, &context));
EXPECT_EQ(kContext, context);
- EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->Release(LocalHandle()));
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c2->Discard());
- EXPECT_EQ(1, RETRY_EINTR(p->Poll(100)));
+ EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->Gain(&fence));
- EXPECT_EQ(0, RETRY_EINTR(p->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c->Poll(100)));
- EXPECT_EQ(0, RETRY_EINTR(c2->Poll(100)));
+ EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+ EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
}
TEST_F(LibBufferHubTest, TestEpoll) {
@@ -137,7 +138,8 @@
// Post the producer and check for consumer signal.
EXPECT_EQ(0, p->Post({}, kContext));
- ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+ ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
ASSERT_TRUE(events[0].events & EPOLLIN);
ASSERT_EQ(c->event_fd(), events[0].data.fd);
@@ -145,10 +147,14 @@
event = events[0];
// Check for events again. Edge-triggered mode should prevent any.
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
// Translate the events.
auto event_status = c->GetEventMask(event.events);
@@ -156,7 +162,8 @@
ASSERT_TRUE(event_status.get() & EPOLLIN);
// Check for events again. Edge-triggered mode should prevent any.
- EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 100));
+ EXPECT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
+ kPollTimeoutMs));
}
TEST_F(LibBufferHubTest, TestStateMask) {
@@ -171,7 +178,7 @@
cs[i] = BufferConsumer::Import(p->CreateConsumer());
ASSERT_TRUE(cs[i].get() != nullptr);
// Expect all buffers have unique state mask.
- EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+ EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
buffer_state_bits |= cs[i]->buffer_state_bit();
}
EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
@@ -187,7 +194,7 @@
cs[i] = BufferConsumer::Import(p->CreateConsumer());
ASSERT_TRUE(cs[i].get() != nullptr);
// The released state mask will be reused.
- EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0);
+ EXPECT_EQ(buffer_state_bits & cs[i]->buffer_state_bit(), 0U);
buffer_state_bits |= cs[i]->buffer_state_bit();
EXPECT_EQ(buffer_state_bits, kProducerStateBit | kConsumerStateMask);
}
@@ -229,7 +236,7 @@
// Release in acquired state should succeed.
EXPECT_EQ(0, c->Release(LocalHandle()));
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// Release, acquire, and post in released state should fail.
EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
@@ -277,7 +284,7 @@
EXPECT_FALSE(invalid_fence.IsValid());
// Acquire in posted state should succeed.
- EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
EXPECT_FALSE(invalid_fence.IsValid());
EXPECT_EQ(p->buffer_state(), c->buffer_state());
@@ -292,7 +299,7 @@
// Release in acquired state should succeed.
EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(p->buffer_state(), c->buffer_state());
EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
@@ -330,7 +337,7 @@
EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
// The buffer should stay in posted stay until a consumer picks it up.
- EXPECT_GE(0, RETRY_EINTR(p->Poll(100)));
+ EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// A new consumer should still be able to acquire the buffer immediately.
std::unique_ptr<BufferConsumer> c =
@@ -361,7 +368,7 @@
for (size_t i = 0; i < kMaxConsumerCount; i++) {
EXPECT_TRUE(IsBufferPosted(cs[i]->buffer_state(),
cs[i]->buffer_state_bit()));
- EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
EXPECT_TRUE(IsBufferAcquired(p->buffer_state()));
}
@@ -373,7 +380,7 @@
EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
}
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
// Buffer state cross all clients must be consistent.
@@ -399,7 +406,7 @@
// Post the gained buffer should signal already created consumer.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
EXPECT_TRUE(IsBufferPosted(p->buffer_state()));
- EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
EXPECT_TRUE(IsBufferAcquired(c->buffer_state()));
}
@@ -440,7 +447,7 @@
// Post, acquire, and release the buffer..
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
- EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
@@ -450,7 +457,7 @@
BufferConsumer::Import(p->CreateConsumer());
ASSERT_TRUE(c2.get() != nullptr);
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
EXPECT_TRUE(IsBufferGained(p->buffer_state()));
@@ -470,7 +477,7 @@
Metadata m = {1, 3};
EXPECT_EQ(0, p->Post(LocalHandle(), m));
- EXPECT_LE(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
LocalHandle fence;
Metadata m2 = {};
@@ -503,7 +510,7 @@
// buffer allocation.
OverSizedMetadata evil_meta = {};
EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
- EXPECT_GE(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
// It is ok to post metadata smaller than originally requested during
// buffer allocation.
@@ -638,7 +645,7 @@
EXPECT_EQ(0, p->Post<void>(LocalHandle()));
EXPECT_EQ(0, c->Acquire(&fence));
EXPECT_EQ(0, c->Release(LocalHandle()));
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// Test that removing persistence and closing the producer orphans the
// consumer.
@@ -679,7 +686,7 @@
// Should acquire a valid fence.
LocalHandle f2;
- EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
EXPECT_TRUE(f2.IsValid());
// The original fence and acquired fence should have different fd number.
@@ -689,14 +696,14 @@
// Signal the original fence will trigger the new fence.
eventfd_write(f1.Get(), 1);
// Now the original FD has been signaled.
- EXPECT_LT(0, PollFd(f2.Get(), 10));
+ EXPECT_LT(0, PollFd(f2.Get(), kPollTimeoutMs));
// Release the consumer with an invalid fence.
EXPECT_EQ(0, c->ReleaseAsync(&meta, LocalHandle()));
// Should gain an invalid fence.
LocalHandle f3;
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->GainAsync(&meta, &f3));
EXPECT_FALSE(f3.IsValid());
@@ -705,10 +712,10 @@
// Should acquire a valid fence and it's already signalled.
LocalHandle f4;
- EXPECT_LT(0, RETRY_EINTR(c->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
EXPECT_TRUE(f4.IsValid());
- EXPECT_LT(0, PollFd(f4.Get(), 10));
+ EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
// Release with an unsignalled fence and signal it immediately after release
// without producer gainning.
@@ -718,10 +725,10 @@
// Should gain a valid fence, which is already signaled.
LocalHandle f6;
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, p->GainAsync(&meta, &f6));
EXPECT_TRUE(f6.IsValid());
- EXPECT_LT(0, PollFd(f6.Get(), 10));
+ EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
}
TEST_F(LibBufferHubTest, TestOrphanedAcquire) {
@@ -737,12 +744,12 @@
EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
LocalHandle fence;
- EXPECT_LT(0, RETRY_EINTR(c1->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
EXPECT_LE(0, c1->AcquireAsync(&meta, &fence));
// Destroy the consumer now will make it orphaned and the buffer is still
// acquired.
c1 = nullptr;
- EXPECT_GE(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_GE(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
std::unique_ptr<BufferConsumer> c2 =
BufferConsumer::Import(p->CreateConsumer());
@@ -751,13 +758,13 @@
EXPECT_NE(consumer_state_bit1, consumer_state_bit2);
// The new consumer is available for acquire.
- EXPECT_LT(0, RETRY_EINTR(c2->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_LE(0, c2->AcquireAsync(&meta, &fence));
// Releasing the consumer makes the buffer gainable.
EXPECT_EQ(0, c2->ReleaseAsync(&meta, LocalHandle()));
// The buffer is now available for the producer to gain.
- EXPECT_LT(0, RETRY_EINTR(p->Poll(10)));
+ EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
// But if another consumer is created in released state.
std::unique_ptr<BufferConsumer> c3 =
@@ -766,7 +773,7 @@
const uint64_t consumer_state_bit3 = c3->buffer_state_bit();
EXPECT_NE(consumer_state_bit2, consumer_state_bit3);
// The consumer buffer is not acquirable.
- EXPECT_GE(0, RETRY_EINTR(c3->Poll(10)));
+ EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &fence));
// Producer should be able to gain no matter what.
diff --git a/libs/vr/libdvr/include/dvr/dvr_display_types.h b/libs/vr/libdvr/include/dvr/dvr_display_types.h
index 25364d8..fd69843 100644
--- a/libs/vr/libdvr/include/dvr/dvr_display_types.h
+++ b/libs/vr/libdvr/include/dvr/dvr_display_types.h
@@ -13,7 +13,7 @@
#ifndef __FLOAT32X4T_86
#define __FLOAT32X4T_86
typedef float float32x4_t __attribute__((__vector_size__(16)));
-typedef struct float32x4x4_t { float32x4_t val[4]; };
+typedef struct float32x4x4_t { float32x4_t val[4]; } float32x4x4_t;
#endif
#endif
diff --git a/libs/vr/libpdx_uds/private/uds/channel_event_set.h b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
index 99e7502..e960740 100644
--- a/libs/vr/libpdx_uds/private/uds/channel_event_set.h
+++ b/libs/vr/libpdx_uds/private/uds/channel_event_set.h
@@ -54,6 +54,14 @@
BorrowedHandle pollhup_event_fd() const { return pollhup_event_fd_.Borrow(); }
BorrowedHandle data_fd() const { return data_fd_.Borrow(); }
+ // Moves file descriptors out of ChannelEventReceiver. Note these operations
+ // immediately invalidates the receiver.
+ std::tuple<LocalHandle, LocalHandle, LocalHandle> TakeFds() {
+ epoll_fd_.Close();
+ return {std::move(data_fd_), std::move(pollin_event_fd_),
+ std::move(pollhup_event_fd_)};
+ }
+
Status<int> GetPendingEvents() const;
Status<int> PollPendingEvents(int timeout_ms) const;
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 32c2d7e..d43c164 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -122,6 +122,16 @@
},
}
+cc_library_static {
+ name: "libEGL_blobCache",
+ defaults: ["egl_libs_defaults"],
+ srcs: [
+ "EGL/BlobCache.cpp",
+ "EGL/FileBlobCache.cpp",
+ ],
+ export_include_dirs: ["EGL"],
+}
+
cc_library_shared {
name: "libEGL",
defaults: ["egl_libs_defaults"],
@@ -133,7 +143,6 @@
"EGL/egl.cpp",
"EGL/eglApi.cpp",
"EGL/Loader.cpp",
- "EGL/BlobCache.cpp",
],
shared_libs: [
"libvndksupport",
@@ -143,7 +152,10 @@
"libhidltransport",
"libutils",
],
- static_libs: ["libEGL_getProcAddress"],
+ static_libs: [
+ "libEGL_getProcAddress",
+ "libEGL_blobCache",
+ ],
ldflags: ["-Wl,--exclude-libs=ALL"],
export_include_dirs: ["EGL/include"],
}
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 0624b60..b3752f5 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -37,9 +37,9 @@
static const uint32_t blobCacheDeviceVersion = 1;
BlobCache::BlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize):
+ mMaxTotalSize(maxTotalSize),
mMaxKeySize(maxKeySize),
mMaxValueSize(maxValueSize),
- mMaxTotalSize(maxTotalSize),
mTotalSize(0) {
int64_t now = std::chrono::steady_clock::now().time_since_epoch().count();
#ifdef _WIN32
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
index a0a270a..1f5d535 100644
--- a/opengl/libs/EGL/BlobCache.h
+++ b/opengl/libs/EGL/BlobCache.h
@@ -97,6 +97,14 @@
//
int unflatten(void const* buffer, size_t size);
+protected:
+ // mMaxTotalSize is the maximum size that all cache entries can occupy. This
+ // includes space for both keys and values. When a call to BlobCache::set
+ // would otherwise cause this limit to be exceeded, either the key/value
+ // pair passed to BlobCache::set will not be cached or other cache entries
+ // will be evicted from the cache to make room for the new entry.
+ const size_t mMaxTotalSize;
+
private:
// Copying is disallowed.
BlobCache(const BlobCache&);
@@ -220,13 +228,6 @@
// simply not add the key/value pair to the cache.
const size_t mMaxValueSize;
- // mMaxTotalSize is the maximum size that all cache entries can occupy. This
- // includes space for both keys and values. When a call to BlobCache::set
- // would otherwise cause this limit to be exceeded, either the key/value
- // pair passed to BlobCache::set will not be cached or other cache entries
- // will be evicted from the cache to make room for the new entry.
- const size_t mMaxTotalSize;
-
// mTotalSize is the total combined size of all keys and values currently in
// the cache.
size_t mTotalSize;
diff --git a/opengl/libs/EGL/FileBlobCache.cpp b/opengl/libs/EGL/FileBlobCache.cpp
new file mode 100644
index 0000000..ff608a3
--- /dev/null
+++ b/opengl/libs/EGL/FileBlobCache.cpp
@@ -0,0 +1,185 @@
+/*
+ ** Copyright 2017, 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.
+ */
+
+#include "FileBlobCache.h"
+
+#include <inttypes.h>
+#include <log/log.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+
+// Cache file header
+static const char* cacheFileMagic = "EGL$";
+static const size_t cacheFileHeaderSize = 8;
+
+namespace android {
+
+static uint32_t crc32c(const uint8_t* buf, size_t len) {
+ const uint32_t polyBits = 0x82F63B78;
+ uint32_t r = 0;
+ for (size_t i = 0; i < len; i++) {
+ r ^= buf[i];
+ for (int j = 0; j < 8; j++) {
+ if (r & 1) {
+ r = (r >> 1) ^ polyBits;
+ } else {
+ r >>= 1;
+ }
+ }
+ }
+ return r;
+}
+
+FileBlobCache::FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
+ const std::string& filename)
+ : BlobCache(maxKeySize, maxValueSize, maxTotalSize)
+ , mFilename(filename) {
+ if (mFilename.length() > 0) {
+ size_t headerSize = cacheFileHeaderSize;
+
+ int fd = open(mFilename.c_str(), O_RDONLY, 0);
+ if (fd == -1) {
+ if (errno != ENOENT) {
+ ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
+ strerror(errno), errno);
+ }
+ return;
+ }
+
+ struct stat statBuf;
+ if (fstat(fd, &statBuf) == -1) {
+ ALOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
+ close(fd);
+ return;
+ }
+
+ // Sanity check the size before trying to mmap it.
+ size_t fileSize = statBuf.st_size;
+ if (fileSize > mMaxTotalSize * 2) {
+ ALOGE("cache file is too large: %#" PRIx64,
+ static_cast<off64_t>(statBuf.st_size));
+ close(fd);
+ return;
+ }
+
+ uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
+ PROT_READ, MAP_PRIVATE, fd, 0));
+ if (buf == MAP_FAILED) {
+ ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
+ errno);
+ close(fd);
+ return;
+ }
+
+ // Check the file magic and CRC
+ size_t cacheSize = fileSize - headerSize;
+ if (memcmp(buf, cacheFileMagic, 4) != 0) {
+ ALOGE("cache file has bad mojo");
+ close(fd);
+ return;
+ }
+ uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+ if (crc32c(buf + headerSize, cacheSize) != *crc) {
+ ALOGE("cache file failed CRC check");
+ close(fd);
+ return;
+ }
+
+ int err = unflatten(buf + headerSize, cacheSize);
+ if (err < 0) {
+ ALOGE("error reading cache contents: %s (%d)", strerror(-err),
+ -err);
+ munmap(buf, fileSize);
+ close(fd);
+ return;
+ }
+
+ munmap(buf, fileSize);
+ close(fd);
+ }
+}
+
+void FileBlobCache::writeToFile() {
+ if (mFilename.length() > 0) {
+ size_t cacheSize = getFlattenedSize();
+ size_t headerSize = cacheFileHeaderSize;
+ const char* fname = mFilename.c_str();
+
+ // Try to create the file with no permissions so we can write it
+ // without anyone trying to read it.
+ int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+ if (fd == -1) {
+ if (errno == EEXIST) {
+ // The file exists, delete it and try again.
+ if (unlink(fname) == -1) {
+ // No point in retrying if the unlink failed.
+ ALOGE("error unlinking cache file %s: %s (%d)", fname,
+ strerror(errno), errno);
+ return;
+ }
+ // Retry now that we've unlinked the file.
+ fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
+ }
+ if (fd == -1) {
+ ALOGE("error creating cache file %s: %s (%d)", fname,
+ strerror(errno), errno);
+ return;
+ }
+ }
+
+ size_t fileSize = headerSize + cacheSize;
+
+ uint8_t* buf = new uint8_t [fileSize];
+ if (!buf) {
+ ALOGE("error allocating buffer for cache contents: %s (%d)",
+ strerror(errno), errno);
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ int err = flatten(buf + headerSize, cacheSize);
+ if (err < 0) {
+ ALOGE("error writing cache contents: %s (%d)", strerror(-err),
+ -err);
+ delete [] buf;
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ // Write the file magic and CRC
+ memcpy(buf, cacheFileMagic, 4);
+ uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
+ *crc = crc32c(buf + headerSize, cacheSize);
+
+ if (write(fd, buf, fileSize) == -1) {
+ ALOGE("error writing cache file: %s (%d)", strerror(errno),
+ errno);
+ delete [] buf;
+ close(fd);
+ unlink(fname);
+ return;
+ }
+
+ delete [] buf;
+ fchmod(fd, S_IRUSR);
+ close(fd);
+ }
+}
+
+}
\ No newline at end of file
diff --git a/opengl/libs/EGL/FileBlobCache.h b/opengl/libs/EGL/FileBlobCache.h
new file mode 100644
index 0000000..393703f
--- /dev/null
+++ b/opengl/libs/EGL/FileBlobCache.h
@@ -0,0 +1,43 @@
+/*
+ ** Copyright 2017, 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_FILE_BLOB_CACHE_H
+#define ANDROID_FILE_BLOB_CACHE_H
+
+#include "BlobCache.h"
+#include <string>
+
+namespace android {
+
+class FileBlobCache : public BlobCache {
+public:
+ // FileBlobCache attempts to load the saved cache contents from disk into
+ // BlobCache.
+ FileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
+ const std::string& filename);
+
+ // writeToFile attempts to save the current contents of BlobCache to
+ // disk.
+ void writeToFile();
+
+private:
+ // mFilename is the name of the file for storing cache contents.
+ std::string mFilename;
+};
+
+} // namespace android
+
+#endif // ANDROID_BLOB_CACHE_H
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 579e422..ec548f3 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -20,12 +20,8 @@
#include "egl_display.h"
-
#include <private/EGL/cache.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
#include <unistd.h>
#include <thread>
@@ -37,10 +33,6 @@
static const size_t maxValueSize = 64 * 1024;
static const size_t maxTotalSize = 2 * 1024 * 1024;
-// Cache file header
-static const char* cacheFileMagic = "EGL$";
-static const size_t cacheFileHeaderSize = 8;
-
// The time in seconds to wait before saving newly inserted cache entries.
static const unsigned int deferredSaveDelay = 4;
@@ -124,7 +116,9 @@
void egl_cache_t::terminate() {
std::lock_guard<std::mutex> lock(mMutex);
- saveBlobCacheLocked();
+ if (mBlobCache) {
+ mBlobCache->writeToFile();
+ }
mBlobCache = NULL;
}
@@ -146,8 +140,8 @@
std::thread deferredSaveThread([this]() {
sleep(deferredSaveDelay);
std::lock_guard<std::mutex> lock(mMutex);
- if (mInitialized) {
- saveBlobCacheLocked();
+ if (mInitialized && mBlobCache) {
+ mBlobCache->writeToFile();
}
mSavePending = false;
});
@@ -179,163 +173,11 @@
BlobCache* egl_cache_t::getBlobCacheLocked() {
if (mBlobCache == nullptr) {
- mBlobCache.reset(new BlobCache(maxKeySize, maxValueSize, maxTotalSize));
- loadBlobCacheLocked();
+ mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
}
return mBlobCache.get();
}
-static uint32_t crc32c(const uint8_t* buf, size_t len) {
- const uint32_t polyBits = 0x82F63B78;
- uint32_t r = 0;
- for (size_t i = 0; i < len; i++) {
- r ^= buf[i];
- for (int j = 0; j < 8; j++) {
- if (r & 1) {
- r = (r >> 1) ^ polyBits;
- } else {
- r >>= 1;
- }
- }
- }
- return r;
-}
-
-void egl_cache_t::saveBlobCacheLocked() {
- if (mFilename.length() > 0 && mBlobCache != NULL) {
- size_t cacheSize = mBlobCache->getFlattenedSize();
- size_t headerSize = cacheFileHeaderSize;
- const char* fname = mFilename.c_str();
-
- // Try to create the file with no permissions so we can write it
- // without anyone trying to read it.
- int fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
- if (fd == -1) {
- if (errno == EEXIST) {
- // The file exists, delete it and try again.
- if (unlink(fname) == -1) {
- // No point in retrying if the unlink failed.
- ALOGE("error unlinking cache file %s: %s (%d)", fname,
- strerror(errno), errno);
- return;
- }
- // Retry now that we've unlinked the file.
- fd = open(fname, O_CREAT | O_EXCL | O_RDWR, 0);
- }
- if (fd == -1) {
- ALOGE("error creating cache file %s: %s (%d)", fname,
- strerror(errno), errno);
- return;
- }
- }
-
- size_t fileSize = headerSize + cacheSize;
-
- uint8_t* buf = new uint8_t [fileSize];
- if (!buf) {
- ALOGE("error allocating buffer for cache contents: %s (%d)",
- strerror(errno), errno);
- close(fd);
- unlink(fname);
- return;
- }
-
- int err = mBlobCache->flatten(buf + headerSize, cacheSize);
- if (err < 0) {
- ALOGE("error writing cache contents: %s (%d)", strerror(-err),
- -err);
- delete [] buf;
- close(fd);
- unlink(fname);
- return;
- }
-
- // Write the file magic and CRC
- memcpy(buf, cacheFileMagic, 4);
- uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
- *crc = crc32c(buf + headerSize, cacheSize);
-
- if (write(fd, buf, fileSize) == -1) {
- ALOGE("error writing cache file: %s (%d)", strerror(errno),
- errno);
- delete [] buf;
- close(fd);
- unlink(fname);
- return;
- }
-
- delete [] buf;
- fchmod(fd, S_IRUSR);
- close(fd);
- }
-}
-
-void egl_cache_t::loadBlobCacheLocked() {
- if (mFilename.length() > 0) {
- size_t headerSize = cacheFileHeaderSize;
-
- int fd = open(mFilename.c_str(), O_RDONLY, 0);
- if (fd == -1) {
- if (errno != ENOENT) {
- ALOGE("error opening cache file %s: %s (%d)", mFilename.c_str(),
- strerror(errno), errno);
- }
- return;
- }
-
- struct stat statBuf;
- if (fstat(fd, &statBuf) == -1) {
- ALOGE("error stat'ing cache file: %s (%d)", strerror(errno), errno);
- close(fd);
- return;
- }
-
- // Sanity check the size before trying to mmap it.
- size_t fileSize = statBuf.st_size;
- if (fileSize > maxTotalSize * 2) {
- ALOGE("cache file is too large: %#" PRIx64,
- static_cast<off64_t>(statBuf.st_size));
- close(fd);
- return;
- }
-
- uint8_t* buf = reinterpret_cast<uint8_t*>(mmap(NULL, fileSize,
- PROT_READ, MAP_PRIVATE, fd, 0));
- if (buf == MAP_FAILED) {
- ALOGE("error mmaping cache file: %s (%d)", strerror(errno),
- errno);
- close(fd);
- return;
- }
-
- // Check the file magic and CRC
- size_t cacheSize = fileSize - headerSize;
- if (memcmp(buf, cacheFileMagic, 4) != 0) {
- ALOGE("cache file has bad mojo");
- close(fd);
- return;
- }
- uint32_t* crc = reinterpret_cast<uint32_t*>(buf + 4);
- if (crc32c(buf + headerSize, cacheSize) != *crc) {
- ALOGE("cache file failed CRC check");
- close(fd);
- return;
- }
-
- int err = mBlobCache->unflatten(buf + headerSize, cacheSize);
- if (err < 0) {
- ALOGE("error reading cache contents: %s (%d)", strerror(-err),
- -err);
- munmap(buf, fileSize);
- close(fd);
- return;
- }
-
- munmap(buf, fileSize);
- close(fd);
- }
-}
-
// ----------------------------------------------------------------------------
}; // namespace android
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.h b/opengl/libs/EGL/egl_cache.h
index 56360f0..7382b91 100644
--- a/opengl/libs/EGL/egl_cache.h
+++ b/opengl/libs/EGL/egl_cache.h
@@ -20,7 +20,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include "BlobCache.h"
+#include "FileBlobCache.h"
#include <memory>
#include <mutex>
@@ -82,14 +82,6 @@
// possible.
BlobCache* getBlobCacheLocked();
- // saveBlobCache attempts to save the current contents of mBlobCache to
- // disk.
- void saveBlobCacheLocked();
-
- // loadBlobCache attempts to load the saved cache contents from disk into
- // mBlobCache.
- void loadBlobCacheLocked();
-
// mInitialized indicates whether the egl_cache_t is in the initialized
// state. It is initialized to false at construction time, and gets set to
// true when initialize is called. It is set back to false when terminate
@@ -101,7 +93,7 @@
// mBlobCache is the cache in which the key/value blob pairs are stored. It
// is initially NULL, and will be initialized by getBlobCacheLocked the
// first time it's needed.
- std::unique_ptr<BlobCache> mBlobCache;
+ std::unique_ptr<FileBlobCache> mBlobCache;
// mFilename is the name of the file for storing cache contents in between
// program invocations. It is initialized to an empty string at
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index 452c8c6..330861d 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -78,12 +78,13 @@
if (checkService()) {
Mutex::Autolock _l(mActivationsLock);
int64_t identity = IPCThreadState::self()->clearCallingIdentity();
- for (size_t i=0 ; i<mActivations.size() ; i++) {
+ for (size_t i=0 ; i<mActivations.size() ; ) {
const Info& info(mActivations[i]);
if (info.uid == uid) {
mBatteryStatService->noteStopSensor(info.uid, info.handle);
mActivations.removeAt(i);
- i--;
+ } else {
+ i++;
}
}
IPCThreadState::self()->restoreCallingIdentity(identity);
@@ -105,4 +106,3 @@
// ---------------------------------------------------------------------------
}; // namespace android
-
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 3f8ab3f..7115ad6 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -14,6 +14,7 @@
FrameTracker.cpp \
GpuService.cpp \
Layer.cpp \
+ BufferLayer.cpp \
ColorLayer.cpp \
LayerRejecter.cpp \
LayerVector.cpp \
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
new file mode 100644
index 0000000..45093be
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -0,0 +1,1002 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "BufferLayer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "BufferLayer.h"
+#include "Colorizer.h"
+#include "DisplayDevice.h"
+#include "LayerRejecter.h"
+#include "clz.h"
+
+#include "RenderEngine/RenderEngine.h"
+
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+
+#include <ui/DebugUtils.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/NativeHandle.h>
+#include <utils/StopWatch.h>
+#include <utils/Trace.h>
+
+#include <cutils/compiler.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+
+#include <math.h>
+#include <stdlib.h>
+#include <mutex>
+
+namespace android {
+
+BufferLayer::BufferLayer(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),
+ mSurfaceFlingerConsumer(nullptr),
+ mTextureName(-1U),
+ mFormat(PIXEL_FORMAT_NONE),
+ mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+ mBufferLatched(false),
+ mPreviousFrameNumber(0),
+ mUpdateTexImageFailed(false),
+ mRefreshPending(false) {
+#ifdef USE_HWC2
+ ALOGV("Creating Layer %s", name.string());
+#endif
+
+ mFlinger->getRenderEngine().genTextures(1, &mTextureName);
+ mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
+
+ if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false;
+
+ mCurrentState.requested = mCurrentState.active;
+
+ // drawing state & current state are identical
+ mDrawingState = mCurrentState;
+}
+
+BufferLayer::~BufferLayer() {
+ sp<Client> c(mClientRef.promote());
+ if (c != 0) {
+ c->detachLayer(this);
+ }
+
+ for (auto& point : mRemoteSyncPoints) {
+ point->setTransactionApplied();
+ }
+ for (auto& point : mLocalSyncPoints) {
+ point->setFrameAvailable();
+ }
+ mFlinger->deleteTextureAsync(mTextureName);
+
+#ifdef USE_HWC2
+ if (!mHwcLayers.empty()) {
+ ALOGE("Found stale hardware composer layers when destroying "
+ "surface flinger layer %s",
+ mName.string());
+ destroyAllHwcLayers();
+ }
+#endif
+}
+
+void BufferLayer::useSurfaceDamage() {
+ if (mFlinger->mForceFullDamage) {
+ surfaceDamageRegion = Region::INVALID_REGION;
+ } else {
+ surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
+ }
+}
+
+void BufferLayer::useEmptyDamage() {
+ surfaceDamageRegion.clear();
+}
+
+bool BufferLayer::isProtected() const {
+ const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
+ return (activeBuffer != 0) && (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+}
+
+bool BufferLayer::isVisible() const {
+ return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
+ (mActiveBuffer != NULL || mSidebandStream != NULL);
+}
+
+bool BufferLayer::isFixedSize() const {
+ return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+}
+
+status_t BufferLayer::setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
+ uint32_t const maxSurfaceDims =
+ min(mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
+
+ // never allow a surface larger than what our underlying GL implementation
+ // can handle.
+ if ((uint32_t(w) > maxSurfaceDims) || (uint32_t(h) > maxSurfaceDims)) {
+ ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
+ return BAD_VALUE;
+ }
+
+ mFormat = format;
+
+ mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
+ mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
+ mCurrentOpacity = getOpacityForFormat(format);
+
+ mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+ mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
+ mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+
+ return NO_ERROR;
+}
+
+static constexpr mat4 inverseOrientation(uint32_t transform) {
+ const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+ const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
+ const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
+ mat4 tr;
+
+ if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ tr = tr * rot90;
+ }
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ tr = tr * flipH;
+ }
+ if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ tr = tr * flipV;
+ }
+ return inverse(tr);
+}
+
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
+void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const {
+ ATRACE_CALL();
+
+ if (CC_UNLIKELY(mActiveBuffer == 0)) {
+ // the texture has not been created yet, this Layer has
+ // in fact never been drawn into. This happens frequently with
+ // SurfaceView because the WindowManager can't know when the client
+ // has drawn the first time.
+
+ // If there is nothing under us, we paint the screen in black, otherwise
+ // we just skip this update.
+
+ // figure out if there is something below us
+ Region under;
+ bool finished = false;
+ mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
+ if (finished || layer == static_cast<BufferLayer const*>(this)) {
+ finished = true;
+ return;
+ }
+ under.orSelf(renderArea.getTransform().transform(layer->visibleRegion));
+ });
+ // if not everything below us is covered, we plug the holes!
+ Region holes(clip.subtract(under));
+ if (!holes.isEmpty()) {
+ clearWithOpenGL(renderArea, 0, 0, 0, 1);
+ }
+ return;
+ }
+
+ // Bind the current buffer to the GL texture, and wait for it to be
+ // ready for us to draw into.
+ status_t err = mSurfaceFlingerConsumer->bindTextureImage();
+ if (err != NO_ERROR) {
+ ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
+ // Go ahead and draw the buffer anyway; no matter what we do the screen
+ // is probably going to have something visibly wrong.
+ }
+
+ bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
+
+ RenderEngine& engine(mFlinger->getRenderEngine());
+
+ if (!blackOutLayer) {
+ // TODO: we could be more subtle with isFixedSize()
+ const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
+
+ // Query the texture matrix given our current filtering mode.
+ float textureMatrix[16];
+ mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
+ mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
+
+ if (getTransformToDisplayInverse()) {
+ /*
+ * the code below applies the primary display's inverse transform to
+ * the texture transform
+ */
+ uint32_t transform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+ mat4 tr = inverseOrientation(transform);
+
+ /**
+ * TODO(b/36727915): This is basically a hack.
+ *
+ * Ensure that regardless of the parent transformation,
+ * this buffer is always transformed from native display
+ * orientation to display orientation. For example, in the case
+ * of a camera where the buffer remains in native orientation,
+ * we want the pixels to always be upright.
+ */
+ sp<Layer> p = mDrawingParent.promote();
+ if (p != nullptr) {
+ const auto parentTransform = p->getTransform();
+ tr = tr * inverseOrientation(parentTransform.getOrientation());
+ }
+
+ // and finally apply it to the original texture matrix
+ const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
+ memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
+ }
+
+ // Set things up for texturing.
+ mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
+ mTexture.setFiltering(useFiltering);
+ mTexture.setMatrix(textureMatrix);
+
+ engine.setupLayerTexturing(mTexture);
+ } else {
+ engine.setupLayerBlackedOut();
+ }
+ drawWithOpenGL(renderArea, useIdentityTransform);
+ engine.disableTexturing();
+}
+
+#ifdef USE_HWC2
+void BufferLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
+ if (mHwcLayers.empty()) {
+ return;
+ }
+ mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
+}
+#else
+void BufferLayer::onLayerDisplayed(const sp<const DisplayDevice>& /*hw*/,
+ HWComposer::HWCLayerInterface* layer) {
+ if (layer) {
+ layer->onDisplayed();
+ mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
+ }
+}
+#endif
+
+void BufferLayer::abandon() {
+ mSurfaceFlingerConsumer->abandon();
+}
+
+bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const {
+ if (mSidebandStreamChanged || mAutoRefresh) {
+ return true;
+ }
+
+ Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return false;
+ }
+ auto timestamp = mQueueItems[0].mTimestamp;
+ nsecs_t expectedPresent = mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
+
+ // Ignore timestamps more than a second in the future
+ bool isPlausible = timestamp < (expectedPresent + s2ns(1));
+ ALOGW_IF(!isPlausible,
+ "[%s] Timestamp %" PRId64 " seems implausible "
+ "relative to expectedPresent %" PRId64,
+ mName.string(), timestamp, expectedPresent);
+
+ bool isDue = timestamp < expectedPresent;
+ return isDue || !isPlausible;
+}
+
+void BufferLayer::setTransformHint(uint32_t orientation) const {
+ mSurfaceFlingerConsumer->setTransformHint(orientation);
+}
+
+bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
+ if (mBufferLatched) {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
+ }
+ mRefreshPending = false;
+ return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
+}
+bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) {
+ // mFrameLatencyNeeded is true when a new frame was latched for the
+ // composition.
+ if (!mFrameLatencyNeeded) return false;
+
+ // Update mFrameEventHistory.
+ {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence,
+ compositorTiming);
+ }
+
+ // Update mFrameTracker.
+ nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
+ mFrameTracker.setDesiredPresentTime(desiredPresentTime);
+
+ std::shared_ptr<FenceTime> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFenceTime();
+ if (frameReadyFence->isValid()) {
+ mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
+ } else {
+ // There was no fence for this frame, so assume that it was ready
+ // to be presented at the desired present time.
+ mFrameTracker.setFrameReadyTime(desiredPresentTime);
+ }
+
+ if (presentFence->isValid()) {
+ mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
+ } else {
+ // The HWC doesn't support present fences, so use the refresh
+ // timestamp instead.
+ mFrameTracker.setActualPresentTime(
+ mFlinger->getHwComposer().getRefreshTimestamp(HWC_DISPLAY_PRIMARY));
+ }
+
+ mFrameTracker.advanceFrame();
+ mFrameLatencyNeeded = false;
+ return true;
+}
+
+std::vector<OccupancyTracker::Segment> BufferLayer::getOccupancyHistory(bool forceFlush) {
+ std::vector<OccupancyTracker::Segment> history;
+ status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush, &history);
+ if (result != NO_ERROR) {
+ ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result);
+ return {};
+ }
+ return history;
+}
+
+bool BufferLayer::getTransformToDisplayInverse() const {
+ return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
+}
+
+#ifdef USE_HWC2
+void BufferLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
+ if (!mSurfaceFlingerConsumer->releasePendingBuffer()) {
+ return;
+ }
+
+ auto releaseFenceTime =
+ std::make_shared<FenceTime>(mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+ mReleaseTimeline.updateSignalTimes();
+ mReleaseTimeline.push(releaseFenceTime);
+
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ if (mPreviousFrameNumber != 0) {
+ mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime,
+ std::move(releaseFenceTime));
+ }
+}
+#endif
+
+Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+ ATRACE_CALL();
+
+ if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
+ // mSidebandStreamChanged was true
+ mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
+ if (mSidebandStream != NULL) {
+ setTransactionFlags(eTransactionNeeded);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
+ }
+ recomputeVisibleRegions = true;
+
+ const State& s(getDrawingState());
+ return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
+ }
+
+ Region outDirtyRegion;
+ if (mQueuedFrames <= 0 && !mAutoRefresh) {
+ return outDirtyRegion;
+ }
+
+ // if we've already called updateTexImage() without going through
+ // a composition step, we have to skip this layer at this point
+ // because we cannot call updateTeximage() without a corresponding
+ // compositionComplete() call.
+ // we'll trigger an update in onPreComposition().
+ if (mRefreshPending) {
+ return outDirtyRegion;
+ }
+
+ // If the head buffer's acquire fence hasn't signaled yet, return and
+ // try again later
+ if (!headFenceHasSignaled()) {
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ }
+
+ // Capture the old state of the layer for comparisons later
+ const State& s(getDrawingState());
+ const bool oldOpacity = isOpaque(s);
+ sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
+
+ if (!allTransactionsSignaled()) {
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ }
+
+ // This boolean is used to make sure that SurfaceFlinger's shadow copy
+ // of the buffer queue isn't modified when the buffer queue is returning
+ // BufferItem's that weren't actually queued. This can happen in shared
+ // buffer mode.
+ bool queuedBuffer = false;
+ LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
+ getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
+ mFreezeGeometryUpdates);
+ status_t updateResult =
+ mSurfaceFlingerConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, &mAutoRefresh,
+ &queuedBuffer, mLastFrameNumberReceived);
+ if (updateResult == BufferQueue::PRESENT_LATER) {
+ // Producer doesn't want buffer to be displayed yet. Signal a
+ // layer update so we check again at the next opportunity.
+ mFlinger->signalLayerUpdate();
+ return outDirtyRegion;
+ } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
+ // If the buffer has been rejected, remove it from the shadow queue
+ // and return early
+ if (queuedBuffer) {
+ Mutex::Autolock lock(mQueueItemLock);
+ mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ }
+ return outDirtyRegion;
+ } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
+ // This can occur if something goes wrong when trying to create the
+ // EGLImage for this buffer. If this happens, the buffer has already
+ // been released, so we need to clean up the queue and bug out
+ // early.
+ if (queuedBuffer) {
+ Mutex::Autolock lock(mQueueItemLock);
+ mQueueItems.clear();
+ android_atomic_and(0, &mQueuedFrames);
+ }
+
+ // Once we have hit this state, the shadow queue may no longer
+ // correctly reflect the incoming BufferQueue's contents, so even if
+ // updateTexImage starts working, the only safe course of action is
+ // to continue to ignore updates.
+ mUpdateTexImageFailed = true;
+
+ return outDirtyRegion;
+ }
+
+ if (queuedBuffer) {
+ // Autolock scope
+ auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+ Mutex::Autolock lock(mQueueItemLock);
+
+ // Remove any stale buffers that have been dropped during
+ // updateTexImage
+ while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+ mQueueItems.removeAt(0);
+ android_atomic_dec(&mQueuedFrames);
+ }
+
+ mQueueItems.removeAt(0);
+ }
+
+ // Decrement the queued-frames count. Signal another event if we
+ // have more frames pending.
+ if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) {
+ mFlinger->signalLayerUpdate();
+ }
+
+ // update the active buffer
+ mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(&mActiveBufferSlot);
+ if (mActiveBuffer == NULL) {
+ // this can only happen if the very first buffer was rejected.
+ return outDirtyRegion;
+ }
+
+ mBufferLatched = true;
+ mPreviousFrameNumber = mCurrentFrameNumber;
+ mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+ {
+ Mutex::Autolock lock(mFrameEventHistoryMutex);
+ mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
+#ifndef USE_HWC2
+ auto releaseFenceTime =
+ std::make_shared<FenceTime>(mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+ mReleaseTimeline.updateSignalTimes();
+ mReleaseTimeline.push(releaseFenceTime);
+ if (mPreviousFrameNumber != 0) {
+ mFrameEventHistory.addRelease(mPreviousFrameNumber, latchTime,
+ std::move(releaseFenceTime));
+ }
+#endif
+ }
+
+ mRefreshPending = true;
+ mFrameLatencyNeeded = true;
+ if (oldActiveBuffer == NULL) {
+ // the first time we receive a buffer, we need to trigger a
+ // geometry invalidation.
+ recomputeVisibleRegions = true;
+ }
+
+ setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace());
+
+ Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
+ const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
+ const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
+ if ((crop != mCurrentCrop) || (transform != mCurrentTransform) ||
+ (scalingMode != mCurrentScalingMode)) {
+ mCurrentCrop = crop;
+ mCurrentTransform = transform;
+ mCurrentScalingMode = scalingMode;
+ recomputeVisibleRegions = true;
+ }
+
+ if (oldActiveBuffer != NULL) {
+ uint32_t bufWidth = mActiveBuffer->getWidth();
+ uint32_t bufHeight = mActiveBuffer->getHeight();
+ if (bufWidth != uint32_t(oldActiveBuffer->width) ||
+ bufHeight != uint32_t(oldActiveBuffer->height)) {
+ recomputeVisibleRegions = true;
+ }
+ }
+
+ mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
+ if (oldOpacity != isOpaque(s)) {
+ recomputeVisibleRegions = true;
+ }
+
+ // Remove any sync points corresponding to the buffer which was just
+ // latched
+ {
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+ auto point = mLocalSyncPoints.begin();
+ while (point != mLocalSyncPoints.end()) {
+ if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
+ // This sync point must have been added since we started
+ // latching. Don't drop it yet.
+ ++point;
+ continue;
+ }
+
+ if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
+ point = mLocalSyncPoints.erase(point);
+ } else {
+ ++point;
+ }
+ }
+ }
+
+ // FIXME: postedRegion should be dirty & bounds
+ Region dirtyRegion(Rect(s.active.w, s.active.h));
+
+ // transform the dirty region to window-manager space
+ outDirtyRegion = (getTransform().transform(dirtyRegion));
+
+ return outDirtyRegion;
+}
+
+void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
+ mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
+}
+
+#ifdef USE_HWC2
+void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+ // Apply this display's projection's viewport to the visible region
+ // before giving it to the HWC HAL.
+ const Transform& tr = displayDevice->getTransform();
+ const auto& viewport = displayDevice->getViewport();
+ Region visible = tr.transform(visibleRegion.intersect(viewport));
+ auto hwcId = displayDevice->getHwcDisplayId();
+ auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcLayer = hwcInfo.layer;
+ auto error = hwcLayer->setVisibleRegion(visible);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ visible.dump(LOG_TAG);
+ }
+
+ error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ surfaceDamageRegion.dump(LOG_TAG);
+ }
+
+ // Sideband layers
+ if (mSidebandStream.get()) {
+ setCompositionType(hwcId, HWC2::Composition::Sideband);
+ ALOGV("[%s] Requesting Sideband composition", mName.string());
+ error = hwcLayer->setSidebandStream(mSidebandStream->handle());
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(),
+ mSidebandStream->handle(), to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+ return;
+ }
+
+ // Client layers
+ if (hwcInfo.forceClientComposition ||
+ (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
+ ALOGV("[%s] Requesting Client composition", mName.string());
+ setCompositionType(hwcId, HWC2::Composition::Client);
+ return;
+ }
+
+ // Device or Cursor layers
+ if (mPotentialCursor) {
+ ALOGV("[%s] Requesting Cursor composition", mName.string());
+ setCompositionType(hwcId, HWC2::Composition::Cursor);
+ } else {
+ ALOGV("[%s] Requesting Device composition", mName.string());
+ setCompositionType(hwcId, HWC2::Composition::Device);
+ }
+
+ ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace);
+ error = hwcLayer->setDataspace(mCurrentState.dataSpace);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), mCurrentState.dataSpace,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+
+ uint32_t hwcSlot = 0;
+ sp<GraphicBuffer> hwcBuffer;
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
+
+ auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+ error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+}
+
+#else
+void BufferLayer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
+ HWComposer::HWCLayerInterface& layer) {
+ int fenceFd = -1;
+
+ // TODO: there is a possible optimization here: we only need to set the
+ // acquire fence the first time a new buffer is acquired on EACH display.
+
+ if (layer.getCompositionType() == HWC_OVERLAY ||
+ layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
+ sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
+ if (fence->isValid()) {
+ fenceFd = fence->dup();
+ if (fenceFd == -1) {
+ ALOGW("failed to dup layer fence, skipping sync: %d", errno);
+ }
+ }
+ }
+ layer.setAcquireFenceFd(fenceFd);
+}
+#endif
+
+bool BufferLayer::isOpaque(const Layer::State& s) const {
+ // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
+ // layer's opaque flag.
+ if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
+ return false;
+ }
+
+ // if the layer has the opaque flag, then we're always opaque,
+ // otherwise we use the current buffer's format.
+ return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
+}
+
+void BufferLayer::onFirstRef() {
+ // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer, true);
+ mProducer = new MonitoredProducer(producer, mFlinger, this);
+ mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
+ mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
+ mSurfaceFlingerConsumer->setContentsChangedListener(this);
+ mSurfaceFlingerConsumer->setName(mName);
+
+ if (mFlinger->isLayerTripleBufferingDisabled()) {
+ mProducer->setMaxDequeuedBufferCount(2);
+ }
+
+ const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
+ updateTransformHint(hw);
+}
+
+// ---------------------------------------------------------------------------
+// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
+// ---------------------------------------------------------------------------
+
+void BufferLayer::onFrameAvailable(const BufferItem& item) {
+ // Add this buffer from our internal queue tracker
+ { // Autolock scope
+ Mutex::Autolock lock(mQueueItemLock);
+ mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ item.mGraphicBuffer->getHeight(),
+ item.mFrameNumber);
+ // Reset the frame number tracker when we receive the first buffer after
+ // a frame number reset
+ if (item.mFrameNumber == 1) {
+ mLastFrameNumberReceived = 0;
+ }
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
+ mQueueItems.push_back(item);
+ android_atomic_inc(&mQueuedFrames);
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
+ }
+
+ mFlinger->signalLayerUpdate();
+}
+
+void BufferLayer::onFrameReplaced(const BufferItem& item) {
+ { // Autolock scope
+ Mutex::Autolock lock(mQueueItemLock);
+
+ // Ensure that callbacks are handled in order
+ while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
+ if (result != NO_ERROR) {
+ ALOGE("[%s] Timed out waiting on callback", mName.string());
+ }
+ }
+
+ if (mQueueItems.empty()) {
+ ALOGE("Can't replace a frame on an empty queue");
+ return;
+ }
+ mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
+
+ // Wake up any pending callbacks
+ mLastFrameNumberReceived = item.mFrameNumber;
+ mQueueItemCondition.broadcast();
+ }
+}
+
+void BufferLayer::onSidebandStreamChanged() {
+ if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
+ // mSidebandStreamChanged was false
+ mFlinger->signalLayerUpdate();
+ }
+}
+
+bool BufferLayer::needsFiltering(const RenderArea& renderArea) const {
+ return mNeedsFiltering || renderArea.needsFiltering();
+}
+
+// As documented in libhardware header, formats in the range
+// 0x100 - 0x1FF are specific to the HAL implementation, and
+// are known to have no alpha channel
+// TODO: move definition for device-specific range into
+// hardware.h, instead of using hard-coded values here.
+#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
+
+bool BufferLayer::getOpacityForFormat(uint32_t format) {
+ if (HARDWARE_IS_DEVICE_FORMAT(format)) {
+ return true;
+ }
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ case HAL_PIXEL_FORMAT_RGBA_FP16:
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ return false;
+ }
+ // in all other case, we have no blending (also for unknown formats)
+ return true;
+}
+
+void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
+ const State& s(getDrawingState());
+
+ computeGeometry(renderArea, 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(computeBounds());
+
+ Transform t = getTransform();
+ if (!s.finalCrop.isEmpty()) {
+ win = t.transform(win);
+ if (!win.intersect(s.finalCrop, &win)) {
+ win.clear();
+ }
+ win = t.inverse().transform(win);
+ if (!win.intersect(computeBounds(), &win)) {
+ win.clear();
+ }
+ }
+
+ 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);
+
+ RenderEngine& engine(mFlinger->getRenderEngine());
+ engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
+ getColor());
+#ifdef USE_HWC2
+ engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
+ engine.drawMesh(mMesh);
+ engine.disableBlending();
+}
+
+uint32_t BufferLayer::getProducerStickyTransform() const {
+ int producerStickyTransform = 0;
+ int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
+ if (ret != OK) {
+ ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
+ strerror(-ret), ret);
+ return 0;
+ }
+ return static_cast<uint32_t>(producerStickyTransform);
+}
+
+bool BufferLayer::latchUnsignaledBuffers() {
+ static bool propertyLoaded = false;
+ static bool latch = false;
+ static std::mutex mutex;
+ std::lock_guard<std::mutex> lock(mutex);
+ if (!propertyLoaded) {
+ char value[PROPERTY_VALUE_MAX] = {};
+ property_get("debug.sf.latch_unsignaled", value, "0");
+ latch = atoi(value);
+ propertyLoaded = true;
+ }
+ return latch;
+}
+
+uint64_t BufferLayer::getHeadFrameNumber() const {
+ Mutex::Autolock lock(mQueueItemLock);
+ if (!mQueueItems.empty()) {
+ return mQueueItems[0].mFrameNumber;
+ } else {
+ return mCurrentFrameNumber;
+ }
+}
+
+bool BufferLayer::headFenceHasSignaled() const {
+#ifdef USE_HWC2
+ if (latchUnsignaledBuffers()) {
+ return true;
+ }
+
+ Mutex::Autolock lock(mQueueItemLock);
+ if (mQueueItems.empty()) {
+ return true;
+ }
+ if (mQueueItems[0].mIsDroppable) {
+ // Even though this buffer's fence may not have signaled yet, it could
+ // be replaced by another buffer before it has a chance to, which means
+ // that it's possible to get into a situation where a buffer is never
+ // able to be latched. To avoid this, grab this buffer anyway.
+ return true;
+ }
+ return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+#else
+ return true;
+#endif
+}
+
+uint32_t BufferLayer::getEffectiveScalingMode() const {
+ if (mOverrideScalingMode >= 0) {
+ return mOverrideScalingMode;
+ }
+ return mCurrentScalingMode;
+}
+
+// ----------------------------------------------------------------------------
+// transaction
+// ----------------------------------------------------------------------------
+
+void BufferLayer::notifyAvailableFrames() {
+ auto headFrameNumber = getHeadFrameNumber();
+ bool headFenceSignaled = headFenceHasSignaled();
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+ for (auto& point : mLocalSyncPoints) {
+ if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
+ point->setFrameAvailable();
+ }
+ }
+}
+
+sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
+ return mProducer;
+}
+
+// ---------------------------------------------------------------------------
+// h/w composer set-up
+// ---------------------------------------------------------------------------
+
+bool BufferLayer::allTransactionsSignaled() {
+ auto headFrameNumber = getHeadFrameNumber();
+ bool matchingFramesFound = false;
+ bool allTransactionsApplied = true;
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+
+ for (auto& point : mLocalSyncPoints) {
+ if (point->getFrameNumber() > headFrameNumber) {
+ break;
+ }
+ matchingFramesFound = true;
+
+ if (!point->frameIsAvailable()) {
+ // We haven't notified the remote layer that the frame for
+ // this point is available yet. Notify it now, and then
+ // abort this attempt to latch.
+ point->setFrameAvailable();
+ allTransactionsApplied = false;
+ break;
+ }
+
+ allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
+ }
+ return !matchingFramesFound || allTransactionsApplied;
+}
+
+} // namespace android
+
+#if defined(__gl_h_)
+#error "don't include gl/gl.h in this file"
+#endif
+
+#if defined(__gl2_h_)
+#error "don't include gl2/gl2.h in this file"
+#endif
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
new file mode 100644
index 0000000..418f032
--- /dev/null
+++ b/services/surfaceflinger/BufferLayer.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#include "Client.h"
+#include "Layer.h"
+#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
+#include "FrameTracker.h"
+#include "LayerVector.h"
+#include "MonitoredProducer.h"
+#include "RenderEngine/Mesh.h"
+#include "RenderEngine/Texture.h"
+#include "SurfaceFlinger.h"
+#include "SurfaceFlingerConsumer.h"
+#include "Transform.h"
+
+#include <gui/ISurfaceComposerClient.h>
+#include <gui/LayerState.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include <ui/FrameStats.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
+#include <ui/Region.h>
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <list>
+
+namespace android {
+
+/*
+ * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
+ * BufferLayer is first referenced.
+ *
+ * This also implements onFrameAvailable(), which notifies SurfaceFlinger
+ * that new data has arrived.
+ */
+class BufferLayer : public Layer, public SurfaceFlingerConsumer::ContentsChangedListener {
+public:
+ BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags);
+
+ ~BufferLayer() override;
+
+ // If we have received a new buffer this frame, we will pass its surface
+ // damage down to hardware composer. Otherwise, we must send a region with
+ // one empty rect.
+ void useSurfaceDamage();
+ void useEmptyDamage();
+
+ // -----------------------------------------------------------------------
+ // Overriden from Layer
+ // -----------------------------------------------------------------------
+
+ /*
+ * getTypeId - Provide unique string for each class type in the Layer
+ * hierarchy
+ */
+ const char* getTypeId() const override { return "BufferLayer"; }
+
+ /*
+ * isProtected - true if the layer may contain protected content in the
+ * GRALLOC_USAGE_PROTECTED sense.
+ */
+ bool isProtected() const;
+
+ /*
+ * isVisible - true if this layer is visible, false otherwise
+ */
+ bool isVisible() const override;
+
+ /*
+ * isFixedSize - true if content has a fixed size
+ */
+ bool isFixedSize() const override;
+
+ // the this layer's size and format
+ status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
+
+ /*
+ * onDraw - draws the surface.
+ */
+ void onDraw(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform) const override;
+
+#ifdef USE_HWC2
+ void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+#else
+ void onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer) override;
+#endif
+
+ void abandon() override;
+ bool shouldPresentNow(const DispSync& dispSync) const override;
+ void setTransformHint(uint32_t orientation) const override;
+ bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) override;
+ std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
+ bool getTransformToDisplayInverse() const override;
+
+public:
+ bool onPreComposition(nsecs_t refreshStartTime) override;
+
+#ifdef USE_HWC2
+ // If a buffer was replaced this frame, release the former buffer
+ void releasePendingBuffer(nsecs_t dequeueReadyTime);
+#endif
+
+ /*
+ * latchBuffer - called each time the screen is redrawn and returns whether
+ * the visible regions need to be recomputed (this is a fairly heavy
+ * operation, so this should be set only if needed). Typically this is used
+ * to figure out if the content or size of a surface has changed.
+ */
+ Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ bool isBufferLatched() const override { return mRefreshPending; }
+ void setDefaultBufferSize(uint32_t w, uint32_t h) override;
+
+#ifdef USE_HWC2
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+#else
+ void setAcquireFence(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer) override;
+#endif
+
+ bool isOpaque(const Layer::State& s) const override;
+
+private:
+ void onFirstRef() override;
+
+ // Interface implementation for
+ // SurfaceFlingerConsumer::ContentsChangedListener
+ void onFrameAvailable(const BufferItem& item) override;
+ void onFrameReplaced(const BufferItem& item) override;
+ void onSidebandStreamChanged() override;
+
+ // needsLinearFiltering - true if this surface's state requires filtering
+ bool needsFiltering(const RenderArea& renderArea) const;
+
+ static bool getOpacityForFormat(uint32_t format);
+
+ // drawing
+ void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const;
+
+ // Temporary - Used only for LEGACY camera mode.
+ uint32_t getProducerStickyTransform() const;
+
+ // Loads the corresponding system property once per process
+ static bool latchUnsignaledBuffers();
+
+ uint64_t getHeadFrameNumber() const;
+ bool headFenceHasSignaled() const;
+
+ // Returns the current scaling mode, unless mOverrideScalingMode
+ // is set, in which case, it returns mOverrideScalingMode
+ uint32_t getEffectiveScalingMode() const override;
+
+public:
+ void notifyAvailableFrames() override;
+
+ PixelFormat getPixelFormat() const override { return mFormat; }
+ sp<IGraphicBufferProducer> getProducer() const;
+
+private:
+ sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
+
+ // Check all of the local sync points to ensure that all transactions
+ // which need to have been applied prior to the frame which is about to
+ // be latched have signaled
+ bool allTransactionsSignaled();
+ sp<IGraphicBufferProducer> mProducer;
+
+ // constants
+ uint32_t mTextureName; // from GLES
+ PixelFormat mFormat;
+
+ // main thread
+ uint32_t mCurrentScalingMode;
+ bool mBufferLatched = false; // TODO: Use mActiveBuffer?
+ uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
+ // The texture used to draw the layer in GLES composition mode
+ mutable Texture mTexture;
+
+ bool mUpdateTexImageFailed; // This is only accessed on the main thread.
+ bool mRefreshPending;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 32526dd..8a17f88 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -18,8 +18,8 @@
#undef LOG_TAG
#define LOG_TAG "ColorLayer"
-#include <stdlib.h>
#include <stdint.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <utils/Errors.h>
@@ -28,27 +28,29 @@
#include <ui/GraphicBuffer.h>
#include "ColorLayer.h"
-#include "SurfaceFlinger.h"
#include "DisplayDevice.h"
#include "RenderEngine/RenderEngine.h"
+#include "SurfaceFlinger.h"
namespace android {
// ---------------------------------------------------------------------------
-ColorLayer::ColorLayer(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) {
+ColorLayer::ColorLayer(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) {
+ // drawing state & current state are identical
+ mDrawingState = mCurrentState;
}
void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
bool useIdentityTransform) const {
const State& s(getDrawingState());
- if (s.color.a>0) {
+ if (s.color.a > 0) {
Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
computeGeometry(renderArea, mesh, useIdentityTransform);
RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
- true /* disableTexture */, s.color);
+ true /* disableTexture */, s.color);
engine.drawMesh(mesh);
engine.disableBlending();
}
@@ -59,6 +61,35 @@
return !isHiddenByPolicy() && s.color.a;
}
+#ifdef USE_HWC2
+void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+ const Transform& tr = displayDevice->getTransform();
+ const auto& viewport = displayDevice->getViewport();
+ Region visible = tr.transform(visibleRegion.intersect(viewport));
+ auto hwcId = displayDevice->getHwcDisplayId();
+ auto& hwcInfo = mHwcLayers[hwcId];
+ auto& hwcLayer = hwcInfo.layer;
+ auto error = hwcLayer->setVisibleRegion(visible);
+
+ setCompositionType(hwcId, HWC2::Composition::SolidColor);
+
+ half4 color = getColor();
+ error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
+ static_cast<uint8_t>(std::round(255.0f * color.g)),
+ static_cast<uint8_t>(std::round(255.0f * color.b)), 255});
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+
+ // Clear out the transform, because it doesn't make sense absent a source buffer
+ error = hwcLayer->setTransform(HWC2::Transform::None);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
+}
+#endif
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index cdf3eca..debd3c3 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -26,20 +26,49 @@
namespace android {
-class ColorLayer : public Layer
-{
+class ColorLayer : public Layer {
public:
- ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags);
+ ColorLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags);
virtual ~ColorLayer() = default;
virtual const char* getTypeId() const { return "ColorLayer"; }
virtual void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const;
+ bool useIdentityTransform) const;
+ bool isVisible() const override;
virtual bool isOpaque(const Layer::State&) const { return false; }
- virtual bool isSecure() const { return false; }
- virtual bool isFixedSize() const { return true; }
- virtual bool isVisible() const;
+ virtual bool isFixedSize() const { return true; }
+
+ void notifyAvailableFrames() override {}
+ PixelFormat getPixelFormat() const override { return PIXEL_FORMAT_NONE; }
+ uint32_t getEffectiveScalingMode() const override { return 0; }
+#ifdef USE_HWC2
+ void releasePendingBuffer(nsecs_t) override {}
+#endif
+ Region latchBuffer(bool&, nsecs_t) override { return Region(); }
+ void useSurfaceDamage() override {}
+ void useEmptyDamage() override {}
+ bool isBufferLatched() const override { return false; }
+ bool onPreComposition(nsecs_t) override { return true; }
+ void abandon() override {}
+#ifdef USE_HWC2
+ void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+#else
+ void setAcquireFence(const sp<const DisplayDevice>& /*hw*/,
+ HWComposer::HWCLayerInterface& /*layer*/) override {}
+#endif
+ void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) override {}
+ bool shouldPresentNow(const DispSync& /*dispSync*/) const override { return false; }
+ bool onPostComposition(const std::shared_ptr<FenceTime>& /*glDoneFence*/,
+ const std::shared_ptr<FenceTime>& /*presentFence*/,
+ const CompositorTiming& /*compositorTiming*/) override {
+ return false;
+ }
+ void setTransformHint(uint32_t /*orientation*/) const override {}
+ std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool /*forceFlush*/) override {
+ return {};
+ }
+ bool getTransformToDisplayInverse() const override { return false; }
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
old mode 100755
new mode 100644
index 0525607..80987a4
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -19,10 +19,10 @@
#define LOG_TAG "Layer"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
#include <cutils/compiler.h>
#include <cutils/native_handle.h>
@@ -43,13 +43,13 @@
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
-#include "clz.h"
#include "Colorizer.h"
#include "DisplayDevice.h"
#include "Layer.h"
#include "LayerRejecter.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
+#include "clz.h"
#include "DisplayHardware/HWComposer.h"
@@ -58,23 +58,19 @@
#include <mutex>
#include "LayerProtoHelper.h"
-#define DEBUG_RESIZE 0
+#define DEBUG_RESIZE 0
namespace android {
-// ---------------------------------------------------------------------------
-
int32_t Layer::sSequence = 1;
-Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags)
- : contentDirty(false),
+Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags)
+ : contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
mFlinger(flinger),
- mTextureName(UINT32_MAX),
mPremultipliedAlpha(true),
- mName("unnamed"),
- mFormat(PIXEL_FORMAT_NONE),
+ mName(name),
mTransactionFlags(0),
mPendingStateMutex(),
mPendingStates(),
@@ -82,13 +78,9 @@
mSidebandStreamChanged(false),
mActiveBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
mCurrentTransform(0),
- mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mOverrideScalingMode(-1),
mCurrentOpacity(true),
- mBufferLatched(false),
mCurrentFrameNumber(0),
- mPreviousFrameNumber(0),
- mRefreshPending(false),
mFrameLatencyNeeded(false),
mFiltering(false),
mNeedsFiltering(false),
@@ -97,41 +89,28 @@
mIsGlesComposition(false),
#endif
mProtectedByApp(false),
- mHasSurface(false),
mClientRef(client),
mPotentialCursor(false),
mQueueItemLock(),
mQueueItemCondition(),
mQueueItems(),
mLastFrameNumberReceived(0),
- mUpdateTexImageFailed(false),
mAutoRefresh(false),
- mFreezeGeometryUpdates(false)
-{
-#ifdef USE_HWC2
- ALOGV("Creating Layer %s", name.string());
-#endif
+ mFreezeGeometryUpdates(false) {
mCurrentCrop.makeInvalid();
- mFlinger->getRenderEngine().genTextures(1, &mTextureName);
- mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
uint32_t layerFlags = 0;
- if (flags & ISurfaceComposerClient::eHidden)
- layerFlags |= layer_state_t::eLayerHidden;
- if (flags & ISurfaceComposerClient::eOpaque)
- layerFlags |= layer_state_t::eLayerOpaque;
- if (flags & ISurfaceComposerClient::eSecure)
- layerFlags |= layer_state_t::eLayerSecure;
-
- if (flags & ISurfaceComposerClient::eNonPremultiplied)
- mPremultipliedAlpha = false;
+ if (flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
+ if (flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
+ if (flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
mName = name;
mTransactionName = String8("TX - ") + mName;
mCurrentState.active.w = w;
mCurrentState.active.h = h;
+ mCurrentState.flags = layerFlags;
mCurrentState.active.transform.set(0, 0);
mCurrentState.crop.makeInvalid();
mCurrentState.finalCrop.makeInvalid();
@@ -140,7 +119,6 @@
mCurrentState.z = 0;
mCurrentState.color.a = 1.0f;
mCurrentState.layerStack = 0;
- mCurrentState.flags = layerFlags;
mCurrentState.sequence = 0;
mCurrentState.requested = mCurrentState.active;
mCurrentState.dataSpace = HAL_DATASPACE_UNKNOWN;
@@ -155,8 +133,7 @@
const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
#else
- nsecs_t displayPeriod =
- flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+ nsecs_t displayPeriod = flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
#endif
mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
@@ -165,137 +142,33 @@
mFrameEventHistory.initializeCompositorTiming(compositorTiming);
}
-void Layer::onFirstRef() {
- // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, true);
- mProducer = new MonitoredProducer(producer, mFlinger, this);
- mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
- mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
- mSurfaceFlingerConsumer->setContentsChangedListener(this);
- mSurfaceFlingerConsumer->setName(mName);
-
- if (mFlinger->isLayerTripleBufferingDisabled()) {
- mProducer->setMaxDequeuedBufferCount(2);
- }
-
- const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
- updateTransformHint(hw);
-}
+void Layer::onFirstRef() {}
Layer::~Layer() {
- sp<Client> c(mClientRef.promote());
- if (c != 0) {
- c->detachLayer(this);
- }
-
- for (auto& point : mRemoteSyncPoints) {
- point->setTransactionApplied();
- }
- for (auto& point : mLocalSyncPoints) {
- point->setFrameAvailable();
- }
- mFlinger->deleteTextureAsync(mTextureName);
mFrameTracker.logAndResetStats(mName);
-
-#ifdef USE_HWC2
- if (!mHwcLayers.empty()) {
- ALOGE("Found stale hardware composer layers when destroying "
- "surface flinger layer %s", mName.string());
- destroyAllHwcLayers();
- }
-#endif
}
// ---------------------------------------------------------------------------
// callbacks
// ---------------------------------------------------------------------------
+/*
+ * onLayerDisplayed is only meaningful for BufferLayer, but, is called through
+ * Layer. So, the implementation is done in BufferLayer. When called on a
+ * ColorLayer object, it's essentially a NOP.
+ */
#ifdef USE_HWC2
-void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) {
- if (mHwcLayers.empty()) {
- return;
- }
- mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
-}
+void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
#else
void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
- HWComposer::HWCLayerInterface* layer) {
- if (layer) {
- layer->onDisplayed();
- mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
- }
-}
+ HWComposer::HWCLayerInterface* /*layer*/) {}
#endif
-void Layer::onFrameAvailable(const BufferItem& item) {
- // Add this buffer from our internal queue tracker
- { // Autolock scope
- Mutex::Autolock lock(mQueueItemLock);
- mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
- item.mGraphicBuffer->getHeight(), item.mFrameNumber);
- // Reset the frame number tracker when we receive the first buffer after
- // a frame number reset
- if (item.mFrameNumber == 1) {
- mLastFrameNumberReceived = 0;
- }
-
- // Ensure that callbacks are handled in order
- while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
- ms2ns(500));
- if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
- }
- }
-
- mQueueItems.push_back(item);
- android_atomic_inc(&mQueuedFrames);
-
- // Wake up any pending callbacks
- mLastFrameNumberReceived = item.mFrameNumber;
- mQueueItemCondition.broadcast();
- }
-
- mFlinger->signalLayerUpdate();
-}
-
-void Layer::onFrameReplaced(const BufferItem& item) {
- { // Autolock scope
- Mutex::Autolock lock(mQueueItemLock);
-
- // Ensure that callbacks are handled in order
- while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
- ms2ns(500));
- if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", mName.string());
- }
- }
-
- if (mQueueItems.empty()) {
- ALOGE("Can't replace a frame on an empty queue");
- return;
- }
- mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
-
- // Wake up any pending callbacks
- mLastFrameNumberReceived = item.mFrameNumber;
- mQueueItemCondition.broadcast();
- }
-}
-
-void Layer::onSidebandStreamChanged() {
- if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) {
- // mSidebandStreamChanged was false
- mFlinger->signalLayerUpdate();
- }
-}
-
void Layer::onRemovedFromCurrentState() {
// the layer is removed from SF mCurrentState to mLayersPendingRemoval
+ mPendingRemoval = true;
+
if (mCurrentState.zOrderRelativeOf != nullptr) {
sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
if (strongRelative != nullptr) {
@@ -312,8 +185,8 @@
void Layer::onRemoved() {
// the layer is removed from SF mLayersPendingRemoval
+ abandon();
- mSurfaceFlingerConsumer->abandon();
#ifdef USE_HWC2
destroyAllHwcLayers();
#endif
@@ -335,55 +208,18 @@
return mPremultipliedAlpha;
}
-status_t Layer::setBuffers( uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags)
-{
- uint32_t const maxSurfaceDims = min(
- mFlinger->getMaxTextureSize(), mFlinger->getMaxViewportDims());
-
- // never allow a surface larger than what our underlying GL implementation
- // can handle.
- if ((uint32_t(w)>maxSurfaceDims) || (uint32_t(h)>maxSurfaceDims)) {
- ALOGE("dimensions too large %u x %u", uint32_t(w), uint32_t(h));
- return BAD_VALUE;
- }
-
- mFormat = format;
-
- mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
- mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
- mCurrentOpacity = getOpacityForFormat(format);
-
- mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
- mSurfaceFlingerConsumer->setDefaultBufferFormat(format);
- mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
-
- return NO_ERROR;
-}
-
sp<IBinder> Layer::getHandle() {
Mutex::Autolock _l(mLock);
-
- LOG_ALWAYS_FATAL_IF(mHasSurface,
- "Layer::getHandle() has already been called");
-
- mHasSurface = true;
-
return new Handle(mFlinger, this);
}
-sp<IGraphicBufferProducer> Layer::getProducer() const {
- return mProducer;
-}
-
// ---------------------------------------------------------------------------
// h/w composer set-up
// ---------------------------------------------------------------------------
#ifdef USE_HWC2
bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
- LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
- "Already have a layer for hwcId %d", hwcId);
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Already have a layer for hwcId %d", hwcId);
HWC2::Layer* layer = hwc->createLayer(hwcId);
if (!layer) {
return false;
@@ -392,7 +228,7 @@
hwcInfo.hwc = hwc;
hwcInfo.layer = layer;
layer->setLayerDestroyedListener(
- [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+ [this, hwcId](HWC2::Layer* /*layer*/) { mHwcLayers.erase(hwcId); });
return true;
}
@@ -401,14 +237,12 @@
return;
}
auto& hwcInfo = mHwcLayers[hwcId];
- LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
- "Attempt to destroy null layer");
+ LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
// The layer destroyed listener should have cleared the entry from
// mHwcLayers. Verify that.
- LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
- "Stale layer entry in mHwcLayers");
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0, "Stale layer entry in mHwcLayers");
}
void Layer::destroyAllHwcLayers() {
@@ -418,7 +252,7 @@
destroyHwcLayer(mHwcLayers.begin()->first);
}
LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
- "All hardware composer layers should have been destroyed");
+ "All hardware composer layers should have been destroyed");
}
#endif
@@ -542,7 +376,7 @@
activeCrop.clear();
}
if (!s.finalCrop.isEmpty()) {
- if(!activeCrop.intersect(s.finalCrop, &activeCrop)) {
+ if (!activeCrop.intersect(s.finalCrop, &activeCrop)) {
activeCrop.clear();
}
}
@@ -592,16 +426,13 @@
* the code below applies the primary display's inverse transform to the
* buffer
*/
- uint32_t invTransformOrient =
- DisplayDevice::getPrimaryDisplayOrientationTransform();
+ uint32_t invTransformOrient = DisplayDevice::getPrimaryDisplayOrientationTransform();
// calculate the inverse transform
if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
// and apply to the current transform
- invTransform = (Transform(invTransformOrient) * Transform(invTransform))
- .getOrientation();
+ invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation();
}
int winWidth = s.active.w;
@@ -615,27 +446,25 @@
bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
if (is_h_flipped == is_v_flipped) {
- invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
winWidth = s.active.h;
winHeight = s.active.w;
}
- const Rect winCrop = activeCrop.transform(
- invTransform, s.active.w, s.active.h);
+ const Rect winCrop = activeCrop.transform(invTransform, s.active.w, s.active.h);
// below, crop is intersected with winCrop expressed in crop's coordinate space
- float xScale = crop.getWidth() / float(winWidth);
+ float xScale = crop.getWidth() / float(winWidth);
float yScale = crop.getHeight() / float(winHeight);
- float insetL = winCrop.left * xScale;
- float insetT = winCrop.top * yScale;
- float insetR = (winWidth - winCrop.right ) * xScale;
+ float insetL = winCrop.left * xScale;
+ float insetT = winCrop.top * yScale;
+ float insetR = (winWidth - winCrop.right) * xScale;
float insetB = (winHeight - winCrop.bottom) * yScale;
- crop.left += insetL;
- crop.top += insetT;
- crop.right -= insetR;
+ crop.left += insetL;
+ crop.top += insetT;
+ crop.right -= insetR;
crop.bottom -= insetB;
return crop;
@@ -644,9 +473,7 @@
#ifdef USE_HWC2
void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
#else
-void Layer::setGeometry(
- const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer)
+void Layer::setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer)
#endif
{
#ifdef USE_HWC2
@@ -678,18 +505,18 @@
#ifdef USE_HWC2
auto blendMode = HWC2::BlendMode::None;
if (!isOpaque(s) || getAlpha() != 1.0f) {
- blendMode = mPremultipliedAlpha ?
- HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
+ blendMode =
+ mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
}
auto error = hwcLayer->setBlendMode(blendMode);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:"
- " %s (%d)", mName.string(), to_string(blendMode).c_str(),
- to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set blend mode %s:"
+ " %s (%d)",
+ mName.string(), to_string(blendMode).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
#else
if (!isOpaque(s) || getAlpha() != 1.0f) {
- layer.setBlending(mPremultipliedAlpha ?
- HWC_BLENDING_PREMULT :
- HWC_BLENDING_COVERAGE);
+ layer.setBlending(mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE);
}
#endif
@@ -701,9 +528,9 @@
Rect activeCrop(s.crop);
activeCrop = t.transform(activeCrop);
#ifdef USE_HWC2
- if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
+ if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
#else
- if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+ if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
#endif
activeCrop.clear();
}
@@ -714,22 +541,20 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+ if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
activeCrop.clear();
}
// mark regions outside the crop as transparent
activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
- activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
- s.active.w, s.active.h));
- activeTransparentRegion.orSelf(Rect(0, activeCrop.top,
- activeCrop.left, activeCrop.bottom));
- activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
- s.active.w, activeCrop.bottom));
+ activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom, s.active.w, s.active.h));
+ activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
+ activeTransparentRegion.orSelf(
+ Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom));
}
Rect frame(t.transform(computeBounds(activeTransparentRegion)));
if (!s.finalCrop.isEmpty()) {
- if(!frame.intersect(s.finalCrop, &frame)) {
+ if (!frame.intersect(s.finalCrop, &frame)) {
frame.clear();
}
}
@@ -741,10 +566,9 @@
Rect transformedFrame = tr.transform(frame);
error = hwcLayer->setDisplayFrame(transformedFrame);
if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
- mName.string(), transformedFrame.left, transformedFrame.top,
- transformedFrame.right, transformedFrame.bottom,
- to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", mName.string(),
+ transformedFrame.left, transformedFrame.top, transformedFrame.right,
+ transformedFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
} else {
hwcInfo.displayFrame = transformedFrame;
}
@@ -753,23 +577,23 @@
error = hwcLayer->setSourceCrop(sourceCrop);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
- "%s (%d)", mName.string(), sourceCrop.left, sourceCrop.top,
- sourceCrop.right, sourceCrop.bottom, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ "%s (%d)",
+ mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom,
+ to_string(error).c_str(), static_cast<int32_t>(error));
} else {
hwcInfo.sourceCrop = sourceCrop;
}
float alpha = static_cast<float>(getAlpha());
error = hwcLayer->setPlaneAlpha(alpha);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
- "%s (%d)", mName.string(), alpha, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set plane alpha %.3f: "
+ "%s (%d)",
+ mName.string(), alpha, to_string(error).c_str(), static_cast<int32_t>(error));
error = hwcLayer->setZOrder(z);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)",
- mName.string(), z, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z,
+ to_string(error).c_str(), static_cast<int32_t>(error));
int type = s.type;
int appId = s.appId;
@@ -781,8 +605,8 @@
}
error = hwcLayer->setInfo(type, appId);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)",
- mName.string(), static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
+ static_cast<int32_t>(error));
#else
if (!frame.intersect(hw->getViewport(), &frame)) {
frame.clear();
@@ -790,7 +614,7 @@
const Transform& tr(hw->getTransform());
layer.setFrame(tr.transform(frame));
layer.setCrop(computeCrop(hw));
- layer.setPlaneAlpha(static_cast<uint8_t>(std::round(255.0f*getAlpha())));
+ layer.setPlaneAlpha(static_cast<uint8_t>(std::round(255.0f * getAlpha())));
#endif
/*
@@ -809,12 +633,10 @@
* the code below applies the primary display's inverse transform to the
* buffer
*/
- uint32_t invTransform =
- DisplayDevice::getPrimaryDisplayOrientationTransform();
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
// calculate the inverse transform
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
- NATIVE_WINDOW_TRANSFORM_FLIP_H;
+ invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
/*
@@ -835,9 +657,11 @@
} else {
auto transform = static_cast<HWC2::Transform>(orientation);
auto error = hwcLayer->setTransform(transform);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: "
- "%s (%d)", mName.string(), to_string(transform).c_str(),
- to_string(error).c_str(), static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set transform %s: "
+ "%s (%d)",
+ mName.string(), to_string(transform).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
#else
if (orientation & Transform::ROT_INVALID) {
@@ -858,110 +682,9 @@
mHwcLayers[hwcId].forceClientComposition = true;
}
-
-void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
- // Apply this display's projection's viewport to the visible region
- // before giving it to the HWC HAL.
- const Transform& tr = displayDevice->getTransform();
- const auto& viewport = displayDevice->getViewport();
- Region visible = tr.transform(visibleRegion.intersect(viewport));
- auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = mHwcLayers[hwcId];
- auto& hwcLayer = hwcInfo.layer;
- auto error = hwcLayer->setVisibleRegion(visible);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- visible.dump(LOG_TAG);
- }
-
- error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- surfaceDamageRegion.dump(LOG_TAG);
- }
-
- // Sideband layers
- if (mSidebandStream.get()) {
- setCompositionType(hwcId, HWC2::Composition::Sideband);
- ALOGV("[%s] Requesting Sideband composition", mName.string());
- error = hwcLayer->setSidebandStream(mSidebandStream->handle());
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set sideband stream %p: %s (%d)",
- mName.string(), mSidebandStream->handle(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
- return;
- }
-
- // Client layers
- if (hwcInfo.forceClientComposition ||
- (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) {
- ALOGV("[%s] Requesting Client composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Client);
- return;
- }
-
- // SolidColor layers
- if (mActiveBuffer == nullptr) {
- setCompositionType(hwcId, HWC2::Composition::SolidColor);
-
- half4 color = getColor();
- error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f*color.r)),
- static_cast<uint8_t>(std::round(255.0f * color.g)),
- static_cast<uint8_t>(std::round(255.0f * color.b)),
- 255});
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set color: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- // Clear out the transform, because it doesn't make sense absent a
- // source buffer
- error = hwcLayer->setTransform(HWC2::Transform::None);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(),
- to_string(error).c_str(), static_cast<int32_t>(error));
- }
-
- return;
- }
-
- // Device or Cursor layers
- if (mPotentialCursor) {
- ALOGV("[%s] Requesting Cursor composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Cursor);
- } else {
- ALOGV("[%s] Requesting Device composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Device);
- }
-
- ALOGV("setPerFrameData: dataspace = %d", mCurrentState.dataSpace);
- error = hwcLayer->setDataspace(mCurrentState.dataSpace);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(),
- mCurrentState.dataSpace, to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
-
- uint32_t hwcSlot = 0;
- sp<GraphicBuffer> hwcBuffer;
- hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
- &hwcSlot, &hwcBuffer);
-
- auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
- error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
- if (error != HWC2::Error::None) {
- ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
- mActiveBuffer->handle, to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
-}
-
#else
void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer) {
+ HWComposer::HWCLayerInterface& layer) {
// 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.
@@ -983,11 +706,11 @@
}
#endif
+
#ifdef USE_HWC2
void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) {
auto hwcId = displayDevice->getHwcDisplayId();
- if (mHwcLayers.count(hwcId) == 0 ||
- getCompositionType(hwcId) != HWC2::Composition::Cursor) {
+ if (mHwcLayers.count(hwcId) == 0 || getCompositionType(hwcId) != HWC2::Composition::Cursor) {
return;
}
@@ -1010,36 +733,15 @@
auto& displayTransform(displayDevice->getTransform());
auto position = displayTransform.transform(frame);
- auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left,
- position.top);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position "
- "to (%d, %d): %s (%d)", mName.string(), position.left,
- position.top, to_string(error).c_str(),
- static_cast<int32_t>(error));
+ auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left, position.top);
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set cursor position "
+ "to (%d, %d): %s (%d)",
+ mName.string(), position.left, position.top, to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
#else
-void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
- HWComposer::HWCLayerInterface& layer) {
- int fenceFd = -1;
-
- // TODO: there is a possible optimization here: we only need to set the
- // acquire fence the first time a new buffer is acquired on EACH display.
-
- if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
- sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
- if (fence->isValid()) {
- fenceFd = fence->dup();
- if (fenceFd == -1) {
- ALOGW("failed to dup layer fence, skipping sync: %d", errno);
- }
- }
- }
- layer.setAcquireFenceFd(fenceFd);
-}
-
-Rect Layer::getPosition(
- const sp<const DisplayDevice>& hw)
-{
+Rect Layer::getPosition(const sp<const DisplayDevice>& hw) {
// this gives us only the "orientation" component of the transform
const State& s(getCurrentState());
@@ -1077,129 +779,8 @@
onDraw(renderArea, Region(renderArea.getBounds()), false);
}
-static constexpr mat4 inverseOrientation(uint32_t transform) {
- const mat4 flipH(-1,0,0,0, 0,1,0,0, 0,0,1,0, 1,0,0,1);
- const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);
- const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
- mat4 tr;
-
- if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- tr = tr * rot90;
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- tr = tr * flipH;
- }
- if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- tr = tr * flipV;
- }
- return inverse(tr);
-}
-
-/*
- * onDraw will draw the current layer onto the presentable buffer
- */
-void Layer::onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const
-{
- ATRACE_CALL();
-
- if (CC_UNLIKELY(mActiveBuffer == 0)) {
- // the texture has not been created yet, this Layer has
- // in fact never been drawn into. This happens frequently with
- // SurfaceView because the WindowManager can't know when the client
- // has drawn the first time.
-
- // If there is nothing under us, we paint the screen in black, otherwise
- // we just skip this update.
-
- // figure out if there is something below us
- Region under;
- bool finished = false;
- mFlinger->mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (finished || layer == static_cast<Layer const*>(this)) {
- finished = true;
- return;
- }
- under.orSelf(renderArea.getTransform().transform(layer->visibleRegion));
- });
- // if not everything below us is covered, we plug the holes!
- Region holes(clip.subtract(under));
- if (!holes.isEmpty()) {
- clearWithOpenGL(renderArea, 0, 0, 0, 1);
- }
- return;
- }
-
- // Bind the current buffer to the GL texture, and wait for it to be
- // ready for us to draw into.
- status_t err = mSurfaceFlingerConsumer->bindTextureImage();
- if (err != NO_ERROR) {
- ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
- // Go ahead and draw the buffer anyway; no matter what we do the screen
- // is probably going to have something visibly wrong.
- }
-
- bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
-
- RenderEngine& engine(mFlinger->getRenderEngine());
-
- if (!blackOutLayer) {
- // TODO: we could be more subtle with isFixedSize()
- const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
-
- // Query the texture matrix given our current filtering mode.
- float textureMatrix[16];
- mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
- mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);
-
- if (getTransformToDisplayInverse()) {
-
- /*
- * the code below applies the primary display's inverse transform to
- * the texture transform
- */
- uint32_t transform =
- DisplayDevice::getPrimaryDisplayOrientationTransform();
- mat4 tr = inverseOrientation(transform);
-
- /**
- * TODO(b/36727915): This is basically a hack.
- *
- * Ensure that regardless of the parent transformation,
- * this buffer is always transformed from native display
- * orientation to display orientation. For example, in the case
- * of a camera where the buffer remains in native orientation,
- * we want the pixels to always be upright.
- */
- sp<Layer> p = mDrawingParent.promote();
- if (p != nullptr) {
- const auto parentTransform = p->getTransform();
- tr = tr * inverseOrientation(parentTransform.getOrientation());
- }
-
- // and finally apply it to the original texture matrix
- const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
- memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
- }
-
- // Set things up for texturing.
- mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
- mTexture.setFiltering(useFiltering);
- mTexture.setMatrix(textureMatrix);
-
- engine.setupLayerTexturing(mTexture);
- } else {
- engine.setupLayerBlackedOut();
- }
- drawWithOpenGL(renderArea, useIdentityTransform);
- engine.disableTexturing();
-}
-
-
-void Layer::clearWithOpenGL(const RenderArea& renderArea,
- float red, float green, float blue,
- float alpha) const
-{
+void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
+ float alpha) const {
RenderEngine& engine(mFlinger->getRenderEngine());
computeGeometry(renderArea, mMesh, false);
engine.setupFillWithColor(red, green, blue, alpha);
@@ -1207,85 +788,29 @@
}
void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
- clearWithOpenGL(renderArea, 0,0,0,0);
-}
-
-void Layer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
- const State& s(getDrawingState());
-
- computeGeometry(renderArea, 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(computeBounds());
-
- Transform t = getTransform();
- if (!s.finalCrop.isEmpty()) {
- win = t.transform(win);
- if (!win.intersect(s.finalCrop, &win)) {
- win.clear();
- }
- win = t.inverse().transform(win);
- if (!win.intersect(computeBounds(), &win)) {
- win.clear();
- }
- }
-
- 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);
-
- RenderEngine& engine(mFlinger->getRenderEngine());
- engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s),
- false /* disableTexture */, getColor());
-#ifdef USE_HWC2
- engine.setSourceDataSpace(mCurrentState.dataSpace);
-#endif
- engine.drawMesh(mMesh);
- engine.disableBlending();
+ clearWithOpenGL(renderArea, 0, 0, 0, 0);
}
#ifdef USE_HWC2
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type,
- bool callIntoHwc) {
+void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
if (mHwcLayers.count(hwcId) == 0) {
ALOGE("setCompositionType called without a valid HWC layer");
return;
}
auto& hwcInfo = mHwcLayers[hwcId];
auto& hwcLayer = hwcInfo.layer;
- ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(),
- to_string(type).c_str(), static_cast<int>(callIntoHwc));
+ ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
+ static_cast<int>(callIntoHwc));
if (hwcInfo.compositionType != type) {
ALOGV(" actually setting");
hwcInfo.compositionType = type;
if (callIntoHwc) {
auto error = hwcLayer->setCompositionType(type);
- ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set "
- "composition type %s: %s (%d)", mName.string(),
- to_string(type).c_str(), to_string(error).c_str(),
- static_cast<int32_t>(error));
+ ALOGE_IF(error != HWC2::Error::None,
+ "[%s] Failed to set "
+ "composition type %s: %s (%d)",
+ mName.string(), to_string(type).c_str(), to_string(error).c_str(),
+ static_cast<int32_t>(error));
}
}
}
@@ -1320,64 +845,6 @@
}
#endif
-uint32_t Layer::getProducerStickyTransform() const {
- int producerStickyTransform = 0;
- int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
- if (ret != OK) {
- ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
- strerror(-ret), ret);
- return 0;
- }
- return static_cast<uint32_t>(producerStickyTransform);
-}
-
-bool Layer::latchUnsignaledBuffers() {
- static bool propertyLoaded = false;
- static bool latch = false;
- static std::mutex mutex;
- std::lock_guard<std::mutex> lock(mutex);
- if (!propertyLoaded) {
- char value[PROPERTY_VALUE_MAX] = {};
- property_get("debug.sf.latch_unsignaled", value, "0");
- latch = atoi(value);
- propertyLoaded = true;
- }
- return latch;
-}
-
-uint64_t Layer::getHeadFrameNumber() const {
- Mutex::Autolock lock(mQueueItemLock);
- if (!mQueueItems.empty()) {
- return mQueueItems[0].mFrameNumber;
- } else {
- return mCurrentFrameNumber;
- }
-}
-
-bool Layer::headFenceHasSignaled() const {
-#ifdef USE_HWC2
- if (latchUnsignaledBuffers()) {
- return true;
- }
-
- Mutex::Autolock lock(mQueueItemLock);
- if (mQueueItems.empty()) {
- return true;
- }
- if (mQueueItems[0].mIsDroppable) {
- // Even though this buffer's fence may not have signaled yet, it could
- // be replaced by another buffer before it has a chance to, which means
- // that it's possible to get into a situation where a buffer is never
- // able to be latched. To avoid this, grab this buffer anyway.
- return true;
- }
- return mQueueItems[0].mFenceTime->getSignalTime() !=
- Fence::SIGNAL_TIME_PENDING;
-#else
- return true;
-#endif
-}
-
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
if (point->getFrameNumber() <= mCurrentFrameNumber) {
// Don't bother with a SyncPoint, since we've already latched the
@@ -1398,28 +865,6 @@
return mFiltering;
}
-// As documented in libhardware header, formats in the range
-// 0x100 - 0x1FF are specific to the HAL implementation, and
-// are known to have no alpha channel
-// TODO: move definition for device-specific range into
-// hardware.h, instead of using hard-coded values here.
-#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
-
-bool Layer::getOpacityForFormat(uint32_t format) {
- if (HARDWARE_IS_DEVICE_FORMAT(format)) {
- return true;
- }
- switch (format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_BGRA_8888:
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- case HAL_PIXEL_FORMAT_RGBA_1010102:
- return false;
- }
- // in all other case, we have no blending (also for unknown formats)
- return true;
-}
-
// ----------------------------------------------------------------------------
// local state
// ----------------------------------------------------------------------------
@@ -1471,49 +916,16 @@
position[1] = renderAreaTransform.transform(lb);
position[2] = renderAreaTransform.transform(rb);
position[3] = renderAreaTransform.transform(rt);
- for (size_t i=0 ; i<4 ; i++) {
+ for (size_t i = 0; i < 4; i++) {
position[i].y = height - position[i].y;
}
}
-bool Layer::isOpaque(const Layer::State& s) const
-{
- // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
- // layer's opaque flag.
- if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
- return false;
- }
-
- // if the layer has the opaque flag, then we're always opaque,
- // otherwise we use the current buffer's format.
- return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
-}
-
-bool Layer::isSecure() const
-{
+bool Layer::isSecure() const {
const Layer::State& s(mDrawingState);
return (s.flags & layer_state_t::eLayerSecure);
}
-bool Layer::isProtected() const
-{
- const sp<GraphicBuffer>& activeBuffer(mActiveBuffer);
- return (activeBuffer != 0) &&
- (activeBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-}
-
-bool Layer::isFixedSize() const {
- return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
-}
-
-bool Layer::isCropped() const {
- return !mCurrentCrop.isEmpty();
-}
-
-bool Layer::needsFiltering(const RenderArea& renderArea) const {
- return mNeedsFiltering || renderArea.needsFiltering();
-}
-
void Layer::setVisibleRegion(const Region& visibleRegion) {
// always called from main thread
this->visibleRegion = visibleRegion;
@@ -1524,8 +936,7 @@
this->coveredRegion = coveredRegion;
}
-void Layer::setVisibleNonTransparentRegion(const Region&
- setVisibleNonTransparentRegion) {
+void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) {
// always called from main thread
this->visibleNonTransparentRegion = setVisibleNonTransparentRegion;
}
@@ -1550,8 +961,7 @@
// to be applied as per normal (no synchronization).
mCurrentState.barrierLayer = nullptr;
} else {
- auto syncPoint = std::make_shared<SyncPoint>(
- mCurrentState.frameNumber);
+ auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber);
if (barrierLayer->addSyncPoint(syncPoint)) {
mRemoteSyncPoints.push_back(std::move(syncPoint));
} else {
@@ -1572,8 +982,8 @@
void Layer::popPendingState(State* stateToCommit) {
auto oldFlags = stateToCommit->flags;
*stateToCommit = mPendingStates[0];
- stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
- (stateToCommit->flags & stateToCommit->mask);
+ stateToCommit->flags =
+ (oldFlags & ~stateToCommit->mask) | (stateToCommit->flags & stateToCommit->mask);
mPendingStates.removeAt(0);
ATRACE_INT(mTransactionName.string(), mPendingStates.size());
@@ -1593,10 +1003,8 @@
continue;
}
- if (mRemoteSyncPoints.front()->getFrameNumber() !=
- mPendingStates[0].frameNumber) {
- ALOGE("[%s] Unexpected sync point frame number found",
- mName.string());
+ if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber) {
+ ALOGE("[%s] Unexpected sync point frame number found", mName.string());
// Signal our end of the sync point and then dispose of it
mRemoteSyncPoints.front()->setTransactionApplied();
@@ -1632,17 +1040,6 @@
return stateUpdateAvailable;
}
-void Layer::notifyAvailableFrames() {
- auto headFrameNumber = getHeadFrameNumber();
- bool headFenceSignaled = headFenceHasSignaled();
- Mutex::Autolock lock(mLocalSyncPointMutex);
- for (auto& point : mLocalSyncPoints) {
- if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
- point->setFrameAvailable();
- }
- }
-}
-
uint32_t Layer::doTransaction(uint32_t flags) {
ATRACE_CALL();
@@ -1654,40 +1051,25 @@
const Layer::State& s(getDrawingState());
- const bool sizeChanged = (c.requested.w != s.requested.w) ||
- (c.requested.h != s.requested.h);
+ const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h);
if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
ALOGD_IF(DEBUG_RESIZE,
- "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
- " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} }}\n"
- " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
- " requested={ wh={%4u,%4u} }}\n",
- this, getName().string(), mCurrentTransform,
- getEffectiveScalingMode(),
- c.active.w, c.active.h,
- c.crop.left,
- c.crop.top,
- c.crop.right,
- c.crop.bottom,
- c.crop.getWidth(),
- c.crop.getHeight(),
- c.requested.w, c.requested.h,
- s.active.w, s.active.h,
- s.crop.left,
- s.crop.top,
- s.crop.right,
- s.crop.bottom,
- s.crop.getWidth(),
- s.crop.getHeight(),
- s.requested.w, s.requested.h);
+ "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
+ " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+ " requested={ wh={%4u,%4u} }}\n"
+ " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
+ " requested={ wh={%4u,%4u} }}\n",
+ this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), c.active.w,
+ c.active.h, c.crop.left, c.crop.top, c.crop.right, c.crop.bottom,
+ c.crop.getWidth(), c.crop.getHeight(), c.requested.w, c.requested.h, s.active.w,
+ s.active.h, s.crop.left, s.crop.top, s.crop.right, s.crop.bottom,
+ s.crop.getWidth(), s.crop.getHeight(), s.requested.w, s.requested.h);
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
- mSurfaceFlingerConsumer->setDefaultBufferSize(
- c.requested.w, c.requested.h);
+ setDefaultBufferSize(c.requested.w, c.requested.h);
}
// Don't let Layer::doTransaction update the drawing state
@@ -1708,8 +1090,8 @@
// resizePending state is to avoid applying the state of the new buffer
// to the old buffer. However in the state where we don't have an old buffer
// there is no such concern but we may still be being used as a parent layer.
- const bool resizePending = ((c.requested.w != c.active.w) ||
- (c.requested.h != c.active.h)) && (mActiveBuffer != nullptr);
+ const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) &&
+ (mActiveBuffer != nullptr);
if (!isFixedSize()) {
if (resizePending && mSidebandStream == NULL) {
flags |= eDontUpdateGeometryState;
@@ -1758,8 +1140,7 @@
// we may use linear filtering, if the matrix scales us
const uint8_t type = c.active.transform.getType();
- mNeedsFiltering = (!c.active.transform.preserveRects() ||
- (type >= Transform::SCALE));
+ mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE));
}
// If the layer is hidden, signal and clear out all local sync points so
@@ -1822,8 +1203,7 @@
}
bool Layer::setLayer(int32_t z) {
- if (mCurrentState.z == z)
- return false;
+ if (mCurrentState.z == z) return false;
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
@@ -1881,8 +1261,7 @@
}
bool Layer::setSize(uint32_t w, uint32_t h) {
- if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
- return false;
+ if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false;
mCurrentState.requested.w = w;
mCurrentState.requested.h = h;
mCurrentState.modified = true;
@@ -1890,8 +1269,7 @@
return true;
}
bool Layer::setAlpha(float alpha) {
- if (mCurrentState.color.a == alpha)
- return false;
+ if (mCurrentState.color.a == alpha) return false;
mCurrentState.sequence++;
mCurrentState.color.a = alpha;
mCurrentState.modified = true;
@@ -1900,8 +1278,8 @@
}
bool Layer::setColor(const half3& color) {
- if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g
- && color.b == mCurrentState.color.b)
+ if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g &&
+ color.b == mCurrentState.color.b)
return false;
mCurrentState.sequence++;
@@ -1915,8 +1293,7 @@
bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
mCurrentState.sequence++;
- mCurrentState.requested.transform.set(
- matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+ mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -1929,8 +1306,7 @@
}
bool Layer::setFlags(uint8_t flags, uint8_t mask) {
const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
- if (mCurrentState.flags == newFlags)
- return false;
+ if (mCurrentState.flags == newFlags) return false;
mCurrentState.sequence++;
mCurrentState.flags = newFlags;
mCurrentState.mask = mask;
@@ -1940,8 +1316,7 @@
}
bool Layer::setCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.requestedCrop == crop)
- return false;
+ if (mCurrentState.requestedCrop == crop) return false;
mCurrentState.sequence++;
mCurrentState.requestedCrop = crop;
if (immediate && !mFreezeGeometryUpdates) {
@@ -1955,8 +1330,7 @@
}
bool Layer::setFinalCrop(const Rect& crop, bool immediate) {
- if (mCurrentState.requestedFinalCrop == crop)
- return false;
+ if (mCurrentState.requestedFinalCrop == crop) return false;
mCurrentState.sequence++;
mCurrentState.requestedFinalCrop = crop;
if (immediate && !mFreezeGeometryUpdates) {
@@ -1970,30 +1344,21 @@
}
bool Layer::setOverrideScalingMode(int32_t scalingMode) {
- if (scalingMode == mOverrideScalingMode)
- return false;
+ if (scalingMode == mOverrideScalingMode) return false;
mOverrideScalingMode = scalingMode;
setTransactionFlags(eTransactionNeeded);
return true;
}
void Layer::setInfo(uint32_t type, uint32_t appId) {
- mCurrentState.appId = appId;
- mCurrentState.type = type;
- mCurrentState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-}
-
-uint32_t Layer::getEffectiveScalingMode() const {
- if (mOverrideScalingMode >= 0) {
- return mOverrideScalingMode;
- }
- return mCurrentScalingMode;
+ mCurrentState.appId = appId;
+ mCurrentState.type = type;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
}
bool Layer::setLayerStack(uint32_t layerStack) {
- if (mCurrentState.layerStack == layerStack)
- return false;
+ if (mCurrentState.layerStack == layerStack) return false;
mCurrentState.sequence++;
mCurrentState.layerStack = layerStack;
mCurrentState.modified = true;
@@ -2002,8 +1367,7 @@
}
bool Layer::setDataSpace(android_dataspace dataSpace) {
- if (mCurrentState.dataSpace == dataSpace)
- return false;
+ if (mCurrentState.dataSpace == dataSpace) return false;
mCurrentState.sequence++;
mCurrentState.dataSpace = dataSpace;
mCurrentState.modified = true;
@@ -2023,8 +1387,7 @@
return p->getLayerStack();
}
-void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer,
- uint64_t frameNumber) {
+void Layer::deferTransactionUntil(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
mCurrentState.barrierLayer = barrierLayer;
mCurrentState.frameNumber = frameNumber;
// We don't set eTransactionNeeded, because just receiving a deferral
@@ -2036,124 +1399,16 @@
mCurrentState.modified = false;
}
-void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle,
- uint64_t frameNumber) {
+void Layer::deferTransactionUntil(const sp<IBinder>& barrierHandle, uint64_t frameNumber) {
sp<Handle> handle = static_cast<Handle*>(barrierHandle.get());
deferTransactionUntil(handle->owner.promote(), frameNumber);
}
-void Layer::useSurfaceDamage() {
- if (mFlinger->mForceFullDamage) {
- surfaceDamageRegion = Region::INVALID_REGION;
- } else {
- surfaceDamageRegion = mSurfaceFlingerConsumer->getSurfaceDamage();
- }
-}
-
-void Layer::useEmptyDamage() {
- surfaceDamageRegion.clear();
-}
// ----------------------------------------------------------------------------
// pageflip handling...
// ----------------------------------------------------------------------------
-bool Layer::shouldPresentNow(const DispSync& dispSync) const {
- if (mSidebandStreamChanged || mAutoRefresh) {
- return true;
- }
-
- Mutex::Autolock lock(mQueueItemLock);
- if (mQueueItems.empty()) {
- return false;
- }
- auto timestamp = mQueueItems[0].mTimestamp;
- nsecs_t expectedPresent =
- mSurfaceFlingerConsumer->computeExpectedPresent(dispSync);
-
- // Ignore timestamps more than a second in the future
- bool isPlausible = timestamp < (expectedPresent + s2ns(1));
- ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible "
- "relative to expectedPresent %" PRId64, mName.string(), timestamp,
- expectedPresent);
-
- bool isDue = timestamp < expectedPresent;
- return isDue || !isPlausible;
-}
-
-bool Layer::onPreComposition(nsecs_t refreshStartTime) {
- if (mBufferLatched) {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
- }
- mRefreshPending = false;
- return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
-}
-
-bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) {
- // mFrameLatencyNeeded is true when a new frame was latched for the
- // composition.
- if (!mFrameLatencyNeeded)
- return false;
-
- // Update mFrameEventHistory.
- {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
- glDoneFence, presentFence, compositorTiming);
- }
-
- // Update mFrameTracker.
- nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
- mFrameTracker.setDesiredPresentTime(desiredPresentTime);
-
- std::shared_ptr<FenceTime> frameReadyFence =
- mSurfaceFlingerConsumer->getCurrentFenceTime();
- if (frameReadyFence->isValid()) {
- mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
- } else {
- // There was no fence for this frame, so assume that it was ready
- // to be presented at the desired present time.
- mFrameTracker.setFrameReadyTime(desiredPresentTime);
- }
-
- if (presentFence->isValid()) {
- mFrameTracker.setActualPresentFence(
- std::shared_ptr<FenceTime>(presentFence));
- } else {
- // The HWC doesn't support present fences, so use the refresh
- // timestamp instead.
- mFrameTracker.setActualPresentTime(
- mFlinger->getHwComposer().getRefreshTimestamp(
- HWC_DISPLAY_PRIMARY));
- }
-
- mFrameTracker.advanceFrame();
- mFrameLatencyNeeded = false;
- return true;
-}
-
-#ifdef USE_HWC2
-void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {
- if (!mSurfaceFlingerConsumer->releasePendingBuffer()) {
- return;
- }
-
- auto releaseFenceTime = std::make_shared<FenceTime>(
- mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
- mReleaseTimeline.updateSignalTimes();
- mReleaseTimeline.push(releaseFenceTime);
-
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- if (mPreviousFrameNumber != 0) {
- mFrameEventHistory.addRelease(mPreviousFrameNumber,
- dequeueReadyTime, std::move(releaseFenceTime));
- }
-}
-#endif
-
bool Layer::isHiddenByPolicy() const {
const Layer::State& s(mDrawingState);
const auto& parent = mDrawingParent.promote();
@@ -2163,251 +1418,7 @@
return s.flags & layer_state_t::eLayerHidden;
}
-bool Layer::isVisible() const {
- return !(isHiddenByPolicy()) && getAlpha() > 0.0f
- && (mActiveBuffer != NULL || mSidebandStream != NULL);
-}
-
-bool Layer::allTransactionsSignaled() {
- auto headFrameNumber = getHeadFrameNumber();
- bool matchingFramesFound = false;
- bool allTransactionsApplied = true;
- Mutex::Autolock lock(mLocalSyncPointMutex);
-
- for (auto& point : mLocalSyncPoints) {
- if (point->getFrameNumber() > headFrameNumber) {
- break;
- }
- matchingFramesFound = true;
-
- if (!point->frameIsAvailable()) {
- // We haven't notified the remote layer that the frame for
- // this point is available yet. Notify it now, and then
- // abort this attempt to latch.
- point->setFrameAvailable();
- allTransactionsApplied = false;
- break;
- }
-
- allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied();
- }
- return !matchingFramesFound || allTransactionsApplied;
-}
-
-Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime)
-{
- ATRACE_CALL();
-
- if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
- // mSidebandStreamChanged was true
- mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
- if (mSidebandStream != NULL) {
- setTransactionFlags(eTransactionNeeded);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
- recomputeVisibleRegions = true;
-
- const State& s(getDrawingState());
- return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
- }
-
- Region outDirtyRegion;
- if (mQueuedFrames <= 0 && !mAutoRefresh) {
- return outDirtyRegion;
- }
-
- // if we've already called updateTexImage() without going through
- // a composition step, we have to skip this layer at this point
- // because we cannot call updateTeximage() without a corresponding
- // compositionComplete() call.
- // we'll trigger an update in onPreComposition().
- if (mRefreshPending) {
- return outDirtyRegion;
- }
-
- // If the head buffer's acquire fence hasn't signaled yet, return and
- // try again later
- if (!headFenceHasSignaled()) {
- mFlinger->signalLayerUpdate();
- return outDirtyRegion;
- }
-
- // Capture the old state of the layer for comparisons later
- const State& s(getDrawingState());
- const bool oldOpacity = isOpaque(s);
- sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
-
- if (!allTransactionsSignaled()) {
- mFlinger->signalLayerUpdate();
- return outDirtyRegion;
- }
-
- // This boolean is used to make sure that SurfaceFlinger's shadow copy
- // of the buffer queue isn't modified when the buffer queue is returning
- // BufferItem's that weren't actually queued. This can happen in shared
- // buffer mode.
- bool queuedBuffer = false;
- LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName.string(),
- mOverrideScalingMode, mFreezeGeometryUpdates);
- status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
- mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived);
- if (updateResult == BufferQueue::PRESENT_LATER) {
- // Producer doesn't want buffer to be displayed yet. Signal a
- // layer update so we check again at the next opportunity.
- mFlinger->signalLayerUpdate();
- return outDirtyRegion;
- } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
- // If the buffer has been rejected, remove it from the shadow queue
- // and return early
- if (queuedBuffer) {
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
- }
- return outDirtyRegion;
- } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
- // This can occur if something goes wrong when trying to create the
- // EGLImage for this buffer. If this happens, the buffer has already
- // been released, so we need to clean up the queue and bug out
- // early.
- if (queuedBuffer) {
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.clear();
- android_atomic_and(0, &mQueuedFrames);
- }
-
- // Once we have hit this state, the shadow queue may no longer
- // correctly reflect the incoming BufferQueue's contents, so even if
- // updateTexImage starts working, the only safe course of action is
- // to continue to ignore updates.
- mUpdateTexImageFailed = true;
-
- return outDirtyRegion;
- }
-
- if (queuedBuffer) {
- // Autolock scope
- auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
- Mutex::Autolock lock(mQueueItemLock);
-
- // Remove any stale buffers that have been dropped during
- // updateTexImage
- while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
- }
-
- mQueueItems.removeAt(0);
- }
-
-
- // Decrement the queued-frames count. Signal another event if we
- // have more frames pending.
- if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
- || mAutoRefresh) {
- mFlinger->signalLayerUpdate();
- }
-
- // update the active buffer
- mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer(
- &mActiveBufferSlot);
- if (mActiveBuffer == NULL) {
- // this can only happen if the very first buffer was rejected.
- return outDirtyRegion;
- }
-
- mBufferLatched = true;
- mPreviousFrameNumber = mCurrentFrameNumber;
- mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
- {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
-#ifndef USE_HWC2
- auto releaseFenceTime = std::make_shared<FenceTime>(
- mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
- mReleaseTimeline.updateSignalTimes();
- mReleaseTimeline.push(releaseFenceTime);
- if (mPreviousFrameNumber != 0) {
- mFrameEventHistory.addRelease(mPreviousFrameNumber,
- latchTime, std::move(releaseFenceTime));
- }
-#endif
- }
-
- mRefreshPending = true;
- mFrameLatencyNeeded = true;
- if (oldActiveBuffer == NULL) {
- // the first time we receive a buffer, we need to trigger a
- // geometry invalidation.
- recomputeVisibleRegions = true;
- }
-
- setDataSpace(mSurfaceFlingerConsumer->getCurrentDataSpace());
-
- Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
- const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
- const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
- if ((crop != mCurrentCrop) ||
- (transform != mCurrentTransform) ||
- (scalingMode != mCurrentScalingMode))
- {
- mCurrentCrop = crop;
- mCurrentTransform = transform;
- mCurrentScalingMode = scalingMode;
- recomputeVisibleRegions = true;
- }
-
- if (oldActiveBuffer != NULL) {
- uint32_t bufWidth = mActiveBuffer->getWidth();
- uint32_t bufHeight = mActiveBuffer->getHeight();
- if (bufWidth != uint32_t(oldActiveBuffer->width) ||
- bufHeight != uint32_t(oldActiveBuffer->height)) {
- recomputeVisibleRegions = true;
- }
- }
-
- mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
- if (oldOpacity != isOpaque(s)) {
- recomputeVisibleRegions = true;
- }
-
- // Remove any sync points corresponding to the buffer which was just
- // latched
- {
- Mutex::Autolock lock(mLocalSyncPointMutex);
- auto point = mLocalSyncPoints.begin();
- while (point != mLocalSyncPoints.end()) {
- if (!(*point)->frameIsAvailable() ||
- !(*point)->transactionIsApplied()) {
- // This sync point must have been added since we started
- // latching. Don't drop it yet.
- ++point;
- continue;
- }
-
- if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
- point = mLocalSyncPoints.erase(point);
- } else {
- ++point;
- }
- }
- }
-
- // FIXME: postedRegion should be dirty & bounds
- Region dirtyRegion(Rect(s.active.w, s.active.h));
-
- // transform the dirty region to window-manager space
- outDirtyRegion = (getTransform().transform(dirtyRegion));
-
- return outDirtyRegion;
-}
-
-uint32_t Layer::getEffectiveUsage(uint32_t usage) const
-{
+uint32_t Layer::getEffectiveUsage(uint32_t usage) const {
// TODO: should we do something special if mSecure is set?
if (mProtectedByApp) {
// need a hardware-protected path to external video sink
@@ -2432,7 +1443,7 @@
orientation = 0;
}
}
- mSurfaceFlingerConsumer->setTransformHint(orientation);
+ setTransformHint(orientation);
}
// ----------------------------------------------------------------------------
@@ -2519,14 +1530,11 @@
const Layer::State& layerState(getDrawingState());
const HWCInfo& hwcInfo = mHwcLayers.at(hwcId);
result.appendFormat(" %10d | ", layerState.z);
- result.appendFormat("%10s | ",
- to_string(getCompositionType(hwcId)).c_str());
+ result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str());
const Rect& frame = hwcInfo.displayFrame;
- result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
- frame.right, frame.bottom);
+ result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
const FloatRect& crop = hwcInfo.sourceCrop;
- result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
- crop.right, crop.bottom);
+ result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom);
result.append("- - - - - - - - - - - - - - - - - - - - ");
result.append("- - - - - - - - - - - - - - - - - - - -\n");
@@ -2550,8 +1558,7 @@
}
void Layer::dumpFrameEvents(String8& result) {
- result.appendFormat("- Layer %s (%s, %p)\n",
- getName().string(), getTypeId(), this);
+ result.appendFormat("- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this);
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.checkFencesForCompletion();
mFrameEventHistory.dump(result);
@@ -2563,7 +1570,7 @@
}
void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
- FrameEventHistoryDelta *outDelta) {
+ FrameEventHistoryDelta* outDelta) {
Mutex::Autolock lock(mFrameEventHistoryMutex);
if (newTimestamps) {
// If there are any unsignaled fences in the aquire timeline at this
@@ -2581,23 +1588,6 @@
}
}
-std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory(
- bool forceFlush) {
- std::vector<OccupancyTracker::Segment> history;
- status_t result = mSurfaceFlingerConsumer->getOccupancyHistory(forceFlush,
- &history);
- if (result != NO_ERROR) {
- ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(),
- result);
- return {};
- }
- return history;
-}
-
-bool Layer::getTransformToDisplayInverse() const {
- return mSurfaceFlingerConsumer->getTransformToDisplayInverse();
-}
-
size_t Layer::getChildrenCount() const {
size_t count = 0;
for (const sp<Layer>& child : mCurrentChildren) {
@@ -2706,8 +1696,8 @@
return mDrawingState.z;
}
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-LayerVector Layer::makeTraversalList(LayerVector::StateSet stateSet) {
+__attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList(
+ LayerVector::StateSet stateSet) {
LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid,
"makeTraversalList received invalid stateSet");
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
@@ -2762,7 +1752,7 @@
LayerVector list = makeTraversalList(stateSet);
int32_t i = 0;
- for (i = list.size()-1; i>=0; i--) {
+ for (i = int32_t(list.size()) - 1; i >= 0; i--) {
const auto& relative = list[i];
if (relative->getZ() < 0) {
break;
@@ -2770,7 +1760,7 @@
relative->traverseInReverseZOrder(stateSet, visitor);
}
visitor(this);
- for (; i>=0; i--) {
+ for (; i >= 0; i--) {
const auto& relative = list[i];
relative->traverseInReverseZOrder(stateSet, visitor);
}
@@ -2820,10 +1810,8 @@
bufferHeight = p->mActiveBuffer->getWidth();
bufferWidth = p->mActiveBuffer->getHeight();
}
- float sx = p->getDrawingState().active.w /
- static_cast<float>(bufferWidth);
- float sy = p->getDrawingState().active.h /
- static_cast<float>(bufferHeight);
+ float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth);
+ float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight);
Transform extraParentScaling;
extraParentScaling.set(sx, 0, 0, sy);
t = t * extraParentScaling;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index d75e175..0580b9f 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -37,20 +37,19 @@
#include <list>
-#include "FrameTracker.h"
#include "Client.h"
+#include "FrameTracker.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
-#include "SurfaceFlingerConsumer.h"
#include "Transform.h"
+#include <layerproto/LayerProtoHeader.h>
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/HWComposerBufferCache.h"
+#include "RenderArea.h"
#include "RenderEngine/Mesh.h"
#include "RenderEngine/Texture.h"
-#include <layerproto/LayerProtoHeader.h>
-#include "RenderArea.h"
#include <math/vec4.h>
@@ -69,14 +68,7 @@
// ---------------------------------------------------------------------------
-/*
- * A new BufferQueue and a new SurfaceFlingerConsumer are created when the
- * Layer is first referenced.
- *
- * This also implements onFrameAvailable(), which notifies SurfaceFlinger
- * that new data has arrived.
- */
-class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {
+class Layer : public virtual RefBase {
static int32_t sSequence;
public:
@@ -102,14 +94,11 @@
uint32_t h;
Transform transform;
- inline bool operator ==(const Geometry& rhs) const {
- return (w == rhs.w && h == rhs.h) &&
- (transform.tx() == rhs.transform.tx()) &&
+ inline bool operator==(const Geometry& rhs) const {
+ return (w == rhs.w && h == rhs.h) && (transform.tx() == rhs.transform.tx()) &&
(transform.ty() == rhs.transform.ty());
}
- inline bool operator !=(const Geometry& rhs) const {
- return !operator ==(rhs);
- }
+ inline bool operator!=(const Geometry& rhs) const { return !operator==(rhs); }
};
struct State {
@@ -162,18 +151,12 @@
half4 color;
};
- // -----------------------------------------------------------------------
-
- Layer(SurfaceFlinger* flinger, const sp<Client>& client,
- const String8& name, uint32_t w, uint32_t h, uint32_t flags);
-
+ Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags);
virtual ~Layer();
void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; }
- // the this layer's size and format
- status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);
-
// ------------------------------------------------------------------------
// Geometry setting functions.
//
@@ -246,8 +229,8 @@
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
// one empty rect.
- void useSurfaceDamage();
- void useEmptyDamage();
+ virtual void useSurfaceDamage() = 0;
+ virtual void useEmptyDamage() = 0;
uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags);
@@ -264,8 +247,7 @@
// -----------------------------------------------------------------------
// Virtuals
-
- virtual const char* getTypeId() const { return "Layer"; }
+ virtual const char* getTypeId() const = 0;
/*
* isOpaque - true if this surface is opaque
@@ -274,24 +256,18 @@
* pixel format includes an alpha channel) and the "opaque" flag set
* on the layer. It does not examine the current plane alpha value.
*/
- virtual bool isOpaque(const Layer::State& s) const;
+ virtual bool isOpaque(const Layer::State& s) const = 0;
/*
* isSecure - true if this surface is secure, that is if it prevents
* screenshots or VNC servers.
*/
- virtual bool isSecure() const;
-
- /*
- * isProtected - true if the layer may contain protected content in the
- * GRALLOC_USAGE_PROTECTED sense.
- */
- virtual bool isProtected() const;
+ bool isSecure() const;
/*
* isVisible - true if this layer is visible, false otherwise
*/
- virtual bool isVisible() const;
+ virtual bool isVisible() const = 0;
/*
* isHiddenByPolicy - true if this layer has been forced invisible.
@@ -299,48 +275,45 @@
* For example if this layer has no active buffer, it may not be hidden by
* policy, but it still can not be visible.
*/
- virtual bool isHiddenByPolicy() const;
+ bool isHiddenByPolicy() const;
/*
* isFixedSize - true if content has a fixed size
*/
- virtual bool isFixedSize() const;
+ virtual bool isFixedSize() const = 0;
- void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
+ bool isPendingRemoval() const { return mPendingRemoval; }
+
+ void writeToProto(LayerProto* layerInfo,
+ LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
protected:
/*
* onDraw - draws the surface.
*/
virtual void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const;
+ bool useIdentityTransform) const = 0;
public:
- // -----------------------------------------------------------------------
+ virtual void setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
#ifdef USE_HWC2
void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
void forceClientComposition(int32_t hwcId);
- void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
+ virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0;
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
- void setCompositionType(int32_t hwcId, HWC2::Composition type,
- bool callIntoHwc = true);
+ void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true);
HWC2::Composition getCompositionType(int32_t hwcId) const;
-
void setClearClientTarget(int32_t hwcId, bool clear);
bool getClearClientTarget(int32_t hwcId) const;
-
void updateCursorPosition(const sp<const DisplayDevice>& hw);
#else
- void setGeometry(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer);
- void setPerFrameData(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer);
- void setAcquireFence(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer);
-
+ void setGeometry(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer);
+ void setPerFrameData(const sp<const DisplayDevice>& hw, HWComposer::HWCLayerInterface& layer);
+ virtual void setAcquireFence(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface& layer) = 0;
Rect getPosition(const sp<const DisplayDevice>& hw);
#endif
@@ -348,31 +321,34 @@
* called after page-flip
*/
#ifdef USE_HWC2
- void onLayerDisplayed(const sp<Fence>& releaseFence);
+ virtual void onLayerDisplayed(const sp<Fence>& releaseFence);
#else
- void onLayerDisplayed(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface* layer);
+ virtual void onLayerDisplayed(const sp<const DisplayDevice>& hw,
+ HWComposer::HWCLayerInterface* layer);
#endif
- bool shouldPresentNow(const DispSync& dispSync) const;
+ virtual void abandon() = 0;
+
+ virtual bool shouldPresentNow(const DispSync& dispSync) const = 0;
+ virtual void setTransformHint(uint32_t orientation) const = 0;
/*
* called before composition.
* returns true if the layer has pending updates.
*/
- bool onPreComposition(nsecs_t refreshStartTime);
+ virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
/*
* called after composition.
* returns true if the layer latched a new buffer this frame.
*/
- bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming);
+ virtual bool onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) = 0;
#ifdef USE_HWC2
// If a buffer was replaced this frame, release the former buffer
- void releasePendingBuffer(nsecs_t dequeueReadyTime);
+ virtual void releasePendingBuffer(nsecs_t dequeueReadyTime) = 0;
#endif
/*
@@ -406,8 +382,7 @@
* setVisibleNonTransparentRegion - called when the visible and
* non-transparent region changes.
*/
- void setVisibleNonTransparentRegion(const Region&
- visibleNonTransparentRegion);
+ void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion);
/*
* latchBuffer - called each time the screen is redrawn and returns whether
@@ -415,11 +390,10 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime);
- bool isBufferLatched() const { return mRefreshPending; }
+ virtual Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+ virtual bool isBufferLatched() const = 0;
- bool isPotentialCursor() const { return mPotentialCursor;}
-
+ bool isPotentialCursor() const { return mPotentialCursor; }
/*
* called with the state lock from a binder thread when the layer is
* removed from the current list to the pending removal list
@@ -432,7 +406,6 @@
*/
void onRemoved();
-
// Updates the transform hint in our SurfaceFlingerConsumer to match
// the current orientation of the display device.
void updateTransformHint(const sp<const DisplayDevice>& hw) const;
@@ -446,8 +419,9 @@
/*
* Returns if a frame is queued.
*/
- bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
- mSidebandStreamChanged || mAutoRefresh; }
+ bool hasQueuedFrame() const {
+ return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
+ }
int32_t getQueuedFrameCount() const { return mQueuedFrames; }
@@ -458,9 +432,7 @@
void destroyHwcLayer(int32_t hwcId);
void destroyAllHwcLayers();
- bool hasHwcLayer(int32_t hwcId) {
- return mHwcLayers.count(hwcId) > 0;
- }
+ bool hasHwcLayer(int32_t hwcId) { return mHwcLayers.count(hwcId) > 0; }
HWC2::Layer* getHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
@@ -479,9 +451,9 @@
// only for debugging
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
- inline const State& getDrawingState() const { return mDrawingState; }
- inline const State& getCurrentState() const { return mCurrentState; }
- inline State& getCurrentState() { return mCurrentState; }
+ inline const State& getDrawingState() const { return mDrawingState; }
+ inline const State& getCurrentState() const { return mCurrentState; }
+ inline State& getCurrentState() { return mCurrentState; }
LayerDebugInfo getLayerDebugInfo() const;
@@ -496,13 +468,13 @@
void logFrameStats();
void getFrameStats(FrameStats* outStats) const;
- std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush);
+ virtual std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) = 0;
void onDisconnect();
void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry,
- FrameEventHistoryDelta* outDelta);
+ FrameEventHistoryDelta* outDelta);
- bool getTransformToDisplayInverse() const;
+ virtual bool getTransformToDisplayInverse() const = 0;
Transform getTransform() const;
@@ -526,15 +498,14 @@
ssize_t removeChild(const sp<Layer>& layer);
sp<Layer> getParent() const { return mCurrentParent.promote(); }
bool hasParent() const { return getParent() != nullptr; }
-
Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
// Copy the current list of children to the drawing state. Called by
// SurfaceFlinger to complete a transaction.
void commitChildList();
-
int32_t getZ() const;
+
protected:
// constant
sp<SurfaceFlinger> mFlinger;
@@ -545,56 +516,36 @@
class LayerCleaner {
sp<SurfaceFlinger> mFlinger;
wp<Layer> mLayer;
+
protected:
~LayerCleaner() {
// destroy client resources
mFlinger->onLayerDestroyed(mLayer);
}
- public:
- LayerCleaner(const sp<SurfaceFlinger>& flinger,
- const sp<Layer>& layer)
- : mFlinger(flinger), mLayer(layer) {
- }
- };
+ public:
+ LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+ : mFlinger(flinger), mLayer(layer) {}
+ };
virtual void onFirstRef();
-
-
-private:
friend class SurfaceInterceptor;
- // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
- virtual void onFrameAvailable(const BufferItem& item) override;
- virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onSidebandStreamChanged() override;
void commitTransaction(const State& stateToCommit);
- // needsLinearFiltering - true if this surface's state requires filtering
- bool needsFiltering(const RenderArea& renderArea) const;
-
uint32_t getEffectiveUsage(uint32_t usage) const;
FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
- // Compute the initial crop as specified by parent layers and the SurfaceControl
- // for this layer. Does not include buffer crop from the IGraphicBufferProducer
- // client, as that should not affect child clipping. Returns in screen space.
+ // Compute the initial crop as specified by parent layers and the
+ // SurfaceControl for this layer. Does not include buffer crop from the
+ // IGraphicBufferProducer client, as that should not affect child clipping.
+ // Returns in screen space.
Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const;
- bool isCropped() const;
- static bool getOpacityForFormat(uint32_t format);
// drawing
- void clearWithOpenGL(const RenderArea& renderArea,
- float r, float g, float b, float alpha) const;
- void drawWithOpenGL(const RenderArea& renderArea,
- bool useIdentityTransform) const;
-
- // Temporary - Used only for LEGACY camera mode.
- uint32_t getProducerStickyTransform() const;
-
- // Loads the corresponding system property once per process
- static bool latchUnsignaledBuffers();
+ void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
+ float alpha) const;
void setParent(const sp<Layer>& layer);
@@ -602,33 +553,20 @@
void addZOrderRelative(const wp<Layer>& relative);
void removeZOrderRelative(const wp<Layer>& relative);
- // -----------------------------------------------------------------------
-
- class SyncPoint
- {
+ class SyncPoint {
public:
- explicit SyncPoint(uint64_t frameNumber) : mFrameNumber(frameNumber),
- mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+ explicit SyncPoint(uint64_t frameNumber)
+ : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
- uint64_t getFrameNumber() const {
- return mFrameNumber;
- }
+ uint64_t getFrameNumber() const { return mFrameNumber; }
- bool frameIsAvailable() const {
- return mFrameIsAvailable;
- }
+ bool frameIsAvailable() const { return mFrameIsAvailable; }
- void setFrameAvailable() {
- mFrameIsAvailable = true;
- }
+ void setFrameAvailable() { mFrameIsAvailable = true; }
- bool transactionIsApplied() const {
- return mTransactionIsApplied;
- }
+ bool transactionIsApplied() const { return mTransactionIsApplied; }
- void setTransactionApplied() {
- mTransactionIsApplied = true;
- }
+ void setTransactionApplied() { mTransactionIsApplied = true; }
private:
const uint64_t mFrameNumber;
@@ -646,9 +584,6 @@
// is applied
std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints;
- uint64_t getHeadFrameNumber() const;
- bool headFenceHasSignaled() const;
-
// Returns false if the relevant frame has already been latched
bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
@@ -661,7 +596,8 @@
// Returns mCurrentScaling mode (originating from the
// Client) or mOverrideScalingMode mode (originating from
// the Surface Controller) if set.
- uint32_t getEffectiveScalingMode() const;
+ virtual uint32_t getEffectiveScalingMode() const = 0;
+
public:
/*
* The layer handle is just a BBinder object passed to the client
@@ -672,36 +608,25 @@
* this layer when the handle is destroyed.
*/
class Handle : public BBinder, public LayerCleaner {
- public:
- Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
- : LayerCleaner(flinger, layer), owner(layer) {}
+ public:
+ Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+ : LayerCleaner(flinger, layer), owner(layer) {}
- wp<Layer> owner;
+ wp<Layer> owner;
};
sp<IBinder> getHandle();
- sp<IGraphicBufferProducer> getProducer() const;
const String8& getName() const;
- void notifyAvailableFrames();
- PixelFormat getPixelFormat() const { return mFormat; }
+ virtual void notifyAvailableFrames() = 0;
+ virtual PixelFormat getPixelFormat() const = 0;
bool getPremultipledAlpha() const;
-private:
+protected:
// -----------------------------------------------------------------------
- // Check all of the local sync points to ensure that all transactions
- // which need to have been applied prior to the frame which is about to
- // be latched have signaled
- bool allTransactionsSignaled();
-
- // constants
- sp<SurfaceFlingerConsumer> mSurfaceFlingerConsumer;
- sp<IGraphicBufferProducer> mProducer;
- uint32_t mTextureName; // from GLES
bool mPremultipliedAlpha;
String8 mName;
String8 mTransactionName; // A cached version of "TX - " + mName for systraces
- PixelFormat mFormat;
bool mPrimaryDisplayOnly = false;
@@ -734,14 +659,10 @@
sp<NativeHandle> mSidebandStream;
Rect mCurrentCrop;
uint32_t mCurrentTransform;
- uint32_t mCurrentScalingMode;
// We encode unset as -1.
int32_t mOverrideScalingMode;
bool mCurrentOpacity;
- bool mBufferLatched = false; // TODO: Use mActiveBuffer?
std::atomic<uint64_t> mCurrentFrameNumber;
- uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
- bool mRefreshPending;
bool mFrameLatencyNeeded;
// Whether filtering is forced on or not
bool mFiltering;
@@ -749,18 +670,18 @@
bool mNeedsFiltering;
// The mesh used to draw the layer in GLES composition mode
mutable Mesh mMesh;
- // The texture used to draw the layer in GLES composition mode
- mutable Texture mTexture;
+
+ bool mPendingRemoval = false;
#ifdef USE_HWC2
// HWC items, accessed from the main thread
struct HWCInfo {
HWCInfo()
- : hwc(nullptr),
- layer(nullptr),
- forceClientComposition(false),
- compositionType(HWC2::Composition::Invalid),
- clearClientTarget(false) {}
+ : hwc(nullptr),
+ layer(nullptr),
+ forceClientComposition(false),
+ compositionType(HWC2::Composition::Invalid),
+ clearClientTarget(false) {}
HWComposer* hwc;
HWC2::Layer* layer;
@@ -786,8 +707,7 @@
// protected by mLock
mutable Mutex mLock;
- // Set to true once we've returned this surface's handle
- mutable bool mHasSurface;
+
const wp<Client> mClientRef;
// This layer can be a cursor on some displays.
@@ -798,8 +718,6 @@
Condition mQueueItemCondition;
Vector<BufferItem> mQueueItems;
std::atomic<uint64_t> mLastFrameNumberReceived;
- bool mUpdateTexImageFailed; // This is only accessed on the main thread.
-
bool mAutoRefresh;
bool mFreezeGeometryUpdates;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 77b9a29..4ca9acb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -72,6 +72,7 @@
#include "EventControlThread.h"
#include "EventThread.h"
#include "Layer.h"
+#include "BufferLayer.h"
#include "LayerVector.h"
#include "ColorLayer.h"
#include "MonitoredProducer.h"
@@ -2856,6 +2857,10 @@
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer, bool topLevelOnly) {
Mutex::Autolock _l(mStateLock);
+ if (layer->isPendingRemoval()) {
+ return NO_ERROR;
+ }
+
const auto& p = layer->getParent();
ssize_t index;
if (p != nullptr) {
@@ -3059,131 +3064,139 @@
const sp<Client>& client,
const layer_state_t& s)
{
- uint32_t flags = 0;
sp<Layer> layer(client->getLayerUser(s.surface));
- if (layer != 0) {
- const uint32_t what = s.what;
- bool geometryAppliesWithResize =
- what & layer_state_t::eGeometryAppliesWithResize;
- if (what & layer_state_t::ePositionChanged) {
- if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
- flags |= eTraversalNeeded;
- }
+ if (layer == nullptr) {
+ return 0;
+ }
+
+ if (layer->isPendingRemoval()) {
+ ALOGW("Attempting to set client state on removed layer: %s", layer->getName().string());
+ return 0;
+ }
+
+ uint32_t flags = 0;
+
+ const uint32_t what = s.what;
+ bool geometryAppliesWithResize =
+ what & layer_state_t::eGeometryAppliesWithResize;
+ if (what & layer_state_t::ePositionChanged) {
+ if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) {
+ flags |= eTraversalNeeded;
}
- if (what & layer_state_t::eLayerChanged) {
- // NOTE: index needs to be calculated before we update the state
- const auto& p = layer->getParent();
- if (p == nullptr) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setLayer(s.z) && idx >= 0) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- // we need traversal (state changed)
- // AND transaction (list changed)
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- } else {
- if (p->setChildLayer(layer, s.z)) {
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- }
- if (what & layer_state_t::eRelativeLayerChanged) {
+ }
+ if (what & layer_state_t::eLayerChanged) {
+ // NOTE: index needs to be calculated before we update the state
+ const auto& p = layer->getParent();
+ if (p == nullptr) {
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
- mCurrentState.layersSortedByZ.removeAt(idx);
- mCurrentState.layersSortedByZ.add(layer);
- flags |= eTransactionNeeded|eTraversalNeeded;
- }
- }
- if (what & layer_state_t::eSizeChanged) {
- if (layer->setSize(s.w, s.h)) {
- flags |= eTraversalNeeded;
- }
- }
- if (what & layer_state_t::eAlphaChanged) {
- if (layer->setAlpha(s.alpha))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eColorChanged) {
- if (layer->setColor(s.color))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eMatrixChanged) {
- if (layer->setMatrix(s.matrix))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eTransparentRegionChanged) {
- if (layer->setTransparentRegionHint(s.transparentRegion))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eFlagsChanged) {
- if (layer->setFlags(s.flags, s.mask))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eCropChanged) {
- if (layer->setCrop(s.crop, !geometryAppliesWithResize))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eFinalCropChanged) {
- if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
- flags |= eTraversalNeeded;
- }
- if (what & layer_state_t::eLayerStackChanged) {
- ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
- // We only allow setting layer stacks for top level layers,
- // everything else inherits layer stack from its parent.
- if (layer->hasParent()) {
- ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
- layer->getName().string());
- } else if (idx < 0) {
- ALOGE("Attempt to set layer stack on layer without parent (%s) that "
- "that also does not appear in the top level layer list. Something"
- " has gone wrong.", layer->getName().string());
- } else if (layer->setLayerStack(s.layerStack)) {
+ if (layer->setLayer(s.z) && idx >= 0) {
mCurrentState.layersSortedByZ.removeAt(idx);
mCurrentState.layersSortedByZ.add(layer);
// we need traversal (state changed)
// AND transaction (list changed)
flags |= eTransactionNeeded|eTraversalNeeded;
}
- }
- if (what & layer_state_t::eDeferTransaction) {
- if (s.barrierHandle != nullptr) {
- layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
- } else if (s.barrierGbp != nullptr) {
- const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
- if (authenticateSurfaceTextureLocked(gbp)) {
- const auto& otherLayer =
- (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
- layer->deferTransactionUntil(otherLayer, s.frameNumber);
- } else {
- ALOGE("Attempt to defer transaction to to an"
- " unrecognized GraphicBufferProducer");
- }
- }
- // We don't trigger a traversal here because if no other state is
- // changed, we don't want this to cause any more work
- }
- if (what & layer_state_t::eReparent) {
- if (layer->reparent(s.parentHandleForChild)) {
+ } else {
+ if (p->setChildLayer(layer, s.z)) {
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
- if (what & layer_state_t::eReparentChildren) {
- if (layer->reparentChildren(s.reparentHandle)) {
- flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ if (what & layer_state_t::eRelativeLayerChanged) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eSizeChanged) {
+ if (layer->setSize(s.w, s.h)) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eAlphaChanged) {
+ if (layer->setAlpha(s.alpha))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eColorChanged) {
+ if (layer->setColor(s.color))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eMatrixChanged) {
+ if (layer->setMatrix(s.matrix))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eTransparentRegionChanged) {
+ if (layer->setTransparentRegionHint(s.transparentRegion))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eFlagsChanged) {
+ if (layer->setFlags(s.flags, s.mask))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eCropChanged) {
+ if (layer->setCrop(s.crop, !geometryAppliesWithResize))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eFinalCropChanged) {
+ if (layer->setFinalCrop(s.finalCrop, !geometryAppliesWithResize))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eLayerStackChanged) {
+ ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+ // We only allow setting layer stacks for top level layers,
+ // everything else inherits layer stack from its parent.
+ if (layer->hasParent()) {
+ ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
+ layer->getName().string());
+ } else if (idx < 0) {
+ ALOGE("Attempt to set layer stack on layer without parent (%s) that "
+ "that also does not appear in the top level layer list. Something"
+ " has gone wrong.", layer->getName().string());
+ } else if (layer->setLayerStack(s.layerStack)) {
+ mCurrentState.layersSortedByZ.removeAt(idx);
+ mCurrentState.layersSortedByZ.add(layer);
+ // we need traversal (state changed)
+ // AND transaction (list changed)
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eDeferTransaction) {
+ if (s.barrierHandle != nullptr) {
+ layer->deferTransactionUntil(s.barrierHandle, s.frameNumber);
+ } else if (s.barrierGbp != nullptr) {
+ const sp<IGraphicBufferProducer>& gbp = s.barrierGbp;
+ if (authenticateSurfaceTextureLocked(gbp)) {
+ const auto& otherLayer =
+ (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
+ layer->deferTransactionUntil(otherLayer, s.frameNumber);
+ } else {
+ ALOGE("Attempt to defer transaction to to an"
+ " unrecognized GraphicBufferProducer");
}
}
- if (what & layer_state_t::eDetachChildren) {
- layer->detachChildren();
+ // We don't trigger a traversal here because if no other state is
+ // changed, we don't want this to cause any more work
+ }
+ if (what & layer_state_t::eReparent) {
+ if (layer->reparent(s.parentHandleForChild)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
}
- if (what & layer_state_t::eOverrideScalingModeChanged) {
- layer->setOverrideScalingMode(s.overrideScalingMode);
- // We don't trigger a traversal here because if no other state is
- // changed, we don't want this to cause any more work
+ }
+ if (what & layer_state_t::eReparentChildren) {
+ if (layer->reparentChildren(s.reparentHandle)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
}
}
+ if (what & layer_state_t::eDetachChildren) {
+ layer->detachChildren();
+ }
+ if (what & layer_state_t::eOverrideScalingModeChanged) {
+ layer->setOverrideScalingMode(s.overrideScalingMode);
+ // We don't trigger a traversal here because if no other state is
+ // changed, we don't want this to cause any more work
+ }
return flags;
}
@@ -3208,14 +3221,15 @@
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
- result = createNormalLayer(client,
+ result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
+
break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
- handle, gbp, &layer);
+ handle, &layer);
break;
default:
result = BAD_VALUE;
@@ -3269,7 +3283,7 @@
return uniqueName;
}
-status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
@@ -3284,24 +3298,24 @@
break;
}
- *outLayer = new Layer(this, client, name, w, h, flags);
- status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+ sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
+ status_t err = layer->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
+ *handle = layer->getHandle();
+ *gbp = layer->getProducer();
+ *outLayer = layer;
}
- ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+ ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
return err;
}
status_t SurfaceFlinger::createColorLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+ sp<IBinder>* handle, sp<Layer>* outLayer)
{
*outLayer = new ColorLayer(this, client, name, w, h, flags);
*handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d0f4699..d10b41b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -244,6 +244,7 @@
friend class DisplayEventConnection;
friend class EventThread;
friend class Layer;
+ friend class BufferLayer;
friend class MonitoredProducer;
// This value is specified in number of frames. Log frame stats at most
@@ -419,14 +420,14 @@
uint32_t windowType, uint32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
- status_t createNormalLayer(const sp<Client>& client, const String8& name,
+ status_t createBufferLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
sp<Layer>* outLayer);
status_t createColorLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
- sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
+ sp<Layer>* outLayer);
String8 getUniqueLayerName(const String8& name);
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 952023e..714c23d 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -70,6 +70,7 @@
#include "EventControlThread.h"
#include "EventThread.h"
#include "Layer.h"
+#include "BufferLayer.h"
#include "LayerVector.h"
#include "ColorLayer.h"
#include "MonitoredProducer.h"
@@ -2733,14 +2734,14 @@
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
- result = createNormalLayer(client,
+ result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
- handle, gbp, &layer);
+ handle, &layer);
break;
default:
result = BAD_VALUE;
@@ -2787,7 +2788,7 @@
return uniqueName;
}
-status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
@@ -2802,24 +2803,24 @@
break;
}
- *outLayer = new Layer(this, client, name, w, h, flags);
- status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+ sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
+ status_t err = layer->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
- *handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
+ *handle = layer->getHandle();
+ *gbp = layer->getProducer();
+ *outLayer = layer;
}
- ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+ ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err));
return err;
}
status_t SurfaceFlinger::createColorLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+ sp<IBinder>* handle, sp<Layer>* outLayer)
{
*outLayer = new ColorLayer(this, client, name, w, h, flags);
*handle = (*outLayer)->getHandle();
- *gbp = (*outLayer)->getProducer();
return NO_ERROR;
}
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 9201520..e92b8d8 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -44,6 +44,13 @@
cflags: [
"-DLOG_TAG=\"vr_hwc\"",
+ "-Wall",
+ "-Werror",
+ // mVrClient unused in vr_composer_client.cpp
+ "-Wno-error=unused-private-field",
+ // Warnings in vr_hwc.cpp to be fixed after sync of goog/master.
+ "-Wno-sign-compare",
+ "-Wno-unused-parameter",
],
}
@@ -63,6 +70,11 @@
},
export_include_dirs: ["aidl"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
shared_libs: [
"libbinder",
"libui",
@@ -92,6 +104,8 @@
],
cflags: [
"-DLOG_TAG=\"vr_hwc\"",
+ "-Wall",
+ "-Werror",
],
}
@@ -120,6 +134,8 @@
],
cflags: [
"-DLOG_TAG=\"vr_hwc\"",
+ "-Wall",
+ "-Werror",
],
init_rc: [
"vr_hwc.rc",
@@ -137,6 +153,13 @@
// symbols in the *-binder library get optimized out.
"libvr_hwc-binder",
],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ // warnings in vr_composer_test.cpp to be fixed after merge of goog/master
+ "-Wno-sign-compare",
+ "-Wno-unused-parameter",
+ ],
shared_libs: [
"libbase",
"libbinder",
diff --git a/services/vr/performanced/Android.mk b/services/vr/performanced/Android.mk
index dbc66f1..1470234 100644
--- a/services/vr/performanced/Android.mk
+++ b/services/vr/performanced/Android.mk
@@ -36,6 +36,7 @@
LOCAL_SRC_FILES := $(sourceFiles)
LOCAL_CFLAGS := -DLOG_TAG=\"performanced\"
LOCAL_CFLAGS += -DTRACE=0
+LOCAL_CFLAGS += -Wall -Werror
LOCAL_STATIC_LIBRARIES := $(staticLibraries)
LOCAL_SHARED_LIBRARIES := $(sharedLibraries)
LOCAL_MODULE := performanced
diff --git a/services/vr/performanced/directory_reader.h b/services/vr/performanced/directory_reader.h
index 7d7ecc5..b9d27c3 100644
--- a/services/vr/performanced/directory_reader.h
+++ b/services/vr/performanced/directory_reader.h
@@ -19,7 +19,7 @@
directory_ = fdopendir(directory_fd.get());
error_ = errno;
if (directory_ != nullptr)
- directory_fd.release();
+ (void) directory_fd.release(); // ignore return result?
}
~DirectoryReader() {
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 6b11ce3..7196b2b 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -23,7 +23,11 @@
shared_libs: shared_libs,
header_libs: header_libraries,
cppflags: ["-std=c++11"],
- cflags: ["-DLOG_TAG=\"VrVirtualTouchpad\""],
+ cflags: [
+ "-DLOG_TAG=\"VrVirtualTouchpad\"",
+ "-Wall",
+ "-Werror",
+ ],
name: "libvirtualtouchpad",
tags: ["optional"],
}
@@ -44,6 +48,10 @@
srcs: test_src_files,
static_libs: test_static_libs,
header_libs: header_libraries,
+ cflags = [
+ "-Wall",
+ "-Werror",
+ ],
cppflags = [
"-std=c++11",
],
@@ -83,6 +91,8 @@
cppflags: ["-std=c++11"],
cflags: [
"-DLOG_TAG=\"VrVirtualTouchpad\"",
+ "-Wall",
+ "-Werror",
],
host_ldlibs: ["-llog"],
name: "virtual_touchpad",
@@ -112,7 +122,11 @@
shared_libs: client_shared_libs,
header_libs: header_libraries,
cppflags: ["-std=c++11"],
- cflags: ["-DLOG_TAG=\"VirtualTouchpadClient\""],
+ cflags: [
+ "-DLOG_TAG=\"VirtualTouchpadClient\"",
+ "-Wall",
+ "-Werror",
+ ],
host_ldlibs: ["-llog"],
name: "libvirtualtouchpadclient",
tags: ["optional"],
diff --git a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
index b19b018..198ed06 100644
--- a/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
+++ b/services/vr/virtual_touchpad/tests/VirtualTouchpad_test.cpp
@@ -110,17 +110,6 @@
EvdevInjectorForTesting injector[kTouchpads];
};
-void DumpDifference(const char* expect, const char* actual) {
- printf(" common: ");
- while (*expect && *expect == *actual) {
- putchar(*expect);
- ++expect;
- ++actual;
- }
- printf("\n expect: %s\n", expect);
- printf(" actual: %s\n", actual);
-}
-
} // anonymous namespace
class VirtualTouchpadTest : public testing::Test {};
@@ -153,7 +142,6 @@
}
const int32_t width = 1 + uidev->absmax[ABS_MT_POSITION_X];
const int32_t height = 1 + uidev->absmax[ABS_MT_POSITION_Y];
- const int32_t slots = uidev->absmax[ABS_MT_SLOT];
for (int t = 0; t < touchpad->GetTouchpadCount(); ++t) {
SCOPED_TRACE(t);
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index dded1e3..ade0bde 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -94,7 +94,6 @@
~CreateInfoWrapper();
VkResult Validate();
- void DowngradeApiVersion();
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -132,8 +131,6 @@
VkDeviceCreateInfo dev_info_;
};
- VkApplicationInfo application_info_;
-
ExtensionFilter extension_filter_;
std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
@@ -540,15 +537,6 @@
}
}
-void CreateInfoWrapper::DowngradeApiVersion() {
- // If pApplicationInfo is NULL, apiVersion is assumed to be 1.0:
- if (instance_info_.pApplicationInfo) {
- application_info_ = *instance_info_.pApplicationInfo;
- instance_info_.pApplicationInfo = &application_info_;
- application_info_.apiVersion = VK_API_VERSION_1_0;
- }
-}
-
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
size_t alignment,
@@ -903,33 +891,6 @@
data->hook_extensions |= wrapper.GetHookExtensions();
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wold-style-cast"
- uint32_t api_version = ((pCreateInfo->pApplicationInfo)
- ? pCreateInfo->pApplicationInfo->apiVersion
- : VK_API_VERSION_1_0);
- uint32_t api_major_version = VK_VERSION_MAJOR(api_version);
- uint32_t api_minor_version = VK_VERSION_MINOR(api_version);
- uint32_t icd_api_version;
- PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version =
- reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
- Hal::Device().GetInstanceProcAddr(NULL,
- "vkEnumerateInstanceVersion"));
- if (!pfn_enumerate_instance_version) {
- icd_api_version = VK_API_VERSION_1_0;
- } else {
- result = (*pfn_enumerate_instance_version)(&icd_api_version);
- }
- uint32_t icd_api_major_version = VK_VERSION_MAJOR(icd_api_version);
- uint32_t icd_api_minor_version = VK_VERSION_MINOR(icd_api_version);
-
- if ((icd_api_major_version == 1) && (icd_api_minor_version == 0) &&
- ((api_major_version > 1) || (api_minor_version > 0))) {
- api_version = VK_API_VERSION_1_0;
- wrapper.DowngradeApiVersion();
- }
-#pragma clang diagnostic pop
-
// call into the driver
VkInstance instance;
result = Hal::Device().CreateInstance(