diff options
| -rw-r--r-- | libs/hwc2on1adapter/Android.bp | 76 | ||||
| -rw-r--r-- | libs/hwc2on1adapter/CleanSpec.mk | 52 | ||||
| -rw-r--r-- | libs/hwc2on1adapter/HWC2On1Adapter.cpp | 2637 | ||||
| -rw-r--r-- | libs/hwc2on1adapter/MiniFence.cpp | 42 | ||||
| -rw-r--r-- | libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h | 738 | ||||
| -rw-r--r-- | libs/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h | 59 | ||||
| -rw-r--r-- | libs/hwc2onfbadapter/Android.bp | 33 | ||||
| -rw-r--r-- | libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp | 887 | ||||
| -rw-r--r-- | libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h | 123 |
9 files changed, 0 insertions, 4647 deletions
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp deleted file mode 100644 index 420a1f6066..0000000000 --- a/libs/hwc2on1adapter/Android.bp +++ /dev/null @@ -1,76 +0,0 @@ -// 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: "libhwc2on1adapter", - vendor: true, - - clang: true, - cflags: [ - "-Wall", - "-Werror", - "-Wno-user-defined-warnings", - ], - cppflags: [ - "-Weverything", - "-Wunused", - "-Wunreachable-code", - - // The static constructors and destructors in this library have not been noted to - // introduce significant overheads - "-Wno-exit-time-destructors", - "-Wno-global-constructors", - - // We only care about compiling as C++14 - "-Wno-c++98-compat-pedantic", - - // android/sensors.h uses nested anonymous unions and anonymous structs - "-Wno-nested-anon-types", - "-Wno-gnu-anonymous-struct", - - // Don't warn about struct padding - "-Wno-padded", - - // hwcomposer2.h features switch covering all cases. - "-Wno-covered-switch-default", - - // hwcomposer.h features zero size array. - "-Wno-zero-length-array", - - // Disabling warning specific to hwc2on1adapter code - "-Wno-double-promotion", - "-Wno-sign-conversion", - "-Wno-switch-enum", - "-Wno-float-equal", - "-Wno-shorten-64-to-32", - "-Wno-sign-compare", - "-Wno-missing-prototypes", - ], - - srcs: [ - "HWC2On1Adapter.cpp", - "MiniFence.cpp", - ], - - shared_libs: [ - "libutils", - "libcutils", - "liblog", - "libhardware", - ], - - export_include_dirs: ["include"], - - export_shared_lib_headers: ["libutils"], -} diff --git a/libs/hwc2on1adapter/CleanSpec.mk b/libs/hwc2on1adapter/CleanSpec.mk deleted file mode 100644 index 7fc22161fa..0000000000 --- a/libs/hwc2on1adapter/CleanSpec.mk +++ /dev/null @@ -1,52 +0,0 @@ -# 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. -# - -# If you don't need to do a full clean build but would like to touch -# a file or delete some intermediate files, add a clean step to the end -# of the list. These steps will only be run once, if they haven't been -# run before. -# -# E.g.: -# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) -# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) -# -# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with -# files that are missing or have been moved. -# -# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. -# Use $(OUT_DIR) to refer to the "out" directory. -# -# If you need to re-do something that's already mentioned, just copy -# the command and add it to the bottom of the list. E.g., if a change -# that you made last week required touching a file and a change you -# made today requires touching the same file, just copy the old -# touch step and add it to the end of the list. -# -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ - -# For example: -#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) -#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) -#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) -#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) - -# ************************************************ -# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST -# ************************************************ -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so) -$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so) diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp deleted file mode 100644 index 77f06bbbe7..0000000000 --- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp +++ /dev/null @@ -1,2637 +0,0 @@ -/* - * Copyright 2015 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 "hwc2on1adapter/HWC2On1Adapter.h" - -//#define LOG_NDEBUG 0 - -#undef LOG_TAG -#define LOG_TAG "HWC2On1Adapter" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS - - -#include <inttypes.h> - -#include <chrono> -#include <cstdlib> -#include <sstream> - -#include <hardware/hwcomposer.h> -#include <log/log.h> -#include <utils/Trace.h> - -using namespace std::chrono_literals; - -static uint8_t getMinorVersion(struct hwc_composer_device_1* device) -{ - auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; - return (version >> 16) & 0xF; -} - -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); -} - -using namespace HWC2; - -static constexpr Attribute ColorMode = static_cast<Attribute>(6); - -namespace android { - -class HWC2On1Adapter::Callbacks : public hwc_procs_t { - public: - explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) { - invalidate = &invalidateHook; - vsync = &vsyncHook; - hotplug = &hotplugHook; - } - - static void invalidateHook(const hwc_procs_t* procs) { - auto callbacks = static_cast<const Callbacks*>(procs); - callbacks->mAdapter.hwc1Invalidate(); - } - - static void vsyncHook(const hwc_procs_t* procs, int display, - int64_t timestamp) { - auto callbacks = static_cast<const Callbacks*>(procs); - callbacks->mAdapter.hwc1Vsync(display, timestamp); - } - - static void hotplugHook(const hwc_procs_t* procs, int display, - int connected) { - auto callbacks = static_cast<const Callbacks*>(procs); - callbacks->mAdapter.hwc1Hotplug(display, connected); - } - - private: - HWC2On1Adapter& mAdapter; -}; - -static int closeHook(hw_device_t* /*device*/) -{ - // Do nothing, since the real work is done in the class destructor, but we - // need to provide a valid function pointer for hwc2_close to call - return 0; -} - -HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device) - : mDumpString(), - mHwc1Device(hwc1Device), - mHwc1MinorVersion(getMinorVersion(hwc1Device)), - mHwc1SupportsVirtualDisplays(false), - mHwc1SupportsBackgroundColor(false), - mHwc1Callbacks(std::make_unique<Callbacks>(*this)), - mCapabilities(), - mLayers(), - mHwc1VirtualDisplay(), - mStateMutex(), - mCallbacks(), - mHasPendingInvalidate(false), - mPendingVsyncs(), - mPendingHotplugs(), - mDisplays(), - mHwc1DisplayMap() -{ - common.close = closeHook; - getCapabilities = getCapabilitiesHook; - getFunction = getFunctionHook; - populateCapabilities(); - populatePrimary(); - mHwc1Device->registerProcs(mHwc1Device, - static_cast<const hwc_procs_t*>(mHwc1Callbacks.get())); -} - -HWC2On1Adapter::~HWC2On1Adapter() { - hwc_close_1(mHwc1Device); -} - -void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount, - int32_t* outCapabilities) { - if (outCapabilities == nullptr) { - *outCount = mCapabilities.size(); - return; - } - - auto capabilityIter = mCapabilities.cbegin(); - for (size_t written = 0; written < *outCount; ++written) { - if (capabilityIter == mCapabilities.cend()) { - return; - } - outCapabilities[written] = static_cast<int32_t>(*capabilityIter); - ++capabilityIter; - } -} - -hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( - FunctionDescriptor descriptor) { - switch (descriptor) { - // Device functions - case FunctionDescriptor::CreateVirtualDisplay: - return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>( - createVirtualDisplayHook); - case FunctionDescriptor::DestroyVirtualDisplay: - return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>( - destroyVirtualDisplayHook); - case FunctionDescriptor::Dump: - return asFP<HWC2_PFN_DUMP>(dumpHook); - case FunctionDescriptor::GetMaxVirtualDisplayCount: - return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>( - getMaxVirtualDisplayCountHook); - case FunctionDescriptor::RegisterCallback: - return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook); - - // Display functions - case FunctionDescriptor::AcceptDisplayChanges: - return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>( - displayHook<decltype(&Display::acceptChanges), - &Display::acceptChanges>); - case FunctionDescriptor::CreateLayer: - return asFP<HWC2_PFN_CREATE_LAYER>( - displayHook<decltype(&Display::createLayer), - &Display::createLayer, hwc2_layer_t*>); - case FunctionDescriptor::DestroyLayer: - return asFP<HWC2_PFN_DESTROY_LAYER>( - displayHook<decltype(&Display::destroyLayer), - &Display::destroyLayer, hwc2_layer_t>); - case FunctionDescriptor::GetActiveConfig: - return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>( - displayHook<decltype(&Display::getActiveConfig), - &Display::getActiveConfig, hwc2_config_t*>); - case FunctionDescriptor::GetChangedCompositionTypes: - return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>( - displayHook<decltype(&Display::getChangedCompositionTypes), - &Display::getChangedCompositionTypes, uint32_t*, - hwc2_layer_t*, int32_t*>); - case FunctionDescriptor::GetColorModes: - return asFP<HWC2_PFN_GET_COLOR_MODES>( - displayHook<decltype(&Display::getColorModes), - &Display::getColorModes, uint32_t*, int32_t*>); - case FunctionDescriptor::GetDisplayAttribute: - return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>( - getDisplayAttributeHook); - case FunctionDescriptor::GetDisplayConfigs: - return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>( - displayHook<decltype(&Display::getConfigs), - &Display::getConfigs, uint32_t*, hwc2_config_t*>); - case FunctionDescriptor::GetDisplayName: - return asFP<HWC2_PFN_GET_DISPLAY_NAME>( - displayHook<decltype(&Display::getName), - &Display::getName, uint32_t*, char*>); - case FunctionDescriptor::GetDisplayRequests: - return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>( - displayHook<decltype(&Display::getRequests), - &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*, - int32_t*>); - case FunctionDescriptor::GetDisplayType: - return asFP<HWC2_PFN_GET_DISPLAY_TYPE>( - displayHook<decltype(&Display::getType), - &Display::getType, int32_t*>); - case FunctionDescriptor::GetDozeSupport: - return asFP<HWC2_PFN_GET_DOZE_SUPPORT>( - displayHook<decltype(&Display::getDozeSupport), - &Display::getDozeSupport, int32_t*>); - case FunctionDescriptor::GetHdrCapabilities: - return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>( - displayHook<decltype(&Display::getHdrCapabilities), - &Display::getHdrCapabilities, uint32_t*, int32_t*, float*, - float*, float*>); - case FunctionDescriptor::GetReleaseFences: - return asFP<HWC2_PFN_GET_RELEASE_FENCES>( - displayHook<decltype(&Display::getReleaseFences), - &Display::getReleaseFences, uint32_t*, hwc2_layer_t*, - int32_t*>); - case FunctionDescriptor::PresentDisplay: - return asFP<HWC2_PFN_PRESENT_DISPLAY>( - displayHook<decltype(&Display::present), - &Display::present, int32_t*>); - case FunctionDescriptor::SetActiveConfig: - return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>( - displayHook<decltype(&Display::setActiveConfig), - &Display::setActiveConfig, hwc2_config_t>); - case FunctionDescriptor::SetClientTarget: - return asFP<HWC2_PFN_SET_CLIENT_TARGET>( - displayHook<decltype(&Display::setClientTarget), - &Display::setClientTarget, buffer_handle_t, int32_t, - int32_t, hwc_region_t>); - case FunctionDescriptor::SetColorMode: - return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook); - case FunctionDescriptor::SetColorTransform: - return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook); - case FunctionDescriptor::SetOutputBuffer: - return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>( - displayHook<decltype(&Display::setOutputBuffer), - &Display::setOutputBuffer, buffer_handle_t, int32_t>); - case FunctionDescriptor::SetPowerMode: - return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook); - case FunctionDescriptor::SetVsyncEnabled: - return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook); - case FunctionDescriptor::ValidateDisplay: - return asFP<HWC2_PFN_VALIDATE_DISPLAY>( - displayHook<decltype(&Display::validate), - &Display::validate, uint32_t*, uint32_t*>); - case FunctionDescriptor::GetClientTargetSupport: - return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>( - displayHook<decltype(&Display::getClientTargetSupport), - &Display::getClientTargetSupport, uint32_t, uint32_t, - int32_t, int32_t>); - - // Layer functions - case FunctionDescriptor::SetCursorPosition: - return asFP<HWC2_PFN_SET_CURSOR_POSITION>( - layerHook<decltype(&Layer::setCursorPosition), - &Layer::setCursorPosition, int32_t, int32_t>); - case FunctionDescriptor::SetLayerBuffer: - return asFP<HWC2_PFN_SET_LAYER_BUFFER>( - layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer, - buffer_handle_t, int32_t>); - case FunctionDescriptor::SetLayerSurfaceDamage: - return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>( - layerHook<decltype(&Layer::setSurfaceDamage), - &Layer::setSurfaceDamage, hwc_region_t>); - - // Layer state functions - case FunctionDescriptor::SetLayerBlendMode: - return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>( - setLayerBlendModeHook); - case FunctionDescriptor::SetLayerColor: - return asFP<HWC2_PFN_SET_LAYER_COLOR>( - layerHook<decltype(&Layer::setColor), &Layer::setColor, - hwc_color_t>); - case FunctionDescriptor::SetLayerCompositionType: - return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>( - setLayerCompositionTypeHook); - case FunctionDescriptor::SetLayerDataspace: - return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook); - case FunctionDescriptor::SetLayerDisplayFrame: - return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>( - layerHook<decltype(&Layer::setDisplayFrame), - &Layer::setDisplayFrame, hwc_rect_t>); - case FunctionDescriptor::SetLayerPlaneAlpha: - return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>( - layerHook<decltype(&Layer::setPlaneAlpha), - &Layer::setPlaneAlpha, float>); - case FunctionDescriptor::SetLayerSidebandStream: - return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>( - layerHook<decltype(&Layer::setSidebandStream), - &Layer::setSidebandStream, const native_handle_t*>); - case FunctionDescriptor::SetLayerSourceCrop: - return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>( - layerHook<decltype(&Layer::setSourceCrop), - &Layer::setSourceCrop, hwc_frect_t>); - case FunctionDescriptor::SetLayerTransform: - return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook); - case FunctionDescriptor::SetLayerVisibleRegion: - return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>( - layerHook<decltype(&Layer::setVisibleRegion), - &Layer::setVisibleRegion, hwc_region_t>); - case FunctionDescriptor::SetLayerZOrder: - return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook); - - default: - ALOGE("doGetFunction: Unknown function descriptor: %d (%s)", - static_cast<int32_t>(descriptor), - to_string(descriptor).c_str()); - return nullptr; - } -} - -// Device functions - -Error HWC2On1Adapter::createVirtualDisplay(uint32_t width, - uint32_t height, hwc2_display_t* outDisplay) { - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - if (mHwc1VirtualDisplay) { - // We have already allocated our only HWC1 virtual display - ALOGE("createVirtualDisplay: HWC1 virtual display already allocated"); - return Error::NoResources; - } - - mHwc1VirtualDisplay = std::make_shared<HWC2On1Adapter::Display>(*this, - HWC2::DisplayType::Virtual); - mHwc1VirtualDisplay->populateConfigs(width, height); - const auto displayId = mHwc1VirtualDisplay->getId(); - mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId; - mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL); - mDisplays.emplace(displayId, mHwc1VirtualDisplay); - *outDisplay = displayId; - - return Error::None; -} - -Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) { - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) { - return Error::BadDisplay; - } - - mHwc1VirtualDisplay.reset(); - mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL); - mDisplays.erase(displayId); - - return Error::None; -} - -void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) { - if (outBuffer != nullptr) { - auto copiedBytes = mDumpString.copy(outBuffer, *outSize); - *outSize = static_cast<uint32_t>(copiedBytes); - return; - } - - std::stringstream output; - - output << "-- HWC2On1Adapter --\n"; - - output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) << - " device\n"; - - // Attempt to acquire the lock for 1 second, but proceed without the lock - // after that, so we can still get some information if we're deadlocked - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex, - std::defer_lock); - lock.try_lock_for(1s); - - if (mCapabilities.empty()) { - output << "Capabilities: None\n"; - } else { - output << "Capabilities:\n"; - for (auto capability : mCapabilities) { - output << " " << to_string(capability) << '\n'; - } - } - - output << "Displays:\n"; - for (const auto& element : mDisplays) { - const auto& display = element.second; - output << display->dump(); - } - output << '\n'; - - // Release the lock before calling into HWC1, and since we no longer require - // mutual exclusion to access mCapabilities or mDisplays - lock.unlock(); - - if (mHwc1Device->dump) { - output << "HWC1 dump:\n"; - std::vector<char> hwc1Dump(4096); - // Call with size - 1 to preserve a null character at the end - mHwc1Device->dump(mHwc1Device, hwc1Dump.data(), - static_cast<int>(hwc1Dump.size() - 1)); - output << hwc1Dump.data(); - } - - mDumpString = output.str(); - *outSize = static_cast<uint32_t>(mDumpString.size()); -} - -uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() { - return mHwc1SupportsVirtualDisplays ? 1 : 0; -} - -static bool isValid(Callback descriptor) { - switch (descriptor) { - case Callback::Hotplug: // Fall-through - case Callback::Refresh: // Fall-through - case Callback::Vsync: return true; - default: return false; - } -} - -Error HWC2On1Adapter::registerCallback(Callback descriptor, - hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { - if (!isValid(descriptor)) { - return Error::BadParameter; - } - - ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(), - callbackData, pointer); - - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - if (pointer != nullptr) { - mCallbacks[descriptor] = {callbackData, pointer}; - } else { - ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str()); - mCallbacks.erase(descriptor); - return Error::None; - } - - bool hasPendingInvalidate = false; - std::vector<hwc2_display_t> displayIds; - std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs; - std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs; - - if (descriptor == Callback::Refresh) { - hasPendingInvalidate = mHasPendingInvalidate; - if (hasPendingInvalidate) { - for (auto& displayPair : mDisplays) { - displayIds.emplace_back(displayPair.first); - } - } - mHasPendingInvalidate = false; - } else if (descriptor == Callback::Vsync) { - for (auto pending : mPendingVsyncs) { - auto hwc1DisplayId = pending.first; - if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { - ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", - hwc1DisplayId); - continue; - } - auto displayId = mHwc1DisplayMap[hwc1DisplayId]; - auto timestamp = pending.second; - pendingVsyncs.emplace_back(displayId, timestamp); - } - mPendingVsyncs.clear(); - } else if (descriptor == Callback::Hotplug) { - // Hotplug the primary display - pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY], - static_cast<int32_t>(Connection::Connected)); - - for (auto pending : mPendingHotplugs) { - auto hwc1DisplayId = pending.first; - if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { - ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d", - hwc1DisplayId); - continue; - } - auto displayId = mHwc1DisplayMap[hwc1DisplayId]; - auto connected = pending.second; - pendingHotplugs.emplace_back(displayId, connected); - } - } - - // Call pending callbacks without the state lock held - lock.unlock(); - - if (hasPendingInvalidate) { - auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer); - for (auto displayId : displayIds) { - refresh(callbackData, displayId); - } - } - if (!pendingVsyncs.empty()) { - auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer); - for (auto& pendingVsync : pendingVsyncs) { - vsync(callbackData, pendingVsync.first, pendingVsync.second); - } - } - if (!pendingHotplugs.empty()) { - auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer); - for (auto& pendingHotplug : pendingHotplugs) { - hotplug(callbackData, pendingHotplug.first, pendingHotplug.second); - } - } - return Error::None; -} - -// Display functions - -std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1); - -HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type) - : mId(sNextId++), - mDevice(device), - mStateMutex(), - mHwc1RequestedContents(nullptr), - mRetireFence(), - mChanges(), - mHwc1Id(-1), - mConfigs(), - mActiveConfig(nullptr), - mActiveColorMode(static_cast<android_color_mode_t>(-1)), - mName(), - mType(type), - mPowerMode(PowerMode::Off), - mVsyncEnabled(Vsync::Invalid), - mClientTarget(), - mOutputBuffer(), - mHasColorTransform(false), - mLayers(), - mHwc1LayerMap(), - mNumAvailableRects(0), - mNextAvailableRect(nullptr), - mGeometryChanged(false) - {} - -Error HWC2On1Adapter::Display::acceptChanges() { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!mChanges) { - ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId); - return Error::NotValidated; - } - - ALOGV("[%" PRIu64 "] acceptChanges", mId); - - for (auto& change : mChanges->getTypeChanges()) { - auto layerId = change.first; - auto type = change.second; - if (mDevice.mLayers.count(layerId) == 0) { - // This should never happen but somehow does. - ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")", - layerId); - continue; - } - auto layer = mDevice.mLayers[layerId]; - layer->setCompositionType(type); - } - - mChanges->clearTypeChanges(); - - return Error::None; -} - -Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - auto layer = *mLayers.emplace(std::make_shared<Layer>(*this)); - mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer)); - *outLayerId = layer->getId(); - ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId); - markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - const auto mapLayer = mDevice.mLayers.find(layerId); - if (mapLayer == mDevice.mLayers.end()) { - ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", - mId, layerId); - return Error::BadLayer; - } - const auto layer = mapLayer->second; - mDevice.mLayers.erase(mapLayer); - const auto zRange = mLayers.equal_range(layer); - for (auto current = zRange.first; current != zRange.second; ++current) { - if (**current == *layer) { - current = mLayers.erase(current); - break; - } - } - ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId); - markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!mActiveConfig) { - ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId, - to_string(Error::BadConfig).c_str()); - return Error::BadConfig; - } - auto configId = mActiveConfig->getId(); - ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId); - *outConfig = configId; - return Error::None; -} - -Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId, - Attribute attribute, int32_t* outValue) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { - ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId, - configId); - return Error::BadConfig; - } - *outValue = mConfigs[configId]->getAttribute(attribute); - ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId, - to_string(attribute).c_str(), *outValue); - return Error::None; -} - -Error HWC2On1Adapter::Display::getChangedCompositionTypes( - uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!mChanges) { - ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated", - mId); - return Error::NotValidated; - } - - if ((outLayers == nullptr) || (outTypes == nullptr)) { - *outNumElements = mChanges->getTypeChanges().size(); - return Error::None; - } - - uint32_t numWritten = 0; - for (const auto& element : mChanges->getTypeChanges()) { - if (numWritten == *outNumElements) { - break; - } - auto layerId = element.first; - auto intType = static_cast<int32_t>(element.second); - ALOGV("Adding %" PRIu64 " %s", layerId, - to_string(element.second).c_str()); - outLayers[numWritten] = layerId; - outTypes[numWritten] = intType; - ++numWritten; - } - *outNumElements = numWritten; - - return Error::None; -} - -Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, - int32_t* outModes) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!outModes) { - *outNumModes = mColorModes.size(); - return Error::None; - } - uint32_t numModes = std::min(*outNumModes, - static_cast<uint32_t>(mColorModes.size())); - std::copy_n(mColorModes.cbegin(), numModes, outModes); - *outNumModes = numModes; - return Error::None; -} - -Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, - hwc2_config_t* outConfigs) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!outConfigs) { - *outNumConfigs = mConfigs.size(); - return Error::None; - } - uint32_t numWritten = 0; - for (const auto& config : mConfigs) { - if (numWritten == *outNumConfigs) { - break; - } - outConfigs[numWritten] = config->getId(); - ++numWritten; - } - *outNumConfigs = numWritten; - return Error::None; -} - -Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) { - *outSupport = 0; - } else { - *outSupport = 1; - } - return Error::None; -} - -Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes, - int32_t* /*outTypes*/, float* /*outMaxLuminance*/, - float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) { - // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0 - *outNumTypes = 0; - return Error::None; -} - -Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!outName) { - *outSize = mName.size(); - return Error::None; - } - auto numCopied = mName.copy(outName, *outSize); - *outSize = numCopied; - return Error::None; -} - -Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements, - hwc2_layer_t* outLayers, int32_t* outFences) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - uint32_t numWritten = 0; - bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr); - for (const auto& layer : mLayers) { - if (outputsNonNull && (numWritten == *outNumElements)) { - break; - } - - auto releaseFence = layer->getReleaseFence(); - if (releaseFence != MiniFence::NO_FENCE) { - if (outputsNonNull) { - outLayers[numWritten] = layer->getId(); - outFences[numWritten] = releaseFence->dup(); - } - ++numWritten; - } - } - *outNumElements = numWritten; - - return Error::None; -} - -Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests, - uint32_t* outNumElements, hwc2_layer_t* outLayers, - int32_t* outLayerRequests) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!mChanges) { - return Error::NotValidated; - } - - if (outLayers == nullptr || outLayerRequests == nullptr) { - *outNumElements = mChanges->getNumLayerRequests(); - return Error::None; - } - - // Display requests (HWC2::DisplayRequest) are not supported by hwc1: - // A hwc1 has always zero requests for the client. - *outDisplayRequests = 0; - - uint32_t numWritten = 0; - for (const auto& request : mChanges->getLayerRequests()) { - if (numWritten == *outNumElements) { - break; - } - outLayers[numWritten] = request.first; - outLayerRequests[numWritten] = static_cast<int32_t>(request.second); - ++numWritten; - } - - return Error::None; -} - -Error HWC2On1Adapter::Display::getType(int32_t* outType) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - *outType = static_cast<int32_t>(mType); - return Error::None; -} - -Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (mChanges) { - Error error = mDevice.setAllDisplays(); - if (error != Error::None) { - ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId, - to_string(error).c_str()); - return error; - } - } - - *outRetireFence = mRetireFence.get()->dup(); - ALOGV("[%" PRIu64 "] present returning retire fence %d", mId, - *outRetireFence); - - return Error::None; -} - -Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - auto config = getConfig(configId); - if (!config) { - return Error::BadConfig; - } - if (config == mActiveConfig) { - return Error::None; - } - - if (mDevice.mHwc1MinorVersion >= 4) { - uint32_t hwc1Id = 0; - auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id); - if (error != Error::None) { - return error; - } - - int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, - mHwc1Id, static_cast<int>(hwc1Id)); - if (intError != 0) { - ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)", - intError); - return Error::BadConfig; - } - mActiveConfig = config; - } - - return Error::None; -} - -Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, - int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence); - mClientTarget.setBuffer(target); - mClientTarget.setFence(acquireFence); - // dataspace and damage can't be used by HWC1, so ignore them - return Error::None; -} - -Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) { - std::unique_lock<std::recursive_mutex> lock (mStateMutex); - - ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode); - - if (mode == mActiveColorMode) { - return Error::None; - } - if (mColorModes.count(mode) == 0) { - ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode); - return Error::Unsupported; - } - - uint32_t hwc1Config = 0; - auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config); - if (error != Error::None) { - return error; - } - - ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config); - int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, - mHwc1Id, hwc1Config); - if (intError != 0) { - ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError); - return Error::Unsupported; - } - - mActiveColorMode = mode; - return Error::None; -} - -Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - ALOGV("%" PRIu64 "] setColorTransform(%d)", mId, - static_cast<int32_t>(hint)); - mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY); - return Error::None; -} - -Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer, - int32_t releaseFence) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence); - mOutputBuffer.setBuffer(buffer); - mOutputBuffer.setFence(releaseFence); - return Error::None; -} - -static bool isValid(PowerMode mode) { - switch (mode) { - case PowerMode::Off: // Fall-through - case PowerMode::DozeSuspend: // Fall-through - case PowerMode::Doze: // Fall-through - case PowerMode::On: return true; - } -} - -static int getHwc1PowerMode(PowerMode mode) { - switch (mode) { - case PowerMode::Off: return HWC_POWER_MODE_OFF; - case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND; - case PowerMode::Doze: return HWC_POWER_MODE_DOZE; - case PowerMode::On: return HWC_POWER_MODE_NORMAL; - } -} - -Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) { - if (!isValid(mode)) { - return Error::BadParameter; - } - if (mode == mPowerMode) { - return Error::None; - } - - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - int error = 0; - if (mDevice.mHwc1MinorVersion < 4) { - error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id, - mode == PowerMode::Off); - } else { - error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device, - mHwc1Id, getHwc1PowerMode(mode)); - } - ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)", - error); - - ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str()); - mPowerMode = mode; - return Error::None; -} - -static bool isValid(Vsync enable) { - switch (enable) { - case Vsync::Enable: // Fall-through - case Vsync::Disable: return true; - case Vsync::Invalid: return false; - } -} - -Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) { - if (!isValid(enable)) { - return Error::BadParameter; - } - if (enable == mVsyncEnabled) { - return Error::None; - } - - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device, - mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable); - ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)", - error); - - mVsyncEnabled = enable; - return Error::None; -} - -Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes, - uint32_t* outNumRequests) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!mChanges) { - if (!mDevice.prepareAllDisplays()) { - return Error::BadDisplay; - } - } else { - ALOGE("Validate was called more than once!"); - } - - *outNumTypes = mChanges->getNumTypes(); - *outNumRequests = mChanges->getNumLayerRequests(); - ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes, - *outNumRequests); - for (auto request : mChanges->getTypeChanges()) { - ALOGV("Layer %" PRIu64 " --> %s", request.first, - to_string(request.second).c_str()); - } - return *outNumTypes > 0 ? Error::HasChanges : Error::None; -} - -Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - const auto mapLayer = mDevice.mLayers.find(layerId); - if (mapLayer == mDevice.mLayers.end()) { - ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId); - return Error::BadLayer; - } - - const auto layer = mapLayer->second; - const auto zRange = mLayers.equal_range(layer); - bool layerOnDisplay = false; - for (auto current = zRange.first; current != zRange.second; ++current) { - if (**current == *layer) { - if ((*current)->getZ() == z) { - // Don't change anything if the Z hasn't changed - return Error::None; - } - current = mLayers.erase(current); - layerOnDisplay = true; - break; - } - } - - if (!layerOnDisplay) { - ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", - mId); - return Error::BadLayer; - } - - layer->setZ(z); - mLayers.emplace(std::move(layer)); - markGeometryChanged(); - - return Error::None; -} - -Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height, - int32_t format, int32_t dataspace){ - if (mActiveConfig == nullptr) { - return Error::Unsupported; - } - - if (width == mActiveConfig->getAttribute(Attribute::Width) && - height == mActiveConfig->getAttribute(Attribute::Height) && - format == HAL_PIXEL_FORMAT_RGBA_8888 && - dataspace == HAL_DATASPACE_UNKNOWN) { - return Error::None; - } - - return Error::Unsupported; -} - -static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = { - HWC_DISPLAY_VSYNC_PERIOD, - HWC_DISPLAY_WIDTH, - HWC_DISPLAY_HEIGHT, - HWC_DISPLAY_DPI_X, - HWC_DISPLAY_DPI_Y, - HWC_DISPLAY_COLOR_TRANSFORM, - HWC_DISPLAY_NO_ATTRIBUTE, -}; - -static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = { - HWC_DISPLAY_VSYNC_PERIOD, - HWC_DISPLAY_WIDTH, - HWC_DISPLAY_HEIGHT, - HWC_DISPLAY_DPI_X, - HWC_DISPLAY_DPI_Y, - HWC_DISPLAY_NO_ATTRIBUTE, -}; - -static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR = - sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t); -static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR), - "Attribute tables have unexpected sizes"); - -static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = { - 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0 - 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, - 1, // HWC_DISPLAY_WIDTH = 2, - 2, // HWC_DISPLAY_HEIGHT = 3, - 3, // HWC_DISPLAY_DPI_X = 4, - 4, // HWC_DISPLAY_DPI_Y = 5, - 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6, -}; - -static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = { - 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0 - 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, - 1, // HWC_DISPLAY_WIDTH = 2, - 2, // HWC_DISPLAY_HEIGHT = 3, - 3, // HWC_DISPLAY_DPI_X = 4, - 4, // HWC_DISPLAY_DPI_Y = 5, -}; - -template <uint32_t attribute> -static constexpr bool attributesMatch() -{ - bool match = (attribute == - ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]); - if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) { - return match; - } - - return match && (attribute == - ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]); -} -static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(), - "Tables out of sync"); -static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync"); -static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync"); -static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync"); -static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync"); -static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(), - "Tables out of sync"); - -void HWC2On1Adapter::Display::populateConfigs() { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - ALOGV("[%" PRIu64 "] populateConfigs", mId); - - if (mHwc1Id == -1) { - ALOGE("populateConfigs: HWC1 ID not set"); - return; - } - - const size_t MAX_NUM_CONFIGS = 128; - uint32_t configs[MAX_NUM_CONFIGS] = {}; - size_t numConfigs = MAX_NUM_CONFIGS; - mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id, - configs, &numConfigs); - - for (size_t c = 0; c < numConfigs; ++c) { - uint32_t hwc1ConfigId = configs[c]; - auto newConfig = std::make_shared<Config>(*this); - - int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {}; - bool hasColor = true; - auto result = mDevice.mHwc1Device->getDisplayAttributes( - mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, - ATTRIBUTES_WITH_COLOR, values); - if (result != 0) { - mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, - mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values); - hasColor = false; - } - - auto attributeMap = hasColor ? - ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR; - - newConfig->setAttribute(Attribute::VsyncPeriod, - values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]); - newConfig->setAttribute(Attribute::Width, - values[attributeMap[HWC_DISPLAY_WIDTH]]); - newConfig->setAttribute(Attribute::Height, - values[attributeMap[HWC_DISPLAY_HEIGHT]]); - newConfig->setAttribute(Attribute::DpiX, - values[attributeMap[HWC_DISPLAY_DPI_X]]); - newConfig->setAttribute(Attribute::DpiY, - values[attributeMap[HWC_DISPLAY_DPI_Y]]); - if (hasColor) { - // In HWC1, color modes are referred to as color transforms. To avoid confusion with - // the HWC2 concept of color transforms, we internally refer to them as color modes for - // both HWC1 and 2. - newConfig->setAttribute(ColorMode, - values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]); - } - - // We can only do this after attempting to read the color mode - newConfig->setHwc1Id(hwc1ConfigId); - - for (auto& existingConfig : mConfigs) { - if (existingConfig->merge(*newConfig)) { - ALOGV("Merged config %d with existing config %u: %s", - hwc1ConfigId, existingConfig->getId(), - existingConfig->toString().c_str()); - newConfig.reset(); - break; - } - } - - // If it wasn't merged with any existing config, add it to the end - if (newConfig) { - newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size())); - ALOGV("Found new config %u: %s", newConfig->getId(), - newConfig->toString().c_str()); - mConfigs.emplace_back(std::move(newConfig)); - } - } - - initializeActiveConfig(); - populateColorModes(); -} - -void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - mConfigs.emplace_back(std::make_shared<Config>(*this)); - auto& config = mConfigs[0]; - - config->setAttribute(Attribute::Width, static_cast<int32_t>(width)); - config->setAttribute(Attribute::Height, static_cast<int32_t>(height)); - config->setHwc1Id(0); - config->setId(0); - mActiveConfig = config; -} - -bool HWC2On1Adapter::Display::prepare() { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - // Only prepare display contents for displays HWC1 knows about - if (mHwc1Id == -1) { - return true; - } - - // It doesn't make sense to prepare a display for which there is no active - // config, so return early - if (!mActiveConfig) { - ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId); - return false; - } - - allocateRequestedContents(); - assignHwc1LayerIds(); - - mHwc1RequestedContents->retireFenceFd = -1; - mHwc1RequestedContents->flags = 0; - if (mGeometryChanged) { - mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED; - } - mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer(); - mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence(); - - // +1 is for framebuffer target layer. - mHwc1RequestedContents->numHwLayers = mLayers.size() + 1; - for (auto& layer : mLayers) { - auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()]; - hwc1Layer.releaseFenceFd = -1; - hwc1Layer.acquireFenceFd = -1; - ALOGV("Applying states for layer %" PRIu64 " ", layer->getId()); - layer->applyState(hwc1Layer); - } - - prepareFramebufferTarget(); - - resetGeometryMarker(); - - return true; -} - -void HWC2On1Adapter::Display::generateChanges() { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - mChanges.reset(new Changes); - - size_t numLayers = mHwc1RequestedContents->numHwLayers; - for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { - const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id]; - if (mHwc1LayerMap.count(hwc1Id) == 0) { - ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET, - "generateChanges: HWC1 layer %zd doesn't have a" - " matching HWC2 layer, and isn't the framebuffer target", - hwc1Id); - continue; - } - - Layer& layer = *mHwc1LayerMap[hwc1Id]; - updateTypeChanges(receivedLayer, layer); - updateLayerRequests(receivedLayer, layer); - } -} - -bool HWC2On1Adapter::Display::hasChanges() const { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - return mChanges != nullptr; -} - -Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - if (!mChanges || (mChanges->getNumTypes() > 0)) { - ALOGE("[%" PRIu64 "] set failed: not validated", mId); - return Error::NotValidated; - } - - // Set up the client/framebuffer target - auto numLayers = hwcContents.numHwLayers; - - // Close acquire fences on FRAMEBUFFER layers, since they will not be used - // by HWC - for (size_t l = 0; l < numLayers - 1; ++l) { - auto& layer = hwcContents.hwLayers[l]; - if (layer.compositionType == HWC_FRAMEBUFFER) { - ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l); - close(layer.acquireFenceFd); - layer.acquireFenceFd = -1; - } - } - - auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1]; - if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) { - clientTargetLayer.handle = mClientTarget.getBuffer(); - clientTargetLayer.acquireFenceFd = mClientTarget.getFence(); - } else { - ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET", - mId); - } - - mChanges.reset(); - - return Error::None; -} - -void HWC2On1Adapter::Display::addRetireFence(int fenceFd) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - mRetireFence.add(fenceFd); -} - -void HWC2On1Adapter::Display::addReleaseFences( - const hwc_display_contents_1_t& hwcContents) { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - size_t numLayers = hwcContents.numHwLayers; - for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { - const auto& receivedLayer = hwcContents.hwLayers[hwc1Id]; - if (mHwc1LayerMap.count(hwc1Id) == 0) { - if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) { - ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a" - " matching HWC2 layer, and isn't the framebuffer" - " target", hwc1Id); - } - // Close the framebuffer target release fence since we will use the - // display retire fence instead - if (receivedLayer.releaseFenceFd != -1) { - close(receivedLayer.releaseFenceFd); - } - continue; - } - - Layer& layer = *mHwc1LayerMap[hwc1Id]; - ALOGV("Adding release fence %d to layer %" PRIu64, - receivedLayer.releaseFenceFd, layer.getId()); - layer.addReleaseFence(receivedLayer.releaseFenceFd); - } -} - -bool HWC2On1Adapter::Display::hasColorTransform() const { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - return mHasColorTransform; -} - -static std::string hwc1CompositionString(int32_t type) { - switch (type) { - case HWC_FRAMEBUFFER: return "Framebuffer"; - case HWC_OVERLAY: return "Overlay"; - case HWC_BACKGROUND: return "Background"; - case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget"; - case HWC_SIDEBAND: return "Sideband"; - case HWC_CURSOR_OVERLAY: return "CursorOverlay"; - default: - return std::string("Unknown (") + std::to_string(type) + ")"; - } -} - -static std::string hwc1TransformString(int32_t transform) { - switch (transform) { - case 0: return "None"; - case HWC_TRANSFORM_FLIP_H: return "FlipH"; - case HWC_TRANSFORM_FLIP_V: return "FlipV"; - case HWC_TRANSFORM_ROT_90: return "Rotate90"; - case HWC_TRANSFORM_ROT_180: return "Rotate180"; - case HWC_TRANSFORM_ROT_270: return "Rotate270"; - case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90"; - case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90"; - default: - return std::string("Unknown (") + std::to_string(transform) + ")"; - } -} - -static std::string hwc1BlendModeString(int32_t mode) { - switch (mode) { - case HWC_BLENDING_NONE: return "None"; - case HWC_BLENDING_PREMULT: return "Premultiplied"; - case HWC_BLENDING_COVERAGE: return "Coverage"; - default: - return std::string("Unknown (") + std::to_string(mode) + ")"; - } -} - -static std::string rectString(hwc_rect_t rect) { - std::stringstream output; - output << "[" << rect.left << ", " << rect.top << ", "; - output << rect.right << ", " << rect.bottom << "]"; - return output.str(); -} - -static std::string approximateFloatString(float f) { - if (static_cast<int32_t>(f) == f) { - return std::to_string(static_cast<int32_t>(f)); - } - int32_t truncated = static_cast<int32_t>(f * 10); - bool approximate = (static_cast<float>(truncated) != f * 10); - const size_t BUFFER_SIZE = 32; - char buffer[BUFFER_SIZE] = {}; - auto bytesWritten = snprintf(buffer, BUFFER_SIZE, - "%s%.1f", approximate ? "~" : "", f); - return std::string(buffer, bytesWritten); -} - -static std::string frectString(hwc_frect_t frect) { - std::stringstream output; - output << "[" << approximateFloatString(frect.left) << ", "; - output << approximateFloatString(frect.top) << ", "; - output << approximateFloatString(frect.right) << ", "; - output << approximateFloatString(frect.bottom) << "]"; - return output.str(); -} - -static std::string colorString(hwc_color_t color) { - std::stringstream output; - output << "RGBA ["; - output << static_cast<int32_t>(color.r) << ", "; - output << static_cast<int32_t>(color.g) << ", "; - output << static_cast<int32_t>(color.b) << ", "; - output << static_cast<int32_t>(color.a) << "]"; - return output.str(); -} - -static std::string alphaString(float f) { - const size_t BUFFER_SIZE = 8; - char buffer[BUFFER_SIZE] = {}; - auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f); - return std::string(buffer, bytesWritten); -} - -static std::string to_string(const hwc_layer_1_t& hwcLayer, - int32_t hwc1MinorVersion) { - const char* fill = " "; - - std::stringstream output; - - output << " Composition: " << - hwc1CompositionString(hwcLayer.compositionType); - - if (hwcLayer.compositionType == HWC_BACKGROUND) { - output << " Color: " << colorString(hwcLayer.backgroundColor) << '\n'; - } else if (hwcLayer.compositionType == HWC_SIDEBAND) { - output << " Stream: " << hwcLayer.sidebandStream << '\n'; - } else { - output << " Buffer: " << hwcLayer.handle << "/" << - hwcLayer.acquireFenceFd << '\n'; - } - - output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) << - '\n'; - - output << fill << "Source crop: "; - if (hwc1MinorVersion >= 3) { - output << frectString(hwcLayer.sourceCropf) << '\n'; - } else { - output << rectString(hwcLayer.sourceCropi) << '\n'; - } - - output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform); - output << " Blend mode: " << hwc1BlendModeString(hwcLayer.blending); - if (hwcLayer.planeAlpha != 0xFF) { - output << " Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f); - } - output << '\n'; - - if (hwcLayer.hints != 0) { - output << fill << "Hints:"; - if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) { - output << " TripleBuffer"; - } - if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) { - output << " ClearFB"; - } - output << '\n'; - } - - if (hwcLayer.flags != 0) { - output << fill << "Flags:"; - if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) { - output << " SkipLayer"; - } - if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) { - output << " IsCursorLayer"; - } - output << '\n'; - } - - return output.str(); -} - -static std::string to_string(const hwc_display_contents_1_t& hwcContents, - int32_t hwc1MinorVersion) { - const char* fill = " "; - - std::stringstream output; - output << fill << "Geometry changed: " << - ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n"); - - output << fill << hwcContents.numHwLayers << " Layer" << - ((hwcContents.numHwLayers == 1) ? "\n" : "s\n"); - for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) { - output << fill << " Layer " << layer; - output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion); - } - - if (hwcContents.outbuf != nullptr) { - output << fill << "Output buffer: " << hwcContents.outbuf << "/" << - hwcContents.outbufAcquireFenceFd << '\n'; - } - - return output.str(); -} - -std::string HWC2On1Adapter::Display::dump() const { - std::unique_lock<std::recursive_mutex> lock(mStateMutex); - - std::stringstream output; - - output << " Display " << mId << ": "; - output << to_string(mType) << " "; - output << "HWC1 ID: " << mHwc1Id << " "; - output << "Power mode: " << to_string(mPowerMode) << " "; - output << "Vsync: " << to_string(mVsyncEnabled) << '\n'; - - output << " Color modes [active]:"; - for (const auto& mode : mColorModes) { - if (mode == mActiveColorMode) { - output << " [" << mode << ']'; - } else { - output << " " << mode; - } - } - output << '\n'; - - output << " " << mConfigs.size() << " Config" << - (mConfigs.size() == 1 ? "" : "s") << " (* active)\n"; - for (const auto& config : mConfigs) { - output << (config == mActiveConfig ? " * " : " "); - output << config->toString(true) << '\n'; - } - - output << " " << mLayers.size() << " Layer" << - (mLayers.size() == 1 ? "" : "s") << '\n'; - for (const auto& layer : mLayers) { - output << layer->dump(); - } - - output << " Client target: " << mClientTarget.getBuffer() << '\n'; - - if (mOutputBuffer.getBuffer() != nullptr) { - output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n'; - } - - if (mHwc1RequestedContents) { - output << " Last requested HWC1 state\n"; - output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion); - } - - return output.str(); -} - -hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) { - if (numRects == 0) { - return nullptr; - } - - if (numRects > mNumAvailableRects) { - // This should NEVER happen since we calculated how many rects the - // display would need. - ALOGE("Rect allocation failure! SF is likely to crash soon!"); - return nullptr; - - } - hwc_rect_t* rects = mNextAvailableRect; - mNextAvailableRect += numRects; - mNumAvailableRects -= numRects; - return rects; -} - -hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() { - return mHwc1RequestedContents.get(); -} - -void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute, - int32_t value) { - mAttributes[attribute] = value; -} - -int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const { - if (mAttributes.count(attribute) == 0) { - return -1; - } - return mAttributes.at(attribute); -} - -void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { - android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode)); - mHwc1Ids.emplace(colorMode, id); -} - -bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const { - for (const auto& idPair : mHwc1Ids) { - if (id == idPair.second) { - return true; - } - } - return false; -} - -Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( - uint32_t id, android_color_mode_t* outMode) const { - for (const auto& idPair : mHwc1Ids) { - if (id == idPair.second) { - *outMode = idPair.first; - return Error::None; - } - } - ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId); - return Error::BadParameter; -} - -Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode, - uint32_t* outId) const { - for (const auto& idPair : mHwc1Ids) { - if (mode == idPair.first) { - *outId = idPair.second; - return Error::None; - } - } - ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId); - return Error::BadParameter; -} - -bool HWC2On1Adapter::Display::Config::merge(const Config& other) { - auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height, - HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX, - HWC2::Attribute::DpiY}; - for (auto attribute : attributes) { - if (getAttribute(attribute) != other.getAttribute(attribute)) { - return false; - } - } - android_color_mode_t otherColorMode = - static_cast<android_color_mode_t>(other.getAttribute(ColorMode)); - if (mHwc1Ids.count(otherColorMode) != 0) { - ALOGE("Attempted to merge two configs (%u and %u) which appear to be " - "identical", mHwc1Ids.at(otherColorMode), - other.mHwc1Ids.at(otherColorMode)); - return false; - } - mHwc1Ids.emplace(otherColorMode, - other.mHwc1Ids.at(otherColorMode)); - return true; -} - -std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const { - std::set<android_color_mode_t> colorModes; - for (const auto& idPair : mHwc1Ids) { - colorModes.emplace(idPair.first); - } - return colorModes; -} - -std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const { - std::string output; - - const size_t BUFFER_SIZE = 100; - char buffer[BUFFER_SIZE] = {}; - auto writtenBytes = snprintf(buffer, BUFFER_SIZE, - "%u x %u", mAttributes.at(HWC2::Attribute::Width), - mAttributes.at(HWC2::Attribute::Height)); - output.append(buffer, writtenBytes); - - if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) { - std::memset(buffer, 0, BUFFER_SIZE); - writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz", - 1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod)); - output.append(buffer, writtenBytes); - } - - if (mAttributes.count(HWC2::Attribute::DpiX) != 0 && - mAttributes.at(HWC2::Attribute::DpiX) != -1) { - std::memset(buffer, 0, BUFFER_SIZE); - writtenBytes = snprintf(buffer, BUFFER_SIZE, - ", DPI: %.1f x %.1f", - mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f, - mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f); - output.append(buffer, writtenBytes); - } - - std::memset(buffer, 0, BUFFER_SIZE); - if (splitLine) { - writtenBytes = snprintf(buffer, BUFFER_SIZE, - "\n HWC1 ID/Color transform:"); - } else { - writtenBytes = snprintf(buffer, BUFFER_SIZE, - ", HWC1 ID/Color transform:"); - } - output.append(buffer, writtenBytes); - - - for (const auto& id : mHwc1Ids) { - android_color_mode_t colorMode = id.first; - uint32_t hwc1Id = id.second; - std::memset(buffer, 0, BUFFER_SIZE); - if (colorMode == mDisplay.mActiveColorMode) { - writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id, - colorMode); - } else { - writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id, - colorMode); - } - output.append(buffer, writtenBytes); - } - - return output; -} - -std::shared_ptr<const HWC2On1Adapter::Display::Config> - HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const { - if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { - return nullptr; - } - return mConfigs[configId]; -} - -void HWC2On1Adapter::Display::populateColorModes() { - mColorModes = mConfigs[0]->getColorModes(); - for (const auto& config : mConfigs) { - std::set<android_color_mode_t> intersection; - auto configModes = config->getColorModes(); - std::set_intersection(mColorModes.cbegin(), mColorModes.cend(), - configModes.cbegin(), configModes.cend(), - std::inserter(intersection, intersection.begin())); - std::swap(intersection, mColorModes); - } -} - -void HWC2On1Adapter::Display::initializeActiveConfig() { - if (mDevice.mHwc1Device->getActiveConfig == nullptr) { - ALOGV("getActiveConfig is null, choosing config 0"); - mActiveConfig = mConfigs[0]; - mActiveColorMode = HAL_COLOR_MODE_NATIVE; - return; - } - - auto activeConfig = mDevice.mHwc1Device->getActiveConfig( - mDevice.mHwc1Device, mHwc1Id); - - // Some devices startup without an activeConfig: - // We need to set one ourselves. - if (activeConfig == HWC_ERROR) { - ALOGV("There is no active configuration: Picking the first one: 0."); - const int defaultIndex = 0; - mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex); - activeConfig = defaultIndex; - } - - for (const auto& config : mConfigs) { - if (config->hasHwc1Id(activeConfig)) { - ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig); - mActiveConfig = config; - if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) { - // This should never happen since we checked for the config's presence before - // setting it as active. - ALOGE("Unable to find color mode for active HWC1 config %d", config->getId()); - mActiveColorMode = HAL_COLOR_MODE_NATIVE; - } - break; - } - } - if (!mActiveConfig) { - ALOGV("Unable to find active HWC1 config %u, defaulting to " - "config 0", activeConfig); - mActiveConfig = mConfigs[0]; - mActiveColorMode = HAL_COLOR_MODE_NATIVE; - } - - - - -} - -void HWC2On1Adapter::Display::allocateRequestedContents() { - // What needs to be allocated: - // 1 hwc_display_contents_1_t - // 1 hwc_layer_1_t for each layer - // 1 hwc_rect_t for each layer's surfaceDamage - // 1 hwc_rect_t for each layer's visibleRegion - // 1 hwc_layer_1_t for the framebuffer - // 1 hwc_rect_t for the framebuffer's visibleRegion - - // Count # of surfaceDamage - size_t numSurfaceDamages = 0; - for (const auto& layer : mLayers) { - numSurfaceDamages += layer->getNumSurfaceDamages(); - } - - // Count # of visibleRegions (start at 1 for mandatory framebuffer target - // region) - size_t numVisibleRegion = 1; - for (const auto& layer : mLayers) { - numVisibleRegion += layer->getNumVisibleRegions(); - } - - size_t numRects = numVisibleRegion + numSurfaceDamages; - auto numLayers = mLayers.size() + 1; - size_t size = sizeof(hwc_display_contents_1_t) + - sizeof(hwc_layer_1_t) * numLayers + - sizeof(hwc_rect_t) * numRects; - auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1)); - mHwc1RequestedContents.reset(contents); - mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]); - mNumAvailableRects = numRects; -} - -void HWC2On1Adapter::Display::assignHwc1LayerIds() { - mHwc1LayerMap.clear(); - size_t nextHwc1Id = 0; - for (auto& layer : mLayers) { - mHwc1LayerMap[nextHwc1Id] = layer; - layer->setHwc1Id(nextHwc1Id++); - } -} - -void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer, - const Layer& layer) { - auto layerId = layer.getId(); - switch (hwc1Layer.compositionType) { - case HWC_FRAMEBUFFER: - if (layer.getCompositionType() != Composition::Client) { - mChanges->addTypeChange(layerId, Composition::Client); - } - break; - case HWC_OVERLAY: - if (layer.getCompositionType() != Composition::Device) { - mChanges->addTypeChange(layerId, Composition::Device); - } - break; - case HWC_BACKGROUND: - ALOGE_IF(layer.getCompositionType() != Composition::SolidColor, - "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2" - " wasn't expecting SolidColor"); - break; - case HWC_FRAMEBUFFER_TARGET: - // Do nothing, since it shouldn't be modified by HWC1 - break; - case HWC_SIDEBAND: - ALOGE_IF(layer.getCompositionType() != Composition::Sideband, - "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2" - " wasn't expecting Sideband"); - break; - case HWC_CURSOR_OVERLAY: - ALOGE_IF(layer.getCompositionType() != Composition::Cursor, - "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but" - " HWC2 wasn't expecting Cursor"); - break; - } -} - -void HWC2On1Adapter::Display::updateLayerRequests( - const hwc_layer_1_t& hwc1Layer, const Layer& layer) { - if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) { - mChanges->addLayerRequest(layer.getId(), - LayerRequest::ClearClientTarget); - } -} - -void HWC2On1Adapter::Display::prepareFramebufferTarget() { - // We check that mActiveConfig is valid in Display::prepare - int32_t width = mActiveConfig->getAttribute(Attribute::Width); - int32_t height = mActiveConfig->getAttribute(Attribute::Height); - - auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()]; - hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET; - hwc1Target.releaseFenceFd = -1; - hwc1Target.hints = 0; - hwc1Target.flags = 0; - hwc1Target.transform = 0; - hwc1Target.blending = HWC_BLENDING_PREMULT; - if (mDevice.getHwc1MinorVersion() < 3) { - hwc1Target.sourceCropi = {0, 0, width, height}; - } else { - hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width), - static_cast<float>(height)}; - } - hwc1Target.displayFrame = {0, 0, width, height}; - hwc1Target.planeAlpha = 255; - - hwc1Target.visibleRegionScreen.numRects = 1; - hwc_rect_t* rects = GetRects(1); - rects[0].left = 0; - rects[0].top = 0; - rects[0].right = width; - rects[0].bottom = height; - hwc1Target.visibleRegionScreen.rects = rects; - - // We will set this to the correct value in set - hwc1Target.acquireFenceFd = -1; -} - -// Layer functions - -std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1); - -HWC2On1Adapter::Layer::Layer(Display& display) - : mId(sNextId++), - mDisplay(display), - mBuffer(), - mSurfaceDamage(), - mBlendMode(BlendMode::None), - mColor({0, 0, 0, 0}), - mCompositionType(Composition::Invalid), - mDisplayFrame({0, 0, -1, -1}), - mPlaneAlpha(0.0f), - mSidebandStream(nullptr), - mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}), - mTransform(Transform::None), - mVisibleRegion(), - mZ(0), - mReleaseFence(), - mHwc1Id(0), - mHasUnsupportedPlaneAlpha(false) {} - -bool HWC2On1Adapter::SortLayersByZ::operator()( - const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) { - return lhs->getZ() < rhs->getZ(); -} - -Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer, - int32_t acquireFence) { - ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId); - mBuffer.setBuffer(buffer); - mBuffer.setFence(acquireFence); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) { - if (mCompositionType != Composition::Cursor) { - return Error::BadLayer; - } - - if (mDisplay.hasChanges()) { - return Error::NotValidated; - } - - auto displayId = mDisplay.getHwc1Id(); - auto hwc1Device = mDisplay.getDevice().getHwc1Device(); - hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) { - // HWC1 supports surface damage starting only with version 1.5. - if (mDisplay.getDevice().mHwc1MinorVersion < 5) { - return Error::None; - } - mSurfaceDamage.resize(damage.numRects); - std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin()); - return Error::None; -} - -// Layer state functions - -Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) { - mBlendMode = mode; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) { - mColor = color; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setCompositionType(Composition type) { - mCompositionType = type; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) { - return Error::None; -} - -Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) { - mDisplayFrame = frame; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) { - mPlaneAlpha = alpha; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) { - mSidebandStream = stream; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) { - mSourceCrop = crop; - mDisplay.markGeometryChanged(); - return Error::None; -} - -Error HWC2On1Adapter::Layer::setTransform(Transform transform) { - mTransform = transform; - mDisplay.markGeometryChanged(); - return Error::None; -} - -static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) { - return rect1.left == rect2.left && - rect1.right == rect2.right && - rect1.top == rect2.top && - rect1.bottom == rect2.bottom; -} - -Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) { - if ((getNumVisibleRegions() != visible.numRects) || - !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects, - compareRects)) { - mVisibleRegion.resize(visible.numRects); - std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin()); - mDisplay.markGeometryChanged(); - } - return Error::None; -} - -Error HWC2On1Adapter::Layer::setZ(uint32_t z) { - mZ = z; - return Error::None; -} - -void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) { - ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId); - mReleaseFence.add(fenceFd); -} - -const sp<MiniFence>& HWC2On1Adapter::Layer::getReleaseFence() const { - return mReleaseFence.get(); -} - -void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) { - applyCommonState(hwc1Layer); - applyCompositionType(hwc1Layer); - switch (mCompositionType) { - case Composition::SolidColor : applySolidColorState(hwc1Layer); break; - case Composition::Sideband : applySidebandState(hwc1Layer); break; - default: applyBufferState(hwc1Layer); break; - } -} - -static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion, - const std::vector<hwc_rect_t>& surfaceDamage) { - std::string regions; - regions += " Visible Region"; - regions.resize(40, ' '); - regions += "Surface Damage\n"; - - size_t numPrinted = 0; - size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size()); - while (numPrinted < maxSize) { - std::string line(" "); - if (visibleRegion.empty() && numPrinted == 0) { - line += "None"; - } else if (numPrinted < visibleRegion.size()) { - line += rectString(visibleRegion[numPrinted]); - } - line.resize(40, ' '); - if (surfaceDamage.empty() && numPrinted == 0) { - line += "None"; - } else if (numPrinted < surfaceDamage.size()) { - line += rectString(surfaceDamage[numPrinted]); - } - line += '\n'; - regions += line; - ++numPrinted; - } - return regions; -} - -std::string HWC2On1Adapter::Layer::dump() const { - std::stringstream output; - const char* fill = " "; - - output << fill << to_string(mCompositionType); - output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " "; - output << "Z: " << mZ; - if (mCompositionType == HWC2::Composition::SolidColor) { - output << " " << colorString(mColor); - } else if (mCompositionType == HWC2::Composition::Sideband) { - output << " Handle: " << mSidebandStream << '\n'; - } else { - output << " Buffer: " << mBuffer.getBuffer() << "/" << - mBuffer.getFence() << '\n'; - output << fill << " Display frame [LTRB]: " << - rectString(mDisplayFrame) << '\n'; - output << fill << " Source crop: " << - frectString(mSourceCrop) << '\n'; - output << fill << " Transform: " << to_string(mTransform); - output << " Blend mode: " << to_string(mBlendMode); - if (mPlaneAlpha != 1.0f) { - output << " Alpha: " << - alphaString(mPlaneAlpha) << '\n'; - } else { - output << '\n'; - } - output << regionStrings(mVisibleRegion, mSurfaceDamage); - } - return output.str(); -} - -static int getHwc1Blending(HWC2::BlendMode blendMode) { - switch (blendMode) { - case BlendMode::Coverage: return HWC_BLENDING_COVERAGE; - case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT; - default: return HWC_BLENDING_NONE; - } -} - -void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) { - auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion(); - hwc1Layer.blending = getHwc1Blending(mBlendMode); - hwc1Layer.displayFrame = mDisplayFrame; - - auto pendingAlpha = mPlaneAlpha; - if (minorVersion < 2) { - mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f; - } else { - hwc1Layer.planeAlpha = - static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f); - } - - if (minorVersion < 3) { - auto pending = mSourceCrop; - hwc1Layer.sourceCropi.left = - static_cast<int32_t>(std::ceil(pending.left)); - hwc1Layer.sourceCropi.top = - static_cast<int32_t>(std::ceil(pending.top)); - hwc1Layer.sourceCropi.right = - static_cast<int32_t>(std::floor(pending.right)); - hwc1Layer.sourceCropi.bottom = - static_cast<int32_t>(std::floor(pending.bottom)); - } else { - hwc1Layer.sourceCropf = mSourceCrop; - } - - hwc1Layer.transform = static_cast<uint32_t>(mTransform); - - auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen; - hwc1VisibleRegion.numRects = mVisibleRegion.size(); - hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects); - hwc1VisibleRegion.rects = rects; - for (size_t i = 0; i < mVisibleRegion.size(); i++) { - rects[i] = mVisibleRegion[i]; - } -} - -void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) { - // If the device does not support background color it is likely to make - // assumption regarding backgroundColor and handle (both fields occupy - // the same location in hwc_layer_1_t union). - // To not confuse these devices we don't set background color and we - // make sure handle is a null pointer. - if (hasUnsupportedBackgroundColor()) { - hwc1Layer.handle = nullptr; - } else { - hwc1Layer.backgroundColor = mColor; - } -} - -void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) { - hwc1Layer.sidebandStream = mSidebandStream; -} - -void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) { - hwc1Layer.handle = mBuffer.getBuffer(); - hwc1Layer.acquireFenceFd = mBuffer.getFence(); -} - -void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) { - // HWC1 never supports color transforms or dataspaces and only sometimes - // supports plane alpha (depending on the version). These require us to drop - // some or all layers to client composition. - if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() || - hasUnsupportedBackgroundColor()) { - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags = HWC_SKIP_LAYER; - return; - } - - hwc1Layer.flags = 0; - switch (mCompositionType) { - case Composition::Client: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - break; - case Composition::Device: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - break; - case Composition::SolidColor: - // In theory the following line should work, but since the HWC1 - // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1 - // devices may not work correctly. To be on the safe side, we - // fall back to client composition. - // - // hwc1Layer.compositionType = HWC_BACKGROUND; - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - break; - case Composition::Cursor: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) { - hwc1Layer.hints |= HWC_IS_CURSOR_LAYER; - } - break; - case Composition::Sideband: - if (mDisplay.getDevice().getHwc1MinorVersion() < 4) { - hwc1Layer.compositionType = HWC_SIDEBAND; - } else { - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - } - break; - default: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - break; - } - ALOGV("Layer %" PRIu64 " %s set to %d", mId, - to_string(mCompositionType).c_str(), - hwc1Layer.compositionType); - ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping"); -} - -// Adapter helpers - -void HWC2On1Adapter::populateCapabilities() { - if (mHwc1MinorVersion >= 3U) { - int supportedTypes = 0; - auto result = mHwc1Device->query(mHwc1Device, - HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes); - if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) { - ALOGI("Found support for HWC virtual displays"); - mHwc1SupportsVirtualDisplays = true; - } - } - if (mHwc1MinorVersion >= 4U) { - mCapabilities.insert(Capability::SidebandStream); - } - - // Check for HWC background color layer support. - if (mHwc1MinorVersion >= 1U) { - int backgroundColorSupported = 0; - auto result = mHwc1Device->query(mHwc1Device, - HWC_BACKGROUND_LAYER_SUPPORTED, - &backgroundColorSupported); - if ((result == 0) && (backgroundColorSupported == 1)) { - ALOGV("Found support for HWC background color"); - mHwc1SupportsBackgroundColor = true; - } - } - - // Some devices might have HWC1 retire fences that accurately emulate - // HWC2 present fences when they are deferred, but it's not very reliable. - // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices. - mCapabilities.insert(Capability::PresentFenceIsNotReliable); -} - -HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) { - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - auto display = mDisplays.find(id); - if (display == mDisplays.end()) { - return nullptr; - } - - return display->second.get(); -} - -std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer( - hwc2_display_t displayId, hwc2_layer_t layerId) { - auto display = getDisplay(displayId); - if (!display) { - return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay); - } - - auto layerEntry = mLayers.find(layerId); - if (layerEntry == mLayers.end()) { - return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer); - } - - auto layer = layerEntry->second; - if (layer->getDisplay().getId() != displayId) { - return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer); - } - return std::make_tuple(layer.get(), Error::None); -} - -void HWC2On1Adapter::populatePrimary() { - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical); - mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId(); - display->setHwc1Id(HWC_DISPLAY_PRIMARY); - display->populateConfigs(); - mDisplays.emplace(display->getId(), std::move(display)); -} - -bool HWC2On1Adapter::prepareAllDisplays() { - ATRACE_CALL(); - - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - for (const auto& displayPair : mDisplays) { - auto& display = displayPair.second; - if (!display->prepare()) { - return false; - } - } - - if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) { - ALOGE("prepareAllDisplays: Unable to find primary HWC1 display"); - return false; - } - - // Build an array of hwc_display_contents_1 to call prepare() on HWC1. - mHwc1Contents.clear(); - - // Always push the primary display - auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY]; - auto& primaryDisplay = mDisplays[primaryDisplayId]; - mHwc1Contents.push_back(primaryDisplay->getDisplayContents()); - - // Push the external display, if present - if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) { - auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL]; - auto& externalDisplay = mDisplays[externalDisplayId]; - mHwc1Contents.push_back(externalDisplay->getDisplayContents()); - } else { - // Even if an external display isn't present, we still need to send - // at least two displays down to HWC1 - mHwc1Contents.push_back(nullptr); - } - - // Push the hardware virtual display, if supported and present - if (mHwc1MinorVersion >= 3) { - if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) { - auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL]; - auto& virtualDisplay = mDisplays[virtualDisplayId]; - mHwc1Contents.push_back(virtualDisplay->getDisplayContents()); - } else { - mHwc1Contents.push_back(nullptr); - } - } - - for (auto& displayContents : mHwc1Contents) { - if (!displayContents) { - continue; - } - - ALOGV("Display %zd layers:", mHwc1Contents.size() - 1); - for (size_t l = 0; l < displayContents->numHwLayers; ++l) { - auto& layer = displayContents->hwLayers[l]; - ALOGV(" %zd: %d", l, layer.compositionType); - } - } - - ALOGV("Calling HWC1 prepare"); - { - ATRACE_NAME("HWC1 prepare"); - mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(), - mHwc1Contents.data()); - } - - for (size_t c = 0; c < mHwc1Contents.size(); ++c) { - auto& contents = mHwc1Contents[c]; - if (!contents) { - continue; - } - ALOGV("Display %zd layers:", c); - for (size_t l = 0; l < contents->numHwLayers; ++l) { - ALOGV(" %zd: %d", l, contents->hwLayers[l].compositionType); - } - } - - // Return the received contents to their respective displays - for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { - if (mHwc1Contents[hwc1Id] == nullptr) { - continue; - } - - auto displayId = mHwc1DisplayMap[hwc1Id]; - auto& display = mDisplays[displayId]; - display->generateChanges(); - } - - return true; -} - -void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays, - hwc_display_contents_1_t** displays) { - ALOGV("*****************************"); - size_t displayId = 0; - while (displayId < numDisplays) { - hwc_display_contents_1_t* display = displays[displayId]; - - ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display); - if (display == nullptr) { - displayId++; - continue; - } - ALOGV(" retirefd:0x%08x", display->retireFenceFd); - ALOGV(" outbuf :0x%p", display->outbuf); - ALOGV(" outbuffd:0x%08x", display->outbufAcquireFenceFd); - ALOGV(" flags :0x%08x", display->flags); - for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) { - hwc_layer_1_t& layer = display->hwLayers[layerId]; - ALOGV(" Layer[%zu]:", layerId); - ALOGV(" composition : 0x%08x", layer.compositionType); - ALOGV(" hints : 0x%08x", layer.hints); - ALOGV(" flags : 0x%08x", layer.flags); - ALOGV(" handle : 0x%p", layer.handle); - ALOGV(" transform : 0x%08x", layer.transform); - ALOGV(" blending : 0x%08x", layer.blending); - ALOGV(" sourceCropf : %f, %f, %f, %f", - layer.sourceCropf.left, - layer.sourceCropf.top, - layer.sourceCropf.right, - layer.sourceCropf.bottom); - ALOGV(" displayFrame : %d, %d, %d, %d", - layer.displayFrame.left, - layer.displayFrame.left, - layer.displayFrame.left, - layer.displayFrame.left); - hwc_region_t& visReg = layer.visibleRegionScreen; - ALOGV(" visibleRegionScreen: #0x%08zx[@0x%p]", - visReg.numRects, - visReg.rects); - for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) { - if (layer.visibleRegionScreen.rects == nullptr) { - ALOGV(" null"); - } else { - ALOGV(" visibleRegionScreen[%zu] %d, %d, %d, %d", - visRegId, - visReg.rects[visRegId].left, - visReg.rects[visRegId].top, - visReg.rects[visRegId].right, - visReg.rects[visRegId].bottom); - } - } - ALOGV(" acquireFenceFd : 0x%08x", layer.acquireFenceFd); - ALOGV(" releaseFenceFd : 0x%08x", layer.releaseFenceFd); - ALOGV(" planeAlpha : 0x%08x", layer.planeAlpha); - if (getMinorVersion(device) < 5) - continue; - ALOGV(" surfaceDamage : #0x%08zx[@0x%p]", - layer.surfaceDamage.numRects, - layer.surfaceDamage.rects); - for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) { - if (layer.surfaceDamage.rects == nullptr) { - ALOGV(" null"); - } else { - ALOGV(" surfaceDamage[%zu] %d, %d, %d, %d", - sdId, - layer.surfaceDamage.rects[sdId].left, - layer.surfaceDamage.rects[sdId].top, - layer.surfaceDamage.rects[sdId].right, - layer.surfaceDamage.rects[sdId].bottom); - } - } - } - displayId++; - } - ALOGV("-----------------------------"); -} - -Error HWC2On1Adapter::setAllDisplays() { - ATRACE_CALL(); - - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - // Make sure we're ready to validate - for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { - if (mHwc1Contents[hwc1Id] == nullptr) { - continue; - } - - auto displayId = mHwc1DisplayMap[hwc1Id]; - auto& display = mDisplays[displayId]; - Error error = display->set(*mHwc1Contents[hwc1Id]); - if (error != Error::None) { - ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id, - to_string(error).c_str()); - return error; - } - } - - ALOGV("Calling HWC1 set"); - { - ATRACE_NAME("HWC1 set"); - //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data()); - mHwc1Device->set(mHwc1Device, mHwc1Contents.size(), - mHwc1Contents.data()); - } - - // Add retire and release fences - for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { - if (mHwc1Contents[hwc1Id] == nullptr) { - continue; - } - - auto displayId = mHwc1DisplayMap[hwc1Id]; - auto& display = mDisplays[displayId]; - auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd; - ALOGV("setAllDisplays: Adding retire fence %d to display %zd", - retireFenceFd, hwc1Id); - display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd); - display->addReleaseFences(*mHwc1Contents[hwc1Id]); - } - - return Error::None; -} - -void HWC2On1Adapter::hwc1Invalidate() { - ALOGV("Received hwc1Invalidate"); - - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - // If the HWC2-side callback hasn't been registered yet, buffer this until - // it is registered. - if (mCallbacks.count(Callback::Refresh) == 0) { - mHasPendingInvalidate = true; - return; - } - - const auto& callbackInfo = mCallbacks[Callback::Refresh]; - std::vector<hwc2_display_t> displays; - for (const auto& displayPair : mDisplays) { - displays.emplace_back(displayPair.first); - } - - // Call back without the state lock held. - lock.unlock(); - - auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer); - for (auto display : displays) { - refresh(callbackInfo.data, display); - } -} - -void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) { - ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp); - - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - // If the HWC2-side callback hasn't been registered yet, buffer this until - // it is registered. - if (mCallbacks.count(Callback::Vsync) == 0) { - mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp); - return; - } - - if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { - ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId); - return; - } - - const auto& callbackInfo = mCallbacks[Callback::Vsync]; - auto displayId = mHwc1DisplayMap[hwc1DisplayId]; - - // Call back without the state lock held. - lock.unlock(); - - auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer); - vsync(callbackInfo.data, displayId, timestamp); -} - -void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) { - ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected); - - if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) { - ALOGE("hwc1Hotplug: Received hotplug for non-external display"); - return; - } - - std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - - // If the HWC2-side callback hasn't been registered yet, buffer this until - // it is registered - if (mCallbacks.count(Callback::Hotplug) == 0) { - mPendingHotplugs.emplace_back(hwc1DisplayId, connected); - return; - } - - hwc2_display_t displayId = UINT64_MAX; - if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { - if (connected == 0) { - ALOGW("hwc1Hotplug: Received disconnect for unconnected display"); - return; - } - - // Create a new display on connect - auto display = std::make_shared<HWC2On1Adapter::Display>(*this, - HWC2::DisplayType::Physical); - display->setHwc1Id(HWC_DISPLAY_EXTERNAL); - display->populateConfigs(); - displayId = display->getId(); - mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId; - mDisplays.emplace(displayId, std::move(display)); - } else { - if (connected != 0) { - ALOGW("hwc1Hotplug: Received connect for previously connected " - "display"); - return; - } - - // Disconnect an existing display - displayId = mHwc1DisplayMap[hwc1DisplayId]; - mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL); - mDisplays.erase(displayId); - } - - const auto& callbackInfo = mCallbacks[Callback::Hotplug]; - - // Call back without the state lock held - lock.unlock(); - - auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer); - auto hwc2Connected = (connected == 0) ? - HWC2::Connection::Disconnected : HWC2::Connection::Connected; - hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected)); -} -} // namespace android diff --git a/libs/hwc2on1adapter/MiniFence.cpp b/libs/hwc2on1adapter/MiniFence.cpp deleted file mode 100644 index dfbe4d63cc..0000000000 --- a/libs/hwc2on1adapter/MiniFence.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ - -#include "hwc2on1adapter/MiniFence.h" - -#include <unistd.h> - -namespace android { - -const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence); - -MiniFence::MiniFence() : - mFenceFd(-1) { -} - -MiniFence::MiniFence(int fenceFd) : - mFenceFd(fenceFd) { -} - -MiniFence::~MiniFence() { - if (mFenceFd != -1) { - close(mFenceFd); - } -} - -int MiniFence::dup() const { - return ::dup(mFenceFd); -} -} diff --git a/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h deleted file mode 100644 index 3badfce078..0000000000 --- a/libs/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h +++ /dev/null @@ -1,738 +0,0 @@ -/* - * Copyright 2015 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_1_ADAPTER_H -#define ANDROID_SF_HWC2_ON_1_ADAPTER_H - -#define HWC2_INCLUDE_STRINGIFICATION -#define HWC2_USE_CPP11 -#include <hardware/hwcomposer2.h> -#undef HWC2_INCLUDE_STRINGIFICATION -#undef HWC2_USE_CPP11 - -#include "MiniFence.h" - -#include <atomic> -#include <map> -#include <mutex> -#include <queue> -#include <set> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -struct hwc_composer_device_1; -struct hwc_display_contents_1; -struct hwc_layer_1; - -namespace android { - -// For devices unable to provide an implementation of HWC2 (see hwcomposer2.h), -// we provide an adapter able to talk to HWC1 (see hwcomposer.h). It translates -// streamed function calls ala HWC2 model to batched array of structs calls ala -// HWC1 model. -class HWC2On1Adapter : public hwc2_device_t -{ -public: - explicit HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device); - ~HWC2On1Adapter(); - - struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; } - uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; } - -private: - static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) { - return static_cast<HWC2On1Adapter*>(device); - } - - // getCapabilities - - void doGetCapabilities(uint32_t* outCount, - int32_t* /*hwc2_capability_t*/ outCapabilities); - static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount, - int32_t* /*hwc2_capability_t*/ outCapabilities) { - getAdapter(device)->doGetCapabilities(outCount, outCapabilities); - } - - bool supportsBackgroundColor() { - return mHwc1SupportsBackgroundColor; - } - - // getFunction - - hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor); - static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device, - int32_t intDesc) { - auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc); - return getAdapter(device)->doGetFunction(descriptor); - } - - // Device functions - - HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height, - hwc2_display_t* outDisplay); - static int32_t createVirtualDisplayHook(hwc2_device_t* device, - uint32_t width, uint32_t height, int32_t* /*format*/, - hwc2_display_t* outDisplay) { - // HWC1 implementations cannot override the buffer format requested by - // the consumer - auto error = getAdapter(device)->createVirtualDisplay(width, height, - outDisplay); - return static_cast<int32_t>(error); - } - - HWC2::Error destroyVirtualDisplay(hwc2_display_t display); - static int32_t destroyVirtualDisplayHook(hwc2_device_t* device, - hwc2_display_t display) { - auto error = getAdapter(device)->destroyVirtualDisplay(display); - return static_cast<int32_t>(error); - } - - std::string mDumpString; - void dump(uint32_t* outSize, char* outBuffer); - static void dumpHook(hwc2_device_t* device, uint32_t* outSize, - char* outBuffer) { - getAdapter(device)->dump(outSize, outBuffer); - } - - uint32_t getMaxVirtualDisplayCount(); - static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) { - return getAdapter(device)->getMaxVirtualDisplayCount(); - } - - HWC2::Error registerCallback(HWC2::Callback descriptor, - hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer); - static int32_t registerCallbackHook(hwc2_device_t* device, - int32_t intDesc, hwc2_callback_data_t callbackData, - hwc2_function_pointer_t pointer) { - auto descriptor = static_cast<HWC2::Callback>(intDesc); - auto error = getAdapter(device)->registerCallback(descriptor, - callbackData, pointer); - return static_cast<int32_t>(error); - } - - // Display functions - - class Layer; - - class SortLayersByZ { - public: - bool operator()(const std::shared_ptr<Layer>& lhs, - const std::shared_ptr<Layer>& rhs); - }; - - // The semantics of the fences returned by the device differ between - // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h - // for more information. - // - // Release fences in hwc1 are obtained on set() for a frame n and signaled - // when the layer buffer is not needed for read operations anymore - // (typically on frame n+1). In HWC2, release fences are obtained with a - // special call after present() for frame n. These fences signal - // on frame n: More specifically, the fence for a given buffer provided in - // frame n will signal when the prior buffer is no longer required. - // - // A retire fence (HWC1) is signaled when a composition is replaced - // on the panel whereas a present fence (HWC2) is signaled when a - // composition starts to be displayed on a panel. - // - // The HWC2to1Adapter emulates the new fence semantics for a frame - // n by returning the fence from frame n-1. For frame 0, the adapter - // returns NO_FENCE. - class DeferredFence { - public: - DeferredFence() - : mFences({MiniFence::NO_FENCE, MiniFence::NO_FENCE}) {} - - void add(int32_t fenceFd) { - mFences.emplace(new MiniFence(fenceFd)); - mFences.pop(); - } - - const sp<MiniFence>& get() const { - return mFences.front(); - } - - private: - // There are always two fences in this queue. - std::queue<sp<MiniFence>> mFences; - }; - - class FencedBuffer { - public: - FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {} - - void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; } - void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); } - - buffer_handle_t getBuffer() const { return mBuffer; } - int getFence() const { return mFence->dup(); } - - private: - buffer_handle_t mBuffer; - sp<MiniFence> mFence; - }; - - class Display { - public: - Display(HWC2On1Adapter& device, HWC2::DisplayType type); - - hwc2_display_t getId() const { return mId; } - HWC2On1Adapter& getDevice() const { return mDevice; } - - // Does not require locking because it is set before adding the - // Displays to the Adapter's list of displays - void setHwc1Id(int32_t id) { mHwc1Id = id; } - int32_t getHwc1Id() const { return mHwc1Id; } - - // HWC2 Display functions - HWC2::Error acceptChanges(); - HWC2::Error createLayer(hwc2_layer_t* outLayerId); - HWC2::Error destroyLayer(hwc2_layer_t layerId); - HWC2::Error getActiveConfig(hwc2_config_t* outConfigId); - HWC2::Error getAttribute(hwc2_config_t configId, - HWC2::Attribute attribute, int32_t* outValue); - HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, - hwc2_layer_t* outLayers, int32_t* outTypes); - HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); - HWC2::Error getConfigs(uint32_t* outNumConfigs, - hwc2_config_t* outConfigIds); - HWC2::Error getDozeSupport(int32_t* outSupport); - HWC2::Error getHdrCapabilities(uint32_t* outNumTypes, - int32_t* outTypes, float* outMaxLuminance, - float* outMaxAverageLuminance, float* outMinLuminance); - HWC2::Error getName(uint32_t* outSize, char* outName); - HWC2::Error getReleaseFences(uint32_t* outNumElements, - hwc2_layer_t* outLayers, int32_t* outFences); - HWC2::Error getRequests(int32_t* outDisplayRequests, - uint32_t* outNumElements, hwc2_layer_t* outLayers, - int32_t* outLayerRequests); - HWC2::Error getType(int32_t* outType); - - // Since HWC1 "presents" (called "set" in HWC1) all Displays - // at once, the first call to any Display::present will trigger - // present() on all Displays in the Device. Subsequent calls without - // first calling validate() are noop (except for duping/returning - // the retire fence). - HWC2::Error present(int32_t* outRetireFence); - - HWC2::Error setActiveConfig(hwc2_config_t configId); - HWC2::Error setClientTarget(buffer_handle_t target, - int32_t acquireFence, int32_t dataspace, - hwc_region_t damage); - HWC2::Error setColorMode(android_color_mode_t mode); - HWC2::Error setColorTransform(android_color_transform_t hint); - HWC2::Error setOutputBuffer(buffer_handle_t buffer, - int32_t releaseFence); - HWC2::Error setPowerMode(HWC2::PowerMode mode); - HWC2::Error setVsyncEnabled(HWC2::Vsync enabled); - - // Since HWC1 "validates" (called "prepare" in HWC1) all Displays - // at once, the first call to any Display::validate() will trigger - // validate() on all other Displays in the Device. - HWC2::Error validate(uint32_t* outNumTypes, - uint32_t* outNumRequests); - - HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z); - - HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height, - int32_t format, int32_t dataspace); - - // Read configs from HWC1 device - void populateConfigs(); - - // Set configs for a virtual display - void populateConfigs(uint32_t width, uint32_t height); - - bool prepare(); - - // Called after hwc.prepare() with responses from the device. - void generateChanges(); - - bool hasChanges() const; - HWC2::Error set(hwc_display_contents_1& hwcContents); - void addRetireFence(int fenceFd); - void addReleaseFences(const hwc_display_contents_1& hwcContents); - - bool hasColorTransform() const; - - std::string dump() const; - - // Return a rect from the pool allocated during validate() - hwc_rect_t* GetRects(size_t numRects); - - hwc_display_contents_1* getDisplayContents(); - - void markGeometryChanged() { mGeometryChanged = true; } - void resetGeometryMarker() { mGeometryChanged = false;} - private: - class Config { - public: - Config(Display& display) - : mDisplay(display), - mId(0), - mAttributes() {} - - bool isOnDisplay(const Display& display) const { - return display.getId() == mDisplay.getId(); - } - - void setAttribute(HWC2::Attribute attribute, int32_t value); - int32_t getAttribute(HWC2::Attribute attribute) const; - - void setHwc1Id(uint32_t id); - bool hasHwc1Id(uint32_t id) const; - HWC2::Error getColorModeForHwc1Id(uint32_t id, - android_color_mode_t *outMode) const; - HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode, - uint32_t* outId) const; - - void setId(hwc2_config_t id) { mId = id; } - hwc2_config_t getId() const { return mId; } - - // Attempts to merge two configs that differ only in color - // mode. Returns whether the merge was successful - bool merge(const Config& other); - - std::set<android_color_mode_t> getColorModes() const; - - // splitLine divides the output into two lines suitable for - // dumpsys SurfaceFlinger - std::string toString(bool splitLine = false) const; - - private: - Display& mDisplay; - hwc2_config_t mId; - std::unordered_map<HWC2::Attribute, int32_t> mAttributes; - - // Maps from color transform to HWC1 config ID - std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids; - }; - - // Stores changes requested from the device upon calling prepare(). - // Handles change request to: - // - Layer composition type. - // - Layer hints. - class Changes { - public: - uint32_t getNumTypes() const { - return static_cast<uint32_t>(mTypeChanges.size()); - } - - uint32_t getNumLayerRequests() const { - return static_cast<uint32_t>(mLayerRequests.size()); - } - - const std::unordered_map<hwc2_layer_t, HWC2::Composition>& - getTypeChanges() const { - return mTypeChanges; - } - - const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>& - getLayerRequests() const { - return mLayerRequests; - } - - void addTypeChange(hwc2_layer_t layerId, - HWC2::Composition type) { - mTypeChanges.insert({layerId, type}); - } - - void clearTypeChanges() { mTypeChanges.clear(); } - - void addLayerRequest(hwc2_layer_t layerId, - HWC2::LayerRequest request) { - mLayerRequests.insert({layerId, request}); - } - - private: - std::unordered_map<hwc2_layer_t, HWC2::Composition> - mTypeChanges; - std::unordered_map<hwc2_layer_t, HWC2::LayerRequest> - mLayerRequests; - }; - - std::shared_ptr<const Config> - getConfig(hwc2_config_t configId) const; - - void populateColorModes(); - void initializeActiveConfig(); - - // Creates a bi-directional mapping between index in HWC1 - // prepare/set array and Layer object. Stores mapping in - // mHwc1LayerMap and also updates Layer's attribute mHwc1Id. - void assignHwc1LayerIds(); - - // Called after a response to prepare() has been received: - // Ingest composition type changes requested by the device. - void updateTypeChanges(const struct hwc_layer_1& hwc1Layer, - const Layer& layer); - - // Called after a response to prepare() has been received: - // Ingest layer hint changes requested by the device. - void updateLayerRequests(const struct hwc_layer_1& hwc1Layer, - const Layer& layer); - - // Set all fields in HWC1 comm array for layer containing the - // HWC_FRAMEBUFFER_TARGET (always the last layer). - void prepareFramebufferTarget(); - - // Display ID generator. - static std::atomic<hwc2_display_t> sNextId; - const hwc2_display_t mId; - - - HWC2On1Adapter& mDevice; - - // The state of this display should only be modified from - // SurfaceFlinger's main loop, with the exception of when dump is - // called. To prevent a bad state from crashing us during a dump - // call, all public calls into Display must acquire this mutex. - // - // It is recursive because we don't want to deadlock in validate - // (or present) when we call HWC2On1Adapter::prepareAllDisplays - // (or setAllDisplays), which calls back into Display functions - // which require locking. - mutable std::recursive_mutex mStateMutex; - - // Allocate RAM able to store all layers and rects used for - // communication with HWC1. Place allocated RAM in variable - // mHwc1RequestedContents. - void allocateRequestedContents(); - - // Array of structs exchanged between client and hwc1 device. - // Sent to device upon calling prepare(). - std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents; - private: - DeferredFence mRetireFence; - - // Will only be non-null after the Display has been validated and - // before it has been presented - std::unique_ptr<Changes> mChanges; - - int32_t mHwc1Id; - - std::vector<std::shared_ptr<Config>> mConfigs; - std::shared_ptr<const Config> mActiveConfig; - std::set<android_color_mode_t> mColorModes; - android_color_mode_t mActiveColorMode; - std::string mName; - HWC2::DisplayType mType; - HWC2::PowerMode mPowerMode; - HWC2::Vsync mVsyncEnabled; - - // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer - FencedBuffer mClientTarget; - - - FencedBuffer mOutputBuffer; - - bool mHasColorTransform; - - // All layers this Display is aware of. - std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers; - - // Mapping between layer index in array of hwc_display_contents_1* - // passed to HWC1 during validate/set and Layer object. - std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap; - - // All communication with HWC1 via prepare/set is done with one - // alloc. This pointer is pointing to a pool of hwc_rect_t. - size_t mNumAvailableRects; - hwc_rect_t* mNextAvailableRect; - - // True if any of the Layers contained in this Display have been - // updated with anything other than a buffer since last call to - // Display::set() - bool mGeometryChanged; - }; - - // Utility template calling a Display object method directly based on the - // hwc2_display_t displayId parameter. - template <typename ...Args> - static int32_t callDisplayFunction(hwc2_device_t* device, - hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...), - Args... args) { - auto display = getAdapter(device)->getDisplay(displayId); - if (!display) { - return static_cast<int32_t>(HWC2::Error::BadDisplay); - } - auto error = ((*display).*member)(std::forward<Args>(args)...); - return static_cast<int32_t>(error); - } - - template <typename MF, MF memFunc, typename ...Args> - static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId, - Args... args) { - return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc, - std::forward<Args>(args)...); - } - - static int32_t getDisplayAttributeHook(hwc2_device_t* device, - hwc2_display_t display, hwc2_config_t config, - int32_t intAttribute, int32_t* outValue) { - auto attribute = static_cast<HWC2::Attribute>(intAttribute); - return callDisplayFunction(device, display, &Display::getAttribute, - config, attribute, outValue); - } - - static int32_t setColorTransformHook(hwc2_device_t* device, - hwc2_display_t display, const float* /*matrix*/, - int32_t /*android_color_transform_t*/ intHint) { - // We intentionally throw away the matrix, because if the hint is - // anything other than IDENTITY, we have to fall back to client - // composition anyway - auto hint = static_cast<android_color_transform_t>(intHint); - return callDisplayFunction(device, display, &Display::setColorTransform, - hint); - } - - static int32_t setColorModeHook(hwc2_device_t* device, - hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) { - auto mode = static_cast<android_color_mode_t>(intMode); - return callDisplayFunction(device, display, &Display::setColorMode, - mode); - } - - static int32_t setPowerModeHook(hwc2_device_t* device, - hwc2_display_t display, int32_t intMode) { - auto mode = static_cast<HWC2::PowerMode>(intMode); - return callDisplayFunction(device, display, &Display::setPowerMode, - mode); - } - - static int32_t setVsyncEnabledHook(hwc2_device_t* device, - hwc2_display_t display, int32_t intEnabled) { - auto enabled = static_cast<HWC2::Vsync>(intEnabled); - return callDisplayFunction(device, display, &Display::setVsyncEnabled, - enabled); - } - - class Layer { - public: - explicit Layer(Display& display); - - bool operator==(const Layer& other) { return mId == other.mId; } - bool operator!=(const Layer& other) { return !(*this == other); } - - hwc2_layer_t getId() const { return mId; } - Display& getDisplay() const { return mDisplay; } - - // HWC2 Layer functions - HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence); - HWC2::Error setCursorPosition(int32_t x, int32_t y); - HWC2::Error setSurfaceDamage(hwc_region_t damage); - - // HWC2 Layer state functions - HWC2::Error setBlendMode(HWC2::BlendMode mode); - HWC2::Error setColor(hwc_color_t color); - HWC2::Error setCompositionType(HWC2::Composition type); - HWC2::Error setDataspace(android_dataspace_t dataspace); - HWC2::Error setDisplayFrame(hwc_rect_t frame); - HWC2::Error setPlaneAlpha(float alpha); - HWC2::Error setSidebandStream(const native_handle_t* stream); - HWC2::Error setSourceCrop(hwc_frect_t crop); - HWC2::Error setTransform(HWC2::Transform transform); - HWC2::Error setVisibleRegion(hwc_region_t visible); - HWC2::Error setZ(uint32_t z); - - HWC2::Composition getCompositionType() const { - return mCompositionType; - } - uint32_t getZ() const { return mZ; } - - void addReleaseFence(int fenceFd); - const sp<MiniFence>& getReleaseFence() const; - - void setHwc1Id(size_t id) { mHwc1Id = id; } - size_t getHwc1Id() const { return mHwc1Id; } - - // Write state to HWC1 communication struct. - void applyState(struct hwc_layer_1& hwc1Layer); - - std::string dump() const; - - std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); } - - std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); } - - // True if a layer cannot be properly rendered by the device due - // to usage of SolidColor (a.k.a BackgroundColor in HWC1). - bool hasUnsupportedBackgroundColor() { - return (mCompositionType == HWC2::Composition::SolidColor && - !mDisplay.getDevice().supportsBackgroundColor()); - } - private: - void applyCommonState(struct hwc_layer_1& hwc1Layer); - void applySolidColorState(struct hwc_layer_1& hwc1Layer); - void applySidebandState(struct hwc_layer_1& hwc1Layer); - void applyBufferState(struct hwc_layer_1& hwc1Layer); - void applyCompositionType(struct hwc_layer_1& hwc1Layer); - - static std::atomic<hwc2_layer_t> sNextId; - const hwc2_layer_t mId; - Display& mDisplay; - - FencedBuffer mBuffer; - std::vector<hwc_rect_t> mSurfaceDamage; - - HWC2::BlendMode mBlendMode; - hwc_color_t mColor; - HWC2::Composition mCompositionType; - hwc_rect_t mDisplayFrame; - float mPlaneAlpha; - const native_handle_t* mSidebandStream; - hwc_frect_t mSourceCrop; - HWC2::Transform mTransform; - std::vector<hwc_rect_t> mVisibleRegion; - - uint32_t mZ; - - DeferredFence mReleaseFence; - - size_t mHwc1Id; - bool mHasUnsupportedPlaneAlpha; - }; - - // Utility tempate calling a Layer object method based on ID parameters: - // hwc2_display_t displayId - // and - // hwc2_layer_t layerId - template <typename ...Args> - static int32_t callLayerFunction(hwc2_device_t* device, - hwc2_display_t displayId, hwc2_layer_t layerId, - HWC2::Error (Layer::*member)(Args...), Args... args) { - auto result = getAdapter(device)->getLayer(displayId, layerId); - auto error = std::get<HWC2::Error>(result); - if (error == HWC2::Error::None) { - auto layer = std::get<Layer*>(result); - error = ((*layer).*member)(std::forward<Args>(args)...); - } - return static_cast<int32_t>(error); - } - - template <typename MF, MF memFunc, typename ...Args> - static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId, - hwc2_layer_t layerId, Args... args) { - return HWC2On1Adapter::callLayerFunction(device, displayId, layerId, - memFunc, std::forward<Args>(args)...); - } - - // Layer state functions - - static int32_t setLayerBlendModeHook(hwc2_device_t* device, - hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) { - auto mode = static_cast<HWC2::BlendMode>(intMode); - return callLayerFunction(device, display, layer, - &Layer::setBlendMode, mode); - } - - static int32_t setLayerCompositionTypeHook(hwc2_device_t* device, - hwc2_display_t display, hwc2_layer_t layer, int32_t intType) { - auto type = static_cast<HWC2::Composition>(intType); - return callLayerFunction(device, display, layer, - &Layer::setCompositionType, type); - } - - static int32_t setLayerDataspaceHook(hwc2_device_t* device, - hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) { - auto dataspace = static_cast<android_dataspace_t>(intDataspace); - return callLayerFunction(device, display, layer, &Layer::setDataspace, - dataspace); - } - - static int32_t setLayerTransformHook(hwc2_device_t* device, - hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) { - auto transform = static_cast<HWC2::Transform>(intTransform); - return callLayerFunction(device, display, layer, &Layer::setTransform, - transform); - } - - static int32_t setLayerZOrderHook(hwc2_device_t* device, - hwc2_display_t display, hwc2_layer_t layer, uint32_t z) { - return callDisplayFunction(device, display, &Display::updateLayerZ, - layer, z); - } - - // Adapter internals - - void populateCapabilities(); - Display* getDisplay(hwc2_display_t id); - std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId, - hwc2_layer_t layerId); - void populatePrimary(); - - bool prepareAllDisplays(); - std::vector<struct hwc_display_contents_1*> mHwc1Contents; - HWC2::Error setAllDisplays(); - - // Callbacks - void hwc1Invalidate(); - void hwc1Vsync(int hwc1DisplayId, int64_t timestamp); - void hwc1Hotplug(int hwc1DisplayId, int connected); - - // These are set in the constructor and before any asynchronous events are - // possible - - struct hwc_composer_device_1* const mHwc1Device; - const uint8_t mHwc1MinorVersion; - bool mHwc1SupportsVirtualDisplays; - bool mHwc1SupportsBackgroundColor; - - class Callbacks; - const std::unique_ptr<Callbacks> mHwc1Callbacks; - - std::unordered_set<HWC2::Capability> mCapabilities; - - // These are only accessed from the main SurfaceFlinger thread (not from - // callbacks or dump - - std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers; - - // A HWC1 supports only one virtual display. - std::shared_ptr<Display> mHwc1VirtualDisplay; - - // These are potentially accessed from multiple threads, and are protected - // by this mutex. This needs to be recursive, since the HWC1 implementation - // can call back into the invalidate callback on the same thread that is - // calling prepare. - std::recursive_timed_mutex mStateMutex; - - struct CallbackInfo { - hwc2_callback_data_t data; - hwc2_function_pointer_t pointer; - }; - std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks; - bool mHasPendingInvalidate; - - // There is a small gap between the time the HWC1 module is started and - // when the callbacks for vsync and hotplugs are registered by the - // HWC2on1Adapter. To prevent losing events they are stored in these arrays - // and fed to the callback as soon as possible. - std::vector<std::pair<int, int64_t>> mPendingVsyncs; - std::vector<std::pair<int, int>> mPendingHotplugs; - - // Mapping between HWC1 display id and Display objects. - std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays; - - // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL, - // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects. - std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap; -}; - -} // namespace android - -#endif diff --git a/libs/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h b/libs/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h deleted file mode 100644 index 75de764d2c..0000000000 --- a/libs/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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. - */ - -#ifndef MINIFENCE_H -#define MINIFENCE_H - -#include <utils/RefBase.h> - -namespace android { - -/* MiniFence is a minimal re-implementation of Fence from libui. It exists to - * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements. - */ -class MiniFence : public LightRefBase<MiniFence> { -public: - static const sp<MiniFence> NO_FENCE; - - // Construct a new MiniFence object with an invalid file descriptor. - MiniFence(); - - // Construct a new MiniFence object to manage a given fence file descriptor. - // When the new MiniFence object is destructed the file descriptor will be - // closed. - explicit MiniFence(int fenceFd); - - // Not copyable or movable. - MiniFence(const MiniFence& rhs) = delete; - MiniFence& operator=(const MiniFence& rhs) = delete; - MiniFence(MiniFence&& rhs) = delete; - MiniFence& operator=(MiniFence&& rhs) = delete; - - // Return a duplicate of the fence file descriptor. The caller is - // responsible for closing the returned file descriptor. On error, -1 will - // be returned and errno will indicate the problem. - int dup() const; - -private: - // Only allow instantiation using ref counting. - friend class LightRefBase<MiniFence>; - ~MiniFence(); - - int mFenceFd; - -}; -} -#endif //MINIFENCE_H diff --git a/libs/hwc2onfbadapter/Android.bp b/libs/hwc2onfbadapter/Android.bp deleted file mode 100644 index 73a41f7ff4..0000000000 --- a/libs/hwc2onfbadapter/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -// 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 deleted file mode 100644 index 7c9e6518b7..0000000000 --- a/libs/hwc2onfbadapter/HWC2OnFbAdapter.cpp +++ /dev/null @@ -1,887 +0,0 @@ -/* - * 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 deleted file mode 100644 index d6272fdb17..0000000000 --- a/libs/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 |