Snap for 9679998 from cb93af3597f90db3d6b17a265c079f8cff8b26ca to sdk-release
Change-Id: I572fe564b3b14287d5a156e4e8556c52e83768e8
diff --git a/Android.mk b/Android.mk
index 85b90d7..0d84a72 100644
--- a/Android.mk
+++ b/Android.mk
@@ -168,8 +168,6 @@
endif
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -gt 28 -o $(IS_AT_LEAST_QPR1) = true && echo isApi29OrHigher),isApi29OrHigher)
- # HWC2 enabled after P
- include $(GOLDFISH_OPENGL_PATH)/system/hwc2/Android.mk
include $(GOLDFISH_OPENGL_PATH)/system/hwc3/Android.mk
# hardware codecs enabled after P
include $(GOLDFISH_OPENGL_PATH)/system/codecs/omx/common/Android.mk
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d2b5bc5..6c93d75 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@
# instead run make from .../device/generic/goldfish-opengl
# which will re-generate this file.
set(GOLDFISH_DEVICE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
-android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/./Android.mk" "a7f2bf82c02bcd8425a99a5c3352ca058377e5be625c6c1bcdf24bd2c80e130d")
+android_validate_sha256("${GOLDFISH_DEVICE_ROOT}/./Android.mk" "08a6f473dc2359222325c2e132462a6f3fd518cf535723b835523e23af207de9")
add_subdirectory(shared/qemupipe)
add_subdirectory(shared/gralloc_cb)
add_subdirectory(shared/GoldfishAddressSpace)
diff --git a/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl
index af46444..7ce17a9 100644
--- a/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_android.impl
@@ -180,9 +180,6 @@
bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size)
{
- ALOGD("%s: Ask for block of size 0x%llx\n", __func__,
- (unsigned long long)size);
-
destroy();
if (!provider->is_opened()) {
@@ -203,20 +200,12 @@
m_handle = provider->m_handle;
m_is_shared_mapping = false;
- ALOGD("%s: ioctl allocate returned offset 0x%llx size 0x%llx\n", __func__,
- (unsigned long long)m_offset,
- (unsigned long long)m_size);
-
return true;
}
}
bool GoldfishAddressSpaceBlock::claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size)
{
- ALOGD("%s: Ask to claim region [0x%llx 0x%llx]\n", __func__,
- (unsigned long long)offset,
- (unsigned long long)offset + size);
-
destroy();
if (!provider->is_opened()) {
diff --git a/shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl
index ebf2538..c09c60e 100644
--- a/shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_fuchsia.impl
@@ -119,9 +119,6 @@
bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size)
{
- ALOGD("%s: Ask for block of size 0x%llx\n", __func__,
- (unsigned long long)size);
-
destroy();
if (!provider->is_opened()) {
@@ -141,12 +138,8 @@
m_size = size;
m_offset = 0;
m_is_shared_mapping = false;
-
- ALOGD("%s: allocate returned offset 0x%llx size 0x%llx\n", __func__,
- (unsigned long long)m_offset,
- (unsigned long long)m_size);
-
m_driver = &provider->m_child_driver;
+
return true;
}
diff --git a/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl b/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl
index d1fa4a3..e4283c7 100644
--- a/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl
+++ b/shared/GoldfishAddressSpace/include/goldfish_address_space_host.impl
@@ -108,9 +108,6 @@
bool GoldfishAddressSpaceBlock::allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size)
{
- ALOGD("%s: Ask for block of size 0x%llx\n", __func__,
- (unsigned long long)size);
-
destroy();
if (!provider->is_opened()) {
@@ -129,10 +126,6 @@
bool GoldfishAddressSpaceBlock::claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size)
{
- ALOGD("%s: Ask to claim region [0x%llx 0x%llx]\n", __func__,
- (unsigned long long)offset,
- (unsigned long long)offset + size);
-
destroy();
if (!provider->is_opened()) {
diff --git a/system/GLESv2_enc/IOStream2.cpp b/system/GLESv2_enc/IOStream2.cpp
index 4890852..cf292ea 100644
--- a/system/GLESv2_enc/IOStream2.cpp
+++ b/system/GLESv2_enc/IOStream2.cpp
@@ -39,12 +39,10 @@
readback(&paddingToDiscard[0], startOffset);
readback((char*)pixels + startOffset, pixelDataSize - startOffset);
} else {
- int totalReadback = 0;
if (startOffset > 0) {
std::vector<char> paddingToDiscard(startOffset, 0);
readback(&paddingToDiscard[0], startOffset);
- totalReadback += startOffset;
}
// need to read back row by row
size_t paddingSize = totalRowSize - pixelRowSize;
@@ -58,15 +56,11 @@
std::vector<char> rowSlackToDiscard(rowSlack, 0);
readback(start, width * bpp);
readback(&rowSlackToDiscard[0], rowSlack);
- totalReadback += pixelRowSize;
readback(&paddingToDiscard[0], paddingSize);
- totalReadback += paddingSize;
start += totalRowSize;
} else {
readback(start, pixelRowSize);
- totalReadback += pixelRowSize;
readback(&paddingToDiscard[0], paddingSize);
- totalReadback += paddingSize;
start += totalRowSize;
}
}
@@ -105,12 +99,10 @@
writeFully(&paddingToDiscard[0], startOffset);
writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
} else {
- int totalReadback = 0;
if (startOffset > 0) {
std::vector<char> paddingToDiscard(startOffset, 0);
writeFully(&paddingToDiscard[0], startOffset);
- totalReadback += startOffset;
}
// need to upload row by row
size_t paddingSize = totalRowSize - pixelRowSize;
@@ -124,15 +116,11 @@
std::vector<char> rowSlackToDiscard(rowSlack, 0);
writeFully(start, width * bpp);
writeFully(&rowSlackToDiscard[0], rowSlack);
- totalReadback += pixelRowSize;
writeFully(&paddingToDiscard[0], paddingSize);
- totalReadback += paddingSize;
start += totalRowSize;
} else {
writeFully(start, pixelRowSize);
- totalReadback += pixelRowSize;
writeFully(&paddingToDiscard[0], paddingSize);
- totalReadback += paddingSize;
start += totalRowSize;
}
}
@@ -161,14 +149,12 @@
ctx->state()->pixelDataSize(
width, height, depth, format, type, 0 /* is unpack */);
- size_t sent = 0;
if (startOffset == 0 &&
pixelRowSize == totalRowSize &&
pixelImageSize == totalImageSize) {
// fast path
writeFully(pixels, pixelDataSize);
- sent += pixelDataSize;
} else if (pixelRowSize == totalRowSize &&
pixelImageSize == totalImageSize &&
pixelRowSize == (width * bpp)) {
@@ -176,14 +162,11 @@
std::vector<char> paddingToDiscard(startOffset, 0);
writeFully(&paddingToDiscard[0], startOffset);
writeFully((char*)pixels + startOffset, pixelDataSize - startOffset);
- sent += pixelDataSize;
} else {
- int totalReadback = 0;
if (startOffset > 0) {
std::vector<char> paddingToDiscard(startOffset, 0);
writeFully(&paddingToDiscard[0], startOffset);
- totalReadback += startOffset;
}
// need to upload row by row
size_t paddingSize = totalRowSize - pixelRowSize;
@@ -202,22 +185,17 @@
if (pixelRowSize != width * bpp) {
writeFully(start, width * bpp);
writeFully(&rowSlackToDiscard[0], rowSlack);
- totalReadback += pixelRowSize;
writeFully(&paddingToDiscard[0], paddingSize);
- totalReadback += paddingSize;
start += totalRowSize;
} else {
writeFully(start, pixelRowSize);
- totalReadback += pixelRowSize;
writeFully(&paddingToDiscard[0], paddingSize);
- totalReadback += paddingSize;
start += totalRowSize;
}
}
if (imageSlack > 0) {
writeFully(&imageSlackToDiscard[0], imageSlack);
start += imageSlack;
- totalReadback += imageSlack;
}
}
}
diff --git a/system/OpenglSystemCommon/AddressSpaceStream.cpp b/system/OpenglSystemCommon/AddressSpaceStream.cpp
index e012c52..23c6d7f 100644
--- a/system/OpenglSystemCommon/AddressSpaceStream.cpp
+++ b/system/OpenglSystemCommon/AddressSpaceStream.cpp
@@ -610,10 +610,8 @@
ensureType1Finished();
size_t actuallyRead = 0;
- size_t readIters = 0;
while (!actuallyRead) {
- ++readIters;
uint32_t readAvail =
ring_buffer_available_read(
diff --git a/system/OpenglSystemCommon/HostConnection.cpp b/system/OpenglSystemCommon/HostConnection.cpp
index cac7ed7..d42ecf4 100644
--- a/system/OpenglSystemCommon/HostConnection.cpp
+++ b/system/OpenglSystemCommon/HostConnection.cpp
@@ -593,9 +593,6 @@
*pClientFlags = 0;
con->m_stream->commitBuffer(sizeof(unsigned int));
- DPRINT("HostConnection::get() New Host Connection established %p, tid %lu\n", con.get(),
- getCurrentThreadId());
-
#if defined(__linux__) || defined(__ANDROID__)
auto rcEnc = con->rcEncoder();
if (rcEnc != nullptr) {
@@ -654,7 +651,6 @@
// static
std::unique_ptr<HostConnection> HostConnection::createUnique(uint32_t capset_id) {
- DPRINT("%s: call\n", __func__);
return connect(capset_id);
}
diff --git a/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp b/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp
index 380732b..03bbbb2 100644
--- a/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp
+++ b/system/codecs/omx/vpxdec/goldfish_vpx_impl.cpp
@@ -110,7 +110,7 @@
}
//TODO: we might not need to do the putting all the time
-vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t* ctx, int hostColorBufferId) {
+vpx_image_t* vpx_codec_get_frame(vpx_codec_ctx_t* ctx, __attribute__((unused)) int hostColorBufferId) {
DDD("%s %d %p", __func__, __LINE__);
if (!ctx) {
ALOGE("ERROR: Failed %s %d: ctx is nullptr", __func__, __LINE__);
@@ -156,7 +156,7 @@
const uint8_t* data,
unsigned int data_sz,
void* user_priv,
- long deadline) {
+ __attribute__((unused)) long deadline) {
if (!ctx) {
ALOGE("ERROR: Failed %s %d: ctx is nullptr", __func__, __LINE__);
return -1;
diff --git a/system/egl/egl.cpp b/system/egl/egl.cpp
index cc31186..5d193bf 100644
--- a/system/egl/egl.cpp
+++ b/system/egl/egl.cpp
@@ -984,7 +984,6 @@
// find the number of extensions
int extStart = 0;
int extEnd = 0;
- int currentExtIndex = 0;
if (sWantES30OrAbove(hostStr) &&
!strstr(hostStr, kOESEGLImageExternalEssl3)) {
@@ -996,7 +995,6 @@
if (hostStr[extEnd] == ' ') {
int extSz = extEnd - extStart;
res.push_back(std::string(hostStr + extStart, extSz));
- currentExtIndex++;
extStart = extEnd + 1;
}
extEnd++;
diff --git a/system/hals/Android.mk b/system/hals/Android.mk
index 06fdc21..ee00507 100644
--- a/system/hals/Android.mk
+++ b/system/hals/Android.mk
@@ -17,14 +17,15 @@
include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.graphics.allocator@3.0-service
+LOCAL_MODULE := android.hardware.graphics.allocator@3.0-service.ranchu
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
LOCAL_LICENSE_CONDITIONS := notice
LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../LICENSE
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_VENDOR_MODULE := true
LOCAL_SRC_FILES := allocator3.cpp
-LOCAL_INIT_RC := android.hardware.graphics.allocator@3.0-service.rc
+LOCAL_INIT_RC := android.hardware.graphics.allocator@3.0-service.ranchu.rc
+LOCAL_VINTF_FRAGMENTS := android.hardware.graphics.gralloc3.ranchu.xml
LOCAL_SHARED_LIBRARIES += \
android.hardware.graphics.allocator@3.0 \
diff --git a/system/hals/android.hardware.graphics.allocator@3.0-service.rc b/system/hals/android.hardware.graphics.allocator@3.0-service.ranchu.rc
similarity index 72%
rename from system/hals/android.hardware.graphics.allocator@3.0-service.rc
rename to system/hals/android.hardware.graphics.allocator@3.0-service.ranchu.rc
index 8b9e13a..f874b14 100644
--- a/system/hals/android.hardware.graphics.allocator@3.0-service.rc
+++ b/system/hals/android.hardware.graphics.allocator@3.0-service.ranchu.rc
@@ -1,7 +1,6 @@
-service vendor.gralloc-3-0 /vendor/bin/hw/android.hardware.graphics.allocator@3.0-service
+service vendor.gralloc-3-0 /vendor/bin/hw/android.hardware.graphics.allocator@3.0-service.ranchu
interface android.hardware.graphics.allocator@3.0::IAllocator default
class hal animation
- interface android.hardware.graphics.allocator@3.0::IAllocator default
user system
group graphics drmrpc
capabilities SYS_NICE
diff --git a/system/hals/android.hardware.graphics.gralloc3.ranchu.xml b/system/hals/android.hardware.graphics.gralloc3.ranchu.xml
new file mode 100644
index 0000000..f3e7d3b
--- /dev/null
+++ b/system/hals/android.hardware.graphics.gralloc3.ranchu.xml
@@ -0,0 +1,20 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.graphics.allocator</name>
+ <transport>hwbinder</transport>
+ <version>3.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl">
+ <name>android.hardware.graphics.mapper</name>
+ <transport arch="32+64">passthrough</transport>
+ <version>3.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/system/hals/mapper3.cpp b/system/hals/mapper3.cpp
index 9848809..46956d6 100644
--- a/system/hals/mapper3.cpp
+++ b/system/hals/mapper3.cpp
@@ -131,12 +131,6 @@
RETURN_ERROR(Error3::BAD_BUFFER);
}
- if (cb->hostHandle) {
- const HostConnectionSession conn = getHostConnectionSession();
- ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
- rcEnc->rcCloseColorBuffer(rcEnc, cb->hostHandle);
- }
-
if (cb->mmapedSize > 0) {
GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
}
@@ -258,16 +252,26 @@
cb->setBufferPtr(ptr);
}
- if (cb->hostHandle) {
- const HostConnectionSession conn = getHostConnectionSession();
- ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
- rcEnc->rcOpenColorBuffer2(rcEnc, cb->hostHandle);
- }
-
*phandle = imported;
RETURN(Error3::NONE);
}
+ void setLocked(cb_handle_30_t* cb, const uint8_t checkedUsage,
+ const Rect& accessRegion) {
+ if (checkedUsage & BufferUsage::CPU_WRITE_MASK) {
+ cb->lockedLeft = accessRegion.left;
+ cb->lockedTop = accessRegion.top;
+ cb->lockedWidth = accessRegion.width;
+ cb->lockedHeight = accessRegion.height;
+ } else {
+ cb->lockedLeft = 0;
+ cb->lockedTop = 0;
+ cb->lockedWidth = cb->width;
+ cb->lockedHeight = cb->height;
+ }
+ cb->lockedUsage = checkedUsage;
+ }
+
Error3 lockImpl(void* raw,
const uint64_t uncheckedUsage,
const Rect& accessRegion,
@@ -308,6 +312,8 @@
}
}
+ setLocked(cb, checkedUsage, accessRegion);
+
*pptr = bufferBits;
*pBytesPerPixel = cb->bytesPerPixel;
*pBytesPerStride = cb->bytesPerPixel * cb->stride;
@@ -396,6 +402,8 @@
}
}
+ setLocked(cb, checkedUsage, accessRegion);
+
pYcbcr->y = bufferBits;
pYcbcr->cb = bufferBits + uOffset;
pYcbcr->cr = bufferBits + vOffset;
@@ -492,19 +500,6 @@
}
}
- if (checkedUsage & BufferUsage::CPU_WRITE_MASK) {
- cb.lockedLeft = accessRegion.left;
- cb.lockedTop = accessRegion.top;
- cb.lockedWidth = accessRegion.width;
- cb.lockedHeight = accessRegion.height;
- } else {
- cb.lockedLeft = 0;
- cb.lockedTop = 0;
- cb.lockedWidth = cb.width;
- cb.lockedHeight = cb.height;
- }
- cb.lockedUsage = checkedUsage;
-
RETURN(Error3::NONE);
}
@@ -532,6 +527,12 @@
unlockHostImpl(*cb, bufferBits);
}
+ cb->lockedLeft = 0;
+ cb->lockedTop = 0;
+ cb->lockedWidth = 0;
+ cb->lockedHeight = 0;
+ cb->lockedUsage = 0;
+
RETURN(Error3::NONE);
}
@@ -579,12 +580,6 @@
}
}
}
-
- cb.lockedLeft = 0;
- cb.lockedTop = 0;
- cb.lockedWidth = 0;
- cb.lockedHeight = 0;
- cb.lockedUsage = 0;
}
/* BufferUsage bits that must be zero */
diff --git a/system/hwc2/Android.mk b/system/hwc2/Android.mk
deleted file mode 100644
index f2c4f25..0000000
--- a/system/hwc2/Android.mk
+++ /dev/null
@@ -1,112 +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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_VENDOR_MODULE := true
-emulator_hwcomposer_shared_libraries := \
- android.hardware.graphics.mapper@2.0 \
- android.hardware.graphics.mapper@4.0 \
- libbase \
- libEGL \
- libcutils \
- libcuttlefish_device_config \
- libcuttlefish_device_config_proto \
- libcuttlefish_utils \
- libcuttlefish_fs \
- libdrm \
- libgralloctypes \
- libhardware \
- libhidlbase \
- libjpeg \
- liblog \
- libsync \
- libui \
- libutils \
- libutils \
-
-emulator_hwcomposer_cflags += \
- -DLOG_TAG=\"hwc2\" \
- -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) \
- -DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
-
-emulator_hwcomposer_c_includes += \
- device/generic/goldfish-opengl/host/include/libOpenglRender \
- device/generic/goldfish-opengl/android-emu \
- device/generic/goldfish-opengl/shared/OpenglCodecCommon \
- device/generic/goldfish-opengl/system/OpenglSystemCommon \
- device/generic/goldfish-opengl/system/include \
- device/generic/goldfish-opengl/system/renderControl_enc \
- external/libdrm \
- system/core/libsync \
- system/core/libsync/include \
-
-emulator_hwcomposer_relative_path := hw
-
-emulator_hwcomposer2_src_files := \
- ClientComposer.cpp \
- Common.cpp \
- Device.cpp \
- Display.cpp \
- DisplayConfig.cpp \
- DisplayFinder.cpp \
- Drm.cpp \
- DrmPresenter.cpp \
- Gralloc.cpp \
- GuestComposer.cpp \
- HostComposer.cpp \
- HostUtils.cpp \
- Layer.cpp \
- NoOpComposer.cpp \
- VsyncThread.cpp \
-
-include $(CLEAR_VARS)
-
-LOCAL_VENDOR_MODULE := true
-LOCAL_STATIC_LIBRARIES := libyuv_static
-LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
-LOCAL_SHARED_LIBRARIES += libOpenglSystemCommon lib_renderControl_enc
-LOCAL_SHARED_LIBRARIES += libui
-LOCAL_SRC_FILES := $(emulator_hwcomposer2_src_files)
-LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
-LOCAL_C_INCLUDES += external/minigbm/cros_gralloc
-LOCAL_MODULE_RELATIVE_PATH := $(emulator_hwcomposer_relative_path)
-
-LOCAL_MODULE := hwcomposer.ranchu
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_VINTF_FRAGMENTS := android.hardware.graphics.composer@2.4.xml
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../LICENSE
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_VENDOR_MODULE := true
-LOCAL_SRC_FILES := drmTest.cpp
-LOCAL_SHARED_LIBRARIES := $(emulator_hwcomposer_shared_libraries)
-LOCAL_SHARED_LIBRARIES += libOpenglSystemCommon lib_renderControl_enc
-LOCAL_SHARED_LIBRARIES += libui
-LOCAL_SHARED_LIBRARIES += libdrm
-LOCAL_C_INCLUDES := $(emulator_hwcomposer_c_includes)
-LOCAL_C_INCLUDES += external/libdrm
-LOCAL_C_INCLUDES += external/minigbm/cros_gralloc
-LOCAL_MODULE := emulatorDrmTest
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../LICENSE
-include $(BUILD_EXECUTABLE)
diff --git a/system/hwc2/ClientComposer.cpp b/system/hwc2/ClientComposer.cpp
deleted file mode 100644
index ee494cd..0000000
--- a/system/hwc2/ClientComposer.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2022 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 "ClientComposer.h"
-
-#include "Device.h"
-#include "Display.h"
-#include "Drm.h"
-#include "Layer.h"
-
-namespace android {
-
-ClientComposer::ClientComposer(DrmPresenter* drmPresenter)
- : mDrmPresenter(drmPresenter) {}
-
-HWC2::Error ClientComposer::init() {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error ClientComposer::onDisplayCreate(Display* display) {
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- // Ensure created.
- mDisplayInfos.emplace(displayId, DisplayInfo{});
-
- return HWC2::Error::None;
-}
-
-HWC2::Error ClientComposer::onDisplayDestroy(Display* display) {
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- auto it = mDisplayInfos.find(displayId);
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__,
- displayId);
- return HWC2::Error::BadDisplay;
- }
-
- mDisplayInfos.erase(it);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error ClientComposer::onDisplayClientTargetSet(Display* display) {
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- auto it = mDisplayInfos.find(displayId);
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__,
- displayId);
- return HWC2::Error::BadDisplay;
- }
-
- DisplayInfo& displayInfo = it->second;
-
- auto [drmBufferCreateError, drmBuffer] =
- mDrmPresenter->create(display->getClientTarget().getBuffer());
- if (drmBufferCreateError != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer",
- __FUNCTION__, displayId);
- return HWC2::Error::NoResources;
- }
- displayInfo.clientTargetDrmBuffer = std::move(drmBuffer);
-
-
- return HWC2::Error::None;
-}
-
-HWC2::Error ClientComposer::onActiveConfigChange(Display*) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-};
-
-HWC2::Error ClientComposer::validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>* changes) {
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
- (void)displayId;
-
- const std::vector<Layer*>& layers = display->getOrderedLayers();
-
- for (Layer* layer : layers) {
- const auto layerId = layer->getId();
- const auto layerCompositionType = layer->getCompositionType();
-
- if (layerCompositionType != HWC2::Composition::Client) {
- (*changes)[layerId] = HWC2::Composition::Client;
- }
- }
-
- return HWC2::Error::None;
-}
-
-std::tuple<HWC2::Error, base::unique_fd> ClientComposer::presentDisplay(
- Display* display) {
- ATRACE_CALL();
-
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- auto displayInfoIt = mDisplayInfos.find(displayId);
- if (displayInfoIt == mDisplayInfos.end()) {
- ALOGE("%s: failed to find display buffers for display:%" PRIu64,
- __FUNCTION__, displayId);
- return std::make_tuple(HWC2::Error::BadDisplay, base::unique_fd());
- }
-
- DisplayInfo& displayInfo = displayInfoIt->second;
- if (!displayInfo.clientTargetDrmBuffer) {
- ALOGW("%s: display:%" PRIu64 " no client target set, nothing to present.",
- __FUNCTION__, displayId);
- return std::make_tuple(HWC2::Error::None, base::unique_fd());
- }
-
- auto clientTargetFence = display->getClientTarget().getFence();
-
- auto [error, presentFence] = mDrmPresenter->flushToDisplay(
- displayId, *displayInfo.clientTargetDrmBuffer, clientTargetFence);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to flush drm buffer" PRIu64,
- __FUNCTION__, displayId);
- return std::make_tuple(error, base::unique_fd());
- }
-
- return std::make_tuple(HWC2::Error::None, std::move(presentFence));
-}
-
-} // namespace android
\ No newline at end of file
diff --git a/system/hwc2/ClientComposer.h b/system/hwc2/ClientComposer.h
deleted file mode 100644
index 216a67e..0000000
--- a/system/hwc2/ClientComposer.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2022 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_HWC_CLIENTCOMPOSER_H
-#define ANDROID_HWC_CLIENTCOMPOSER_H
-
-#include <memory>
-#include <unordered_map>
-
-#include "Common.h"
-#include "Composer.h"
-#include "Display.h"
-#include "DrmPresenter.h"
-#include "Layer.h"
-
-namespace android {
-
-class ClientComposer : public Composer {
- public:
- ClientComposer(DrmPresenter* drmPresenter);
-
- ClientComposer(const ClientComposer&) = delete;
- ClientComposer& operator=(const ClientComposer&) = delete;
-
- ClientComposer(ClientComposer&&) = delete;
- ClientComposer& operator=(ClientComposer&&) = delete;
-
- HWC2::Error init() override;
-
- HWC2::Error onDisplayCreate(Display*) override;
-
- HWC2::Error onDisplayDestroy(Display*) override;
-
- HWC2::Error onDisplayClientTargetSet(Display*) override;
-
- HWC2::Error onActiveConfigChange(Display*) override;
-
- // Determines if this composer can compose the given layers on the given
- // display and requests changes for layers that can't not be composed.
- HWC2::Error validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- outLayerCompositionChanges) override;
-
- // Performs the actual composition of layers and presents the composed result
- // to the display.
- std::tuple<HWC2::Error, base::unique_fd> presentDisplay(
- Display* display) override;
-
- private:
- struct DisplayInfo {
- std::shared_ptr<DrmBuffer> clientTargetDrmBuffer;
- };
-
- std::unordered_map<int64_t, DisplayInfo> mDisplayInfos;
-
- DrmPresenter* mDrmPresenter = nullptr;
-};
-
-} // namespace android
-
-#endif
\ No newline at end of file
diff --git a/system/hwc2/Common.cpp b/system/hwc2/Common.cpp
deleted file mode 100644
index f33fb8d..0000000
--- a/system/hwc2/Common.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2021 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 "Common.h"
-
-#include <android-base/properties.h>
-
-bool IsCuttlefish() {
- return android::base::GetProperty("ro.product.board", "") == "cutf";
-}
-
-bool IsCuttlefishFoldable() {
- return IsCuttlefish() &&
- android::base::GetProperty("ro.product.name", "").find("foldable") !=
- std::string::npos;
-}
-
-bool IsInNoOpCompositionMode() {
- const std::string mode = ::android::base::GetProperty("ro.vendor.hwcomposer.mode", "");
- DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.mode is %s", __FUNCTION__, mode.c_str());
- return mode == "noop";
-}
-
-bool IsInClientCompositionMode() {
- const std::string mode = ::android::base::GetProperty("ro.vendor.hwcomposer.mode", "");
- DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.mode is %s", __FUNCTION__, mode.c_str());
- return mode == "client";
-}
-
-bool IsInNoOpDisplayFinderMode() {
- const std::string mode =
- ::android::base::GetProperty("ro.vendor.hwcomposer.display_finder_mode", "");
- DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.display_finder_mode is %s",
- __FUNCTION__, mode.c_str());
- return mode == "noop";
-}
-
-bool IsInDrmDisplayFinderMode() {
- const std::string mode =
- ::android::base::GetProperty("ro.vendor.hwcomposer.display_finder_mode", "");
- DEBUG_LOG("%s: sysprop ro.vendor.hwcomposer.display_finder_mode is %s",
- __FUNCTION__, mode.c_str());
- return mode == "drm";
-}
-
-bool IsClientCompositionMode() {
- return android::base::GetProperty("ro.vendor.hwcomposer.mode", "") == "client";
-}
diff --git a/system/hwc2/Common.h b/system/hwc2/Common.h
deleted file mode 100644
index 7d364cb..0000000
--- a/system/hwc2/Common.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2021 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_HWC_COMMON_H
-#define ANDROID_HWC_COMMON_H
-
-#undef LOG_TAG
-#define LOG_TAG "RanchuHwc"
-
-#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
-
-#include <android-base/logging.h>
-#include <inttypes.h>
-#include <log/log.h>
-#include <utils/Trace.h>
-
-// Uncomment to enable additional debug logging.
-//#define DEBUG_RANCHU_HWC
-
-#if defined(DEBUG_RANCHU_HWC)
-#define DEBUG_LOG ALOGE
-#else
-#define DEBUG_LOG(...) ((void)0)
-#endif
-
-#define HWC2_INCLUDE_STRINGIFICATION
-#define HWC2_USE_CPP11
-#include <hardware/hwcomposer2.h>
-#undef HWC2_INCLUDE_STRINGIFICATION
-#undef HWC2_USE_CPP11
-
-bool IsCuttlefish();
-bool IsCuttlefishFoldable();
-
-bool IsInNoOpCompositionMode();
-bool IsInClientCompositionMode();
-
-bool IsInNoOpDisplayFinderMode();
-bool IsInDrmDisplayFinderMode();
-
-#endif
diff --git a/system/hwc2/Composer.h b/system/hwc2/Composer.h
deleted file mode 100644
index f19178e..0000000
--- a/system/hwc2/Composer.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2021 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_HWC_COMPOSER_H
-#define ANDROID_HWC_COMPOSER_H
-
-#include <android-base/unique_fd.h>
-
-#include <functional>
-#include <tuple>
-#include <unordered_map>
-#include <vector>
-
-#include "Common.h"
-
-namespace android {
-class Device;
-class Display;
-
-class Composer {
- public:
- virtual ~Composer() {}
-
- using HotplugCallback = std::function<void(
- bool /*connected*/, uint32_t /*id*/, uint32_t /*width*/,
- uint32_t /*height*/, uint32_t /*dpiX*/, uint32_t /*dpiY*/,
- uint32_t /*refreshRate*/)>;
-
- virtual HWC2::Error init() = 0;
-
- virtual HWC2::Error onDisplayCreate(Display* display) = 0;
-
- virtual HWC2::Error onDisplayDestroy(Display* display) = 0;
-
- virtual HWC2::Error onDisplayClientTargetSet(Display* display) = 0;
-
- // Determines if this composer can compose the given layers and requests
- // changes for layers that can't not be composed.
- virtual HWC2::Error validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- outLayerCompositionChanges) = 0;
-
- // Performs the actual composition of layers and presents the composed result
- // to the display.
- virtual std::tuple<HWC2::Error, base::unique_fd> presentDisplay(
- Display* display) = 0;
- virtual HWC2::Error onActiveConfigChange(Display* display) = 0;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/Device.cpp b/system/hwc2/Device.cpp
deleted file mode 100644
index 5f6fb86..0000000
--- a/system/hwc2/Device.cpp
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright 2021 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 "Device.h"
-
-#include <android-base/properties.h>
-
-#include "ClientComposer.h"
-#include "DisplayFinder.h"
-#include "GuestComposer.h"
-#include "HostComposer.h"
-#include "NoOpComposer.h"
-
-namespace android {
-namespace {
-
-static bool isMinigbmFromProperty() {
- static constexpr const auto kGrallocProp = "ro.hardware.gralloc";
-
- const auto grallocProp = android::base::GetProperty(kGrallocProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, grallocProp.c_str());
-
- if (grallocProp == "minigbm") {
- ALOGD("%s: Using minigbm, in minigbm mode.\n", __FUNCTION__);
- return true;
- } else {
- ALOGD("%s: Is not using minigbm, in goldfish mode.\n", __FUNCTION__);
- return false;
- }
-}
-
-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);
-}
-
-static int CloseHook(hw_device_t* dev) {
- Device* device = Device::fromDevice(dev);
- delete device;
- return 0;
-}
-
-bool ShouldUseGuestComposer() {
- return android::base::GetProperty("ro.hardware.vulkan", "") == "pastel";
-}
-
-} // namespace
-
-Device::Device() {
- DEBUG_LOG("%s", __FUNCTION__);
-
- common.tag = HARDWARE_DEVICE_TAG;
- common.version = HWC_DEVICE_API_VERSION_2_0;
- common.close = CloseHook;
- hwc2_device_t::getCapabilities = getCapabilitiesHook;
- hwc2_device_t::getFunction = getFunctionHook;
-
- mDrmPresenter = std::make_unique<DrmPresenter>();
-}
-
-HWC2::Error Device::init() {
- DEBUG_LOG("%s", __FUNCTION__);
- bool isMinigbm = isMinigbmFromProperty();
-
- if (IsInNoOpCompositionMode()) {
- DEBUG_LOG("%s: using NoOpComposer", __FUNCTION__);
- mComposer = std::make_unique<NoOpComposer>();
- } else if (IsInClientCompositionMode()) {
- DEBUG_LOG("%s: using ClientComposer", __FUNCTION__);
- mComposer = std::make_unique<ClientComposer>(mDrmPresenter.get());
- } else if (ShouldUseGuestComposer()) {
- DEBUG_LOG("%s: using GuestComposer", __FUNCTION__);
- mComposer = std::make_unique<GuestComposer>(mDrmPresenter.get());
- } else {
- DEBUG_LOG("%s: using HostComposer", __FUNCTION__);
- mComposer = std::make_unique<HostComposer>(mDrmPresenter.get(), isMinigbm);
- }
-
- if (!IsInNoOpCompositionMode() && (ShouldUseGuestComposer() || isMinigbm)) {
- bool success = mDrmPresenter->init(
- [this](bool connected, uint32_t id, uint32_t width, uint32_t height,
- uint32_t dpiX, uint32_t dpiY, uint32_t refreshRate) {
- handleHotplug(connected, id, width, height, dpiX, dpiY, refreshRate);
- });
-
- if (!success) {
- ALOGE("%s: failed to initialize DrmPresenter", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- }
-
- HWC2::Error error = mComposer->init();
-
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize Composer", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- return HWC2::Error::None;
-}
-
-Device::~Device() {
- DEBUG_LOG("%s", __FUNCTION__);
-
- HWC2::Error error = HWC2::Error::None;
-
- error = destroyDisplays();
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to destroy displays", __FUNCTION__);
- }
-}
-
-HWC2::Error Device::createDisplays() {
- DEBUG_LOG("%s", __FUNCTION__);
-
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- if (!mComposer) {
- ALOGE("%s composer not initialized!", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- std::vector<DisplayMultiConfigs> displays;
-
- HWC2::Error error = findDisplays(mDrmPresenter.get(), &displays);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to find display configs", __FUNCTION__);
- return error;
- }
-
- for (const auto& iter : displays) {
- error = createDisplay(iter.displayId, iter.activeConfigId, iter.configs);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to create display from config", __FUNCTION__);
- return error;
- }
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Device::createDisplay(hwc2_display_t displayId,
- hwc2_config_t activeConfigId,
- const std::vector<DisplayConfig>& configs) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- if (!mComposer) {
- ALOGE("%s composer not initialized!", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- auto display = std::make_unique<Display>(mComposer.get(), displayId);
- if (display == nullptr) {
- ALOGE("%s failed to allocate display", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- HWC2::Error error = display->init(configs, activeConfigId);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize display:%" PRIu64, __FUNCTION__, displayId);
- return error;
- }
-
- error = mComposer->onDisplayCreate(display.get());
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to register display:%" PRIu64 " with composer",
- __FUNCTION__, displayId);
- return error;
- }
-
- DEBUG_LOG("%s: adding display:%" PRIu64, __FUNCTION__, displayId);
- mDisplays.emplace(displayId, std::move(display));
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Device::destroyDisplays() {
- DEBUG_LOG("%s", __FUNCTION__);
-
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- if (!mComposer) {
- ALOGE("%s composer not initialized!", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- for (auto& [displayId, displayPtr] : mDisplays) {
- HWC2::Error error = mComposer->onDisplayDestroy(displayPtr.get());
- if (error != HWC2::Error::None) {
- ALOGE("%s composer failed to destroy displays", __FUNCTION__);
- return error;
- }
-
- displayPtr.reset();
- }
-
- mDisplays.clear();
-
- return HWC2::Error::None;
-}
-
-void Device::getCapabilities(uint32_t* outCount, int32_t* outCapabilities) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- if (outCapabilities == nullptr) {
- *outCount = mCapabilities.size();
- return;
- }
-
- auto capabilityIter = mCapabilities.cbegin();
- for (size_t i = 0; i < *outCount; ++i) {
- if (capabilityIter == mCapabilities.cend()) {
- return;
- }
- outCapabilities[i] = static_cast<int32_t>(*capabilityIter);
- ++capabilityIter;
- }
-}
-
-/*static*/
-void Device::getCapabilitiesHook(hwc2_device_t* dev, uint32_t* outCount,
- int32_t* outCapabilities) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- Device* device = Device::fromDevice(dev);
- device->getCapabilities(outCount, outCapabilities);
-}
-
-hwc2_function_pointer_t Device::getFunction(int32_t desc) {
- const auto func = static_cast<HWC2::FunctionDescriptor>(desc);
- const auto funcString = to_string(func);
- DEBUG_LOG("%s(%s)", __FUNCTION__, funcString.c_str());
-
- switch (func) {
- // Device functions.
- case HWC2::FunctionDescriptor::CreateVirtualDisplay:
- return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
- DeviceHook<int32_t, decltype(&Device::createVirtualDisplay),
- &Device::createVirtualDisplay, uint32_t, uint32_t,
- int32_t*, hwc2_display_t*>);
- case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
- return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
- DeviceHook<int32_t, decltype(&Device::destroyVirtualDisplay),
- &Device::destroyVirtualDisplay, hwc2_display_t>);
- case HWC2::FunctionDescriptor::Dump:
- return asFP<HWC2_PFN_DUMP>(DeviceHook<void, decltype(&Device::dump),
- &Device::dump, uint32_t*, char*>);
- case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
- return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
- DeviceHook<uint32_t, decltype(&Device::getMaxVirtualDisplayCount),
- &Device::getMaxVirtualDisplayCount>);
- case HWC2::FunctionDescriptor::RegisterCallback:
- return asFP<HWC2_PFN_REGISTER_CALLBACK>(
- DeviceHook<int32_t, decltype(&Device::registerCallback),
- &Device::registerCallback, int32_t, hwc2_callback_data_t,
- hwc2_function_pointer_t>);
-
- // Display functions
- case HWC2::FunctionDescriptor::AcceptDisplayChanges:
- return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
- displayHook<decltype(&Display::acceptChanges),
- &Display::acceptChanges>);
- case HWC2::FunctionDescriptor::CreateLayer:
- return asFP<HWC2_PFN_CREATE_LAYER>(
- displayHook<decltype(&Display::createLayer), &Display::createLayer,
- hwc2_layer_t*>);
- case HWC2::FunctionDescriptor::DestroyLayer:
- return asFP<HWC2_PFN_DESTROY_LAYER>(
- displayHook<decltype(&Display::destroyLayer), &Display::destroyLayer,
- hwc2_layer_t>);
- case HWC2::FunctionDescriptor::GetActiveConfig:
- return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
- displayHook<decltype(&Display::getActiveConfig),
- &Display::getActiveConfig, hwc2_config_t*>);
- case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
- return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
- displayHook<decltype(&Display::getChangedCompositionTypes),
- &Display::getChangedCompositionTypes, uint32_t*,
- hwc2_layer_t*, int32_t*>);
- case HWC2::FunctionDescriptor::GetColorModes:
- return asFP<HWC2_PFN_GET_COLOR_MODES>(
- displayHook<decltype(&Display::getColorModes),
- &Display::getColorModes, uint32_t*, int32_t*>);
- case HWC2::FunctionDescriptor::GetDisplayAttribute:
- return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
- displayHook<decltype(&Display::getDisplayAttribute),
- &Display::getDisplayAttribute, hwc2_config_t, int32_t,
- int32_t*>);
- case HWC2::FunctionDescriptor::GetDisplayConfigs:
- return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
- displayHook<decltype(&Display::getConfigs), &Display::getConfigs,
- uint32_t*, hwc2_config_t*>);
- case HWC2::FunctionDescriptor::GetDisplayName:
- return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
- displayHook<decltype(&Display::getName), &Display::getName, uint32_t*,
- char*>);
- case HWC2::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 HWC2::FunctionDescriptor::GetDisplayType:
- return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
- displayHook<decltype(&Display::getType), &Display::getType,
- int32_t*>);
- case HWC2::FunctionDescriptor::GetDozeSupport:
- return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
- displayHook<decltype(&Display::getDozeSupport),
- &Display::getDozeSupport, int32_t*>);
- case HWC2::FunctionDescriptor::GetHdrCapabilities:
- return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
- displayHook<decltype(&Display::getHdrCapabilities),
- &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
- float*, float*>);
- case HWC2::FunctionDescriptor::GetReleaseFences:
- return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
- displayHook<decltype(&Display::getReleaseFences),
- &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
- int32_t*>);
- case HWC2::FunctionDescriptor::PresentDisplay:
- return asFP<HWC2_PFN_PRESENT_DISPLAY>(
- displayHook<decltype(&Display::present), &Display::present,
- int32_t*>);
- case HWC2::FunctionDescriptor::SetActiveConfig:
- return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
- displayHook<decltype(&Display::setActiveConfig),
- &Display::setActiveConfig, hwc2_config_t>);
- case HWC2::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 HWC2::FunctionDescriptor::SetColorMode:
- return asFP<HWC2_PFN_SET_COLOR_MODE>(
- displayHook<decltype(&Display::setColorMode), &Display::setColorMode,
- int32_t>);
- case HWC2::FunctionDescriptor::SetColorTransform:
- return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(
- displayHook<decltype(&Display::setColorTransform),
- &Display::setColorTransform, const float*, int32_t>);
- case HWC2::FunctionDescriptor::SetOutputBuffer:
- return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
- displayHook<decltype(&Display::setOutputBuffer),
- &Display::setOutputBuffer, buffer_handle_t, int32_t>);
- case HWC2::FunctionDescriptor::SetPowerMode:
- return asFP<HWC2_PFN_SET_POWER_MODE>(
- displayHook<decltype(&Display::setPowerMode), &Display::setPowerMode,
- int32_t>);
- case HWC2::FunctionDescriptor::SetVsyncEnabled:
- return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(
- displayHook<decltype(&Display::setVsyncEnabled),
- &Display::setVsyncEnabled, int32_t>);
- case HWC2::FunctionDescriptor::ValidateDisplay:
- return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
- displayHook<decltype(&Display::validate), &Display::validate,
- uint32_t*, uint32_t*>);
- case HWC2::FunctionDescriptor::GetClientTargetSupport:
- return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
- displayHook<decltype(&Display::getClientTargetSupport),
- &Display::getClientTargetSupport, uint32_t, uint32_t,
- int32_t, int32_t>);
- case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
- return asFP<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
- displayHook<decltype(&Display::getDisplayIdentificationData),
- &Display::getDisplayIdentificationData, uint8_t*,
- uint32_t*, uint8_t*>);
- case HWC2::FunctionDescriptor::GetDisplayCapabilities:
- return asFP<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
- displayHook<decltype(&Display::getDisplayCapabilities),
- &Display::getDisplayCapabilities, uint32_t*, uint32_t*>);
- case HWC2::FunctionDescriptor::GetDisplayBrightnessSupport:
- return asFP<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(
- displayHook<decltype(&Display::getDisplayBrightnessSupport),
- &Display::getDisplayBrightnessSupport, bool*>);
- case HWC2::FunctionDescriptor::SetDisplayBrightness:
- return asFP<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(
- displayHook<decltype(&Display::setDisplayBrightness),
- &Display::setDisplayBrightness, float>);
- case HWC2::FunctionDescriptor::GetDisplayVsyncPeriod:
- return asFP<HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD>(
- displayHook<decltype(&Display::getDisplayVsyncPeriod),
- &Display::getDisplayVsyncPeriod, hwc2_vsync_period_t*>);
- case HWC2::FunctionDescriptor::SetActiveConfigWithConstraints:
- return asFP<HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS>(
- displayHook<decltype(&Display::setActiveConfigWithConstraints),
- &Display::setActiveConfigWithConstraints, hwc2_config_t,
- hwc_vsync_period_change_constraints_t*,
- hwc_vsync_period_change_timeline_t*>);
- case HWC2::FunctionDescriptor::GetDisplayConnectionType:
- return asFP<HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE>(
- displayHook<decltype(&Display::getDisplayConnectionType),
- &Display::getDisplayConnectionType, uint32_t*>);
- case HWC2::FunctionDescriptor::SetAutoLowLatencyMode:
- return asFP<HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE>(
- displayHook<decltype(&Display::setAutoLowLatencyMode),
- &Display::setAutoLowLatencyMode, bool>);
- case HWC2::FunctionDescriptor::GetSupportedContentTypes:
- return asFP<HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES>(
- displayHook<decltype(&Display::getSupportedContentTypes),
- &Display::getSupportedContentTypes, uint32_t*,
- uint32_t*>);
- case HWC2::FunctionDescriptor::SetContentType:
- return asFP<HWC2_PFN_SET_CONTENT_TYPE>(
- displayHook<decltype(&Display::setContentType),
- &Display::setContentType, int32_t>);
-
- // Layer functions
- case HWC2::FunctionDescriptor::SetCursorPosition:
- return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
- layerHook<decltype(&Layer::setCursorPosition),
- &Layer::setCursorPosition, int32_t, int32_t>);
- case HWC2::FunctionDescriptor::SetLayerBuffer:
- return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
- layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
- buffer_handle_t, int32_t>);
- case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
- return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
- layerHook<decltype(&Layer::setSurfaceDamage),
- &Layer::setSurfaceDamage, hwc_region_t>);
- case HWC2::FunctionDescriptor::SetLayerBlendMode:
- return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
- layerHook<decltype(&Layer::setBlendMode), &Layer::setBlendMode,
- int32_t>);
- case HWC2::FunctionDescriptor::SetLayerColor:
- return asFP<HWC2_PFN_SET_LAYER_COLOR>(
- layerHook<decltype(&Layer::setColor), &Layer::setColor, hwc_color_t>);
- case HWC2::FunctionDescriptor::SetLayerCompositionType:
- return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
- layerHook<decltype(&Layer::setCompositionType),
- &Layer::setCompositionType, int32_t>);
- case HWC2::FunctionDescriptor::SetLayerDataspace:
- return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(
- layerHook<decltype(&Layer::setDataspace), &Layer::setDataspace,
- int32_t>);
- case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
- return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
- layerHook<decltype(&Layer::setDisplayFrame), &Layer::setDisplayFrame,
- hwc_rect_t>);
- case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
- return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
- layerHook<decltype(&Layer::setPlaneAlpha), &Layer::setPlaneAlpha,
- float>);
- case HWC2::FunctionDescriptor::SetLayerSidebandStream:
- return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
- layerHook<decltype(&Layer::setSidebandStream),
- &Layer::setSidebandStream, const native_handle_t*>);
- case HWC2::FunctionDescriptor::SetLayerSourceCrop:
- return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
- layerHook<decltype(&Layer::setSourceCrop), &Layer::setSourceCrop,
- hwc_frect_t>);
- case HWC2::FunctionDescriptor::SetLayerTransform:
- return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(
- layerHook<decltype(&Layer::setTransform), &Layer::setTransform,
- int32_t>);
- case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
- return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
- layerHook<decltype(&Layer::setVisibleRegion),
- &Layer::setVisibleRegion, hwc_region_t>);
- case HWC2::FunctionDescriptor::SetLayerZOrder:
- return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(
- displayHook<decltype(&Display::updateLayerZ), &Display::updateLayerZ,
- hwc2_layer_t, uint32_t>);
-
- default:
- ALOGE("GetFunction: Unknown function descriptor: %d",
- static_cast<int32_t>(desc));
- return nullptr;
- }
-}
-
-/*static*/
-hwc2_function_pointer_t Device::getFunctionHook(hwc2_device_t* dev,
- int32_t desc) {
- Device* device = Device::fromDevice(dev);
- return device->getFunction(desc);
-}
-
-// Device functions
-
-HWC2::Error Device::createVirtualDisplay(uint32_t /*width*/,
- uint32_t /*height*/,
- int32_t* /*format*/,
- hwc2_display_t* /*outDisplay*/) {
- DEBUG_LOG("%s", __FUNCTION__);
- // TODO: VirtualDisplay support
- return HWC2::Error::None;
-}
-
-HWC2::Error Device::destroyVirtualDisplay(hwc2_display_t /*displayId*/) {
- DEBUG_LOG("%s", __FUNCTION__);
- // TODO: VirtualDisplay support
- return HWC2::Error::None;
-}
-
-void Device::dump(uint32_t* /*outSize*/, char* /*outBuffer*/) {
- DEBUG_LOG("%s", __FUNCTION__);
- // TODO:
- return;
-}
-
-uint32_t Device::getMaxVirtualDisplayCount() {
- DEBUG_LOG("%s", __FUNCTION__);
- // TODO: VirtualDisplay support
- return 0;
-}
-
-HWC2::Error Device::registerCallback(int32_t desc,
- hwc2_callback_data_t callbackData,
- hwc2_function_pointer_t callbackPointer) {
- const auto callbackType = static_cast<HWC2::Callback>(desc);
- const auto callbackTypeString = to_string(callbackType);
- DEBUG_LOG("%s callback %s", __FUNCTION__, callbackTypeString.c_str());
-
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- if (callbackPointer != nullptr) {
- mCallbacks[callbackType] = {callbackData, callbackPointer};
- } else {
- mCallbacks.erase(callbackType);
- }
-
- if (callbackType == HWC2::Callback::Vsync) {
- auto callback = reinterpret_cast<HWC2_PFN_VSYNC>(callbackPointer);
- for (const auto& [displayId, display] : mDisplays) {
- display->setVsyncCallback(callback, callbackData);
- }
- } else if (callbackType == HWC2::Callback::Vsync_2_4) {
- auto callback = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(callbackPointer);
- for (const auto& [displayId, display] : mDisplays) {
- display->setVsync24Callback(callback, callbackData);
- }
- } else if (callbackType == HWC2::Callback::Hotplug) {
- if (callbackPointer == nullptr) {
- return HWC2::Error::None;
- }
-
- // Callback without the state lock held
- lock.unlock();
- auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackPointer);
- auto hotplugConnect = static_cast<int32_t>(HWC2::Connection::Connected);
- for (const auto& [displayId, display] : mDisplays) {
- ALOGI("%s hotplug connecting display:%" PRIu64, __FUNCTION__, displayId);
- hotplug(callbackData, displayId, hotplugConnect);
- }
- } else if (callbackType == HWC2::Callback::Refresh) {
- // Not used
- } else {
- ALOGE("%s unhandled callback: %s", __FUNCTION__,
- callbackTypeString.c_str());
- return HWC2::Error::BadParameter;
- }
-
- return HWC2::Error::None;
-}
-
-bool Device::handleHotplug(bool connected, uint32_t id, uint32_t width,
- uint32_t height, uint32_t dpiX, uint32_t dpiY,
- uint32_t refreshRate) {
- std::unique_lock<std::mutex> lock(mStateMutex);
- if (mCallbacks[HWC2::Callback::Hotplug].pointer == nullptr) {
- return false;
- }
- auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(
- mCallbacks[HWC2::Callback::Hotplug].pointer);
- auto hotplugConnect = static_cast<int32_t>(HWC2::Connection::Connected);
- auto hotplugDisconnect = static_cast<int32_t>(HWC2::Connection::Disconnected);
- Display* display = getDisplay(id);
- if (display) {
- // if existed, disconnect first
- ALOGD("callback hotplugDisconnect display %" PRIu32, id);
- hotplug(mCallbacks[HWC2::Callback::Hotplug].data, id, hotplugDisconnect);
- display->lock();
- mComposer->onDisplayDestroy(display);
- display->unlock();
- }
- if (connected) {
- hwc2_display_t displayId = static_cast<hwc2_display_t>(id);
- hwc2_config_t configId = static_cast<hwc2_config_t>(id);
- std::vector<DisplayConfig> configs = {
- DisplayConfig(configId, static_cast<int>(width),
- static_cast<int>(height), static_cast<int>(dpiX),
- static_cast<int>(dpiY), static_cast<int>(refreshRate))};
- createDisplay(displayId, configId, configs);
- ALOGD("callback hotplugConnect display %" PRIu32 " width %" PRIu32
- " height %" PRIu32 " dpiX %" PRIu32 " dpiY %" PRIu32 "fps %" PRIu32,
- id, width, height, dpiX, dpiY, refreshRate);
- hotplug(mCallbacks[HWC2::Callback::Hotplug].data, id, hotplugConnect);
- };
-
- return true;
-}
-
-Display* Device::getDisplay(hwc2_display_t id) {
- auto display = mDisplays.find(id);
- if (display == mDisplays.end()) {
- ALOGW("Failed to get display for id=%d", (uint32_t)id);
- return nullptr;
- }
- return display->second.get();
-}
-
-static int OpenDevice(const struct hw_module_t* module, const char* name,
- struct hw_device_t** dev) {
- DEBUG_LOG("%s ", __FUNCTION__);
-
- if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
- ALOGE("Invalid module name- %s", name);
- return -EINVAL;
- }
-
- std::unique_ptr<Device> device = std::make_unique<Device>();
- HWC2::Error error = device->init();
- if (error != HWC2::Error::None) {
- ALOGE("%s: failed to initialize device", __FUNCTION__);
- return -EINVAL;
- }
-
- error = device->createDisplays();
- if (error != HWC2::Error::None) {
- ALOGE("%s: failed to initialize device displays.", __FUNCTION__);
- return -EINVAL;
- }
-
- device->common.module = const_cast<hw_module_t*>(module);
- *dev = &device.release()->common;
- return 0;
-}
-
-} // namespace android
-
-static struct hw_module_methods_t hwc2_module_methods = {
- .open = android::OpenDevice,
-};
-
-hw_module_t HAL_MODULE_INFO_SYM = {
- .tag = HARDWARE_MODULE_TAG,
- .version_major = 2,
- .version_minor = 4,
- .id = HWC_HARDWARE_MODULE_ID,
- .name = "goldfish HWC2 module",
- .author = "The Android Open Source Project",
- .methods = &hwc2_module_methods,
- .dso = NULL,
- .reserved = {0},
-};
diff --git a/system/hwc2/Device.h b/system/hwc2/Device.h
deleted file mode 100644
index 7361d3a..0000000
--- a/system/hwc2/Device.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2021 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_HWC_DEVICE_H
-#define ANDROID_HWC_DEVICE_H
-
-#include <atomic>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "Common.h"
-#include "Composer.h"
-#include "Display.h"
-#include "DrmPresenter.h"
-#include "Layer.h"
-
-namespace android {
-
-class Composer;
-class Display;
-
-class Device : public hwc2_device_t {
- public:
- static inline Device* fromDevice(hw_device_t* device) {
- return reinterpret_cast<Device*>(device);
- }
-
- static inline Device* fromDevice(hwc2_device_t* device) {
- return static_cast<Device*>(device);
- }
-
- Device();
- ~Device();
-
- HWC2::Error init();
-
- HWC2::Error createDisplays();
-
- HWC2::Error createDisplay(hwc2_display_t displayId,
- hwc2_config_t activeConfigId,
- const std::vector<DisplayConfig>& configs);
-
- Display* getDisplay(hwc2_display_t displayId);
-
- private:
- HWC2::Error destroyDisplays();
-
- bool handleHotplug(bool connected, uint32_t id, uint32_t width,
- uint32_t height, uint32_t dpiX, uint32_t dpiY,
- uint32_t refreshRate);
-
- void getCapabilities(uint32_t* outCount, int32_t* outCapabilities);
- static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
- int32_t* outCapabilities);
-
- hwc2_function_pointer_t getFunction(int32_t descriptor);
- static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
- int32_t descriptor);
-
- // Wrapper to call a specific function on a specific device.
- template <typename T, typename HookType, HookType func, typename... Args>
- static T DeviceHook(hwc2_device_t* dev, Args... args) {
- Device* device = Device::fromDevice(dev);
- return static_cast<T>(((*device).*func)(std::forward<Args>(args)...));
- }
-
- // Wrapper to call a specific function on a specific display.
- template <typename HookType, HookType func, typename... Args>
- static int32_t displayHook(hwc2_device_t* dev, hwc2_display_t displayId,
- Args... args) {
- Device* device = Device::fromDevice(dev);
-
- Display* display = device->getDisplay(displayId);
- if (display == nullptr) {
- return static_cast<int32_t>(HWC2::Error::BadDisplay);
- }
-
- return static_cast<int32_t>((display->*func)(std::forward<Args>(args)...));
- }
-
- // Wrapper to call a specific function on a specific layer.
- template <typename HookType, HookType func, typename... Args>
- static int32_t layerHook(hwc2_device_t* dev, hwc2_display_t displayId,
- hwc2_layer_t layerId, Args... args) {
- Device* device = Device::fromDevice(dev);
-
- Display* display = device->getDisplay(displayId);
- if (display == nullptr) {
- return static_cast<int32_t>(HWC2::Error::BadDisplay);
- }
-
- Layer* layer = display->getLayer(layerId);
- if (layer == nullptr) {
- return static_cast<int32_t>(HWC2::Error::BadLayer);
- }
-
- return static_cast<int32_t>((layer->*func)(std::forward<Args>(args)...));
- }
-
- // Device functions
- HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
- int32_t* format, hwc2_display_t* outDisplay);
-
- HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
-
- void dump(uint32_t* outSize, char* outBuffer);
-
- uint32_t getMaxVirtualDisplayCount();
-
- HWC2::Error registerCallback(int32_t descriptor,
- hwc2_callback_data_t callbackData,
- hwc2_function_pointer_t pointer);
-
- // These are potentially accessed from multiple threads, and are protected
- // by this mutex.
- std::mutex mStateMutex;
-
- std::unique_ptr<Composer> mComposer;
-
- std::unordered_set<HWC2::Capability> mCapabilities;
-
- // For sharing Vsync callback with each displays Vsync thread.
- friend class Display;
-
- struct CallbackInfo {
- hwc2_callback_data_t data;
- hwc2_function_pointer_t pointer;
- };
- std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
- std::map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
-
- std::unique_ptr<DrmPresenter> mDrmPresenter;
-};
-
-} // namespace android
-#endif
diff --git a/system/hwc2/Display.cpp b/system/hwc2/Display.cpp
deleted file mode 100644
index d5975b6..0000000
--- a/system/hwc2/Display.cpp
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * Copyright 2021 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 "Display.h"
-
-#include <android-base/unique_fd.h>
-#include <sync/sync.h>
-
-#include <atomic>
-#include <numeric>
-#include <sstream>
-
-#include "Common.h"
-#include "Device.h"
-
-namespace android {
-namespace {
-
-using android::hardware::graphics::common::V1_0::ColorTransform;
-
-bool IsValidColorMode(android_color_mode_t mode) {
- switch (mode) {
- case HAL_COLOR_MODE_NATIVE: // Fall-through
- case HAL_COLOR_MODE_STANDARD_BT601_625: // Fall-through
- case HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED: // Fall-through
- case HAL_COLOR_MODE_STANDARD_BT601_525: // Fall-through
- case HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED: // Fall-through
- case HAL_COLOR_MODE_STANDARD_BT709: // Fall-through
- case HAL_COLOR_MODE_DCI_P3: // Fall-through
- case HAL_COLOR_MODE_SRGB: // Fall-through
- case HAL_COLOR_MODE_ADOBE_RGB: // Fall-through
- case HAL_COLOR_MODE_DISPLAY_P3:
- return true;
- default:
- return false;
- }
-}
-
-bool isValidPowerMode(HWC2::PowerMode mode) {
- switch (mode) {
- case HWC2::PowerMode::Off: // Fall-through
- case HWC2::PowerMode::DozeSuspend: // Fall-through
- case HWC2::PowerMode::Doze: // Fall-through
- case HWC2::PowerMode::On:
- return true;
- default:
- return false;
- }
-}
-
-} // namespace
-
-Display::Display(Composer* composer, hwc2_display_t id)
- : mComposer(composer), mId(id), mVsyncThread(new VsyncThread(id)) {}
-
-Display::~Display() {}
-
-HWC2::Error Display::init(const std::vector<DisplayConfig>& configs,
- hwc2_config_t activeConfigId,
- const std::optional<std::vector<uint8_t>>& edid) {
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- for (const DisplayConfig& config : configs) {
- mConfigs.emplace(config.getId(), config);
- }
-
- mActiveConfigId = activeConfigId;
- mEdid = edid;
-
- auto it = mConfigs.find(activeConfigId);
- if (it == mConfigs.end()) {
- ALOGE("%s: display:%" PRIu64 "missing config:%" PRIu32, __FUNCTION__, mId,
- activeConfigId);
- return HWC2::Error::NoResources;
- }
-
- const auto& activeConfig = it->second;
- const auto activeConfigString = activeConfig.toString();
- ALOGD("%s initializing display:%" PRIu64 " with config:%s", __FUNCTION__, mId,
- activeConfigString.c_str());
-
- mVsyncThread->start(activeConfig.getVsyncPeriod());
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::updateParameters(
- uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
- uint32_t refreshRateHz, const std::optional<std::vector<uint8_t>>& edid) {
- DEBUG_LOG("%s updating display:%" PRIu64
- " width:%d height:%d dpiX:%d dpiY:%d refreshRateHz:%d",
- __FUNCTION__, mId, width, height, dpiX, dpiY, refreshRateHz);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- auto it = mConfigs.find(*mActiveConfigId);
- if (it == mConfigs.end()) {
- ALOGE("%s: failed to find config %" PRIu32, __func__, *mActiveConfigId);
- return HWC2::Error::NoResources;
- }
- it->second.setAttribute(HWC2::Attribute::VsyncPeriod,
- 1000 * 1000 * 1000 / refreshRateHz);
- it->second.setAttribute(HWC2::Attribute::Width, width);
- it->second.setAttribute(HWC2::Attribute::Height, height);
- it->second.setAttribute(HWC2::Attribute::DpiX, dpiX);
- it->second.setAttribute(HWC2::Attribute::DpiY, dpiY);
-
- mEdid = edid;
-
- return HWC2::Error::None;
-}
-
-Layer* Display::getLayer(hwc2_layer_t layerId) {
- auto it = mLayers.find(layerId);
- if (it == mLayers.end()) {
- ALOGE("%s Unknown layer:%" PRIu64, __FUNCTION__, layerId);
- return nullptr;
- }
-
- return it->second.get();
-}
-
-buffer_handle_t Display::waitAndGetClientTargetBuffer() {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- base::unique_fd fence = mClientTarget.getFence();
- if (fence.ok()) {
- int err = sync_wait(fence.get(), 3000);
- if (err < 0 && errno == ETIME) {
- ALOGE("%s waited on fence %" PRId32 " for 3000 ms", __FUNCTION__,
- fence.get());
- }
- }
-
- return mClientTarget.getBuffer();
-}
-
-HWC2::Error Display::acceptChanges() {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mChanges) {
- ALOGE("%s: display %" PRIu64 " failed, not validated", __FUNCTION__, mId);
- return HWC2::Error::NotValidated;
- }
-
- for (auto& [layerId, layerCompositionType] : mChanges->getTypeChanges()) {
- auto* layer = getLayer(layerId);
- if (layer == nullptr) {
- ALOGE("%s: display:%" PRIu64 " layer:%" PRIu64
- " dropped before AcceptChanges?",
- __FUNCTION__, mId, layerId);
- continue;
- }
-
- layer->setCompositionTypeEnum(layerCompositionType);
- }
- mChanges->clearTypeChanges();
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::createLayer(hwc2_layer_t* outLayerId) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- auto layer = std::make_unique<Layer>();
- auto layerId = layer->getId();
- DEBUG_LOG("%s created layer:%" PRIu64, __FUNCTION__, layerId);
-
- *outLayerId = layerId;
-
- mLayers.emplace(layerId, std::move(layer));
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::destroyLayer(hwc2_layer_t layerId) {
- DEBUG_LOG("%s destroy layer:%" PRIu64, __FUNCTION__, layerId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- auto it = mLayers.find(layerId);
- if (it == mLayers.end()) {
- ALOGE("%s display:%" PRIu64 " has no such layer:%." PRIu64, __FUNCTION__,
- mId, layerId);
- return HWC2::Error::BadLayer;
- }
-
- mOrderedLayers.erase(std::remove_if(mOrderedLayers.begin(), //
- mOrderedLayers.end(), //
- [layerId](Layer* layer) {
- return layer->getId() == layerId;
- }),
- mOrderedLayers.end());
-
- mLayers.erase(it);
-
- DEBUG_LOG("%s destroyed layer:%" PRIu64, __FUNCTION__, layerId);
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getActiveConfig(hwc2_config_t* outConfig) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mActiveConfigId) {
- ALOGW("%s: display:%" PRIu64 " has no active config.", __FUNCTION__, mId);
- return HWC2::Error::BadConfig;
- }
-
- *outConfig = *mActiveConfigId;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getDisplayAttributeEnum(hwc2_config_t configId,
- HWC2::Attribute attribute,
- int32_t* outValue) {
- auto attributeString = to_string(attribute);
- DEBUG_LOG("%s: display:%" PRIu64 " attribute:%s", __FUNCTION__, mId,
- attributeString.c_str());
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- auto it = mConfigs.find(configId);
- if (it == mConfigs.end()) {
- ALOGW("%s: display:%" PRIu64 "bad config:%" PRIu32, __FUNCTION__, mId,
- configId);
- return HWC2::Error::BadConfig;
- }
-
- const DisplayConfig& config = it->second;
- *outValue = config.getAttribute(attribute);
- DEBUG_LOG("%s: display:%" PRIu64 " attribute:%s value is %" PRIi32,
- __FUNCTION__, mId, attributeString.c_str(), *outValue);
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getDisplayAttribute(hwc2_config_t configId,
- int32_t attribute, int32_t* outValue) {
- return getDisplayAttributeEnum(
- configId, static_cast<HWC2::Attribute>(attribute), outValue);
-}
-
-HWC2::Error Display::getChangedCompositionTypes(uint32_t* outNumElements,
- hwc2_layer_t* outLayers,
- int32_t* outTypes) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mChanges) {
- ALOGE("%s: for display:%" PRIu64 " failed, display not validated",
- __FUNCTION__, mId);
- return HWC2::Error::NotValidated;
- }
-
- if ((outLayers == nullptr) || (outTypes == nullptr)) {
- *outNumElements = mChanges->getTypeChanges().size();
- return HWC2::Error::None;
- }
-
- uint32_t numWritten = 0;
- for (const auto& element : mChanges->getTypeChanges()) {
- if (numWritten == *outNumElements) {
- break;
- }
-
- auto layerId = element.first;
- const auto layerCompositionType = element.second;
- const auto layerCompositionTypeString = to_string(layerCompositionType);
- DEBUG_LOG("%s: display:%" PRIu64 " layer:%" PRIu64 " changed to %s",
- __FUNCTION__, mId, layerId, layerCompositionTypeString.c_str());
-
- outLayers[numWritten] = layerId;
- outTypes[numWritten] = static_cast<int32_t>(layerCompositionType);
- ++numWritten;
- }
- *outNumElements = numWritten;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getColorModes(uint32_t* outNumModes, int32_t* outModes) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!outModes) {
- *outNumModes = mColorModes.size();
- return HWC2::Error::None;
- }
-
- // we only support HAL_COLOR_MODE_NATIVE so far
- uint32_t numModes = std::min<uint32_t>(
- *outNumModes, static_cast<uint32_t>(mColorModes.size()));
- std::copy_n(mColorModes.cbegin(), numModes, outModes);
- *outNumModes = numModes;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getConfigs(uint32_t* outNumConfigs,
- hwc2_config_t* outConfigs) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!outConfigs) {
- *outNumConfigs = mConfigs.size();
- return HWC2::Error::None;
- }
-
- uint32_t numWritten = 0;
- for (const auto& [configId, config] : mConfigs) {
- if (numWritten == *outNumConfigs) {
- break;
- }
- outConfigs[numWritten] = configId;
- ++numWritten;
- }
-
- *outNumConfigs = numWritten;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getDozeSupport(int32_t* outSupport) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- // We don't support so far
- *outSupport = 0;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getHdrCapabilities(uint32_t* outNumTypes,
- int32_t* /*outTypes*/,
- float* /*outMaxLuminance*/,
- float* /*outMaxAverageLuminance*/,
- float* /*outMinLuminance*/) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- // We don't support so far
- *outNumTypes = 0;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getName(uint32_t* outSize, char* outName) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!outName) {
- *outSize = mName.size();
- return HWC2::Error::None;
- }
- auto numCopied = mName.copy(outName, *outSize);
- *outSize = numCopied;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::addReleaseFenceLocked(hwc2_layer_t layerId,
- base::unique_fd fence) {
- DEBUG_LOG("%s: display:%" PRIu64 " layer: %" PRIu64 ", fence: %d",
- __FUNCTION__, mId, static_cast<uint64_t>(layerId), fence.get());
-
- mReleaseFences[layerId] = std::move(fence);
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getReleaseFences(uint32_t* outNumElements,
- hwc2_layer_t* outLayers,
- int32_t* outFences) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- uint32_t outArraySize = *outNumElements;
-
- *outNumElements = 0;
- for (const auto& [_, releaseFence] : mReleaseFences) {
- if (releaseFence.ok()) {
- (*outNumElements)++;
- }
- }
-
- if ((!outLayers && !outFences) || (outArraySize == 0) ||
- (*outNumElements == 0)) {
- return HWC2::Error::None;
- }
- DEBUG_LOG("%s export release fences", __FUNCTION__);
-
- uint32_t index = 0;
- for (const auto& [layer_id, releaseFence] : mReleaseFences) {
- if (index >= outArraySize) {
- break;
- }
- if (!releaseFence.ok()) {
- continue;
- }
- if (outLayers) {
- outLayers[index] = layer_id;
- }
- if (outFences) {
- int outFence = dup(releaseFence.get());
- if (outFence < 0) {
- ALOGE("%s: Fail to dup release fence for display id = %" PRIu64
- ", layer id = %" PRIu64 ", fence = %d, error(%d): %s",
- __FUNCTION__, static_cast<uint64_t>(mId),
- static_cast<uint64_t>(layer_id), releaseFence.get(), errno,
- strerror(errno));
- }
- outFences[index] = outFence;
- }
- index++;
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::clearReleaseFencesAndIdsLocked() {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- mReleaseFences.clear();
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getRequests(int32_t* outDisplayRequests,
- uint32_t* outNumElements,
- hwc2_layer_t* outLayers,
- int32_t* outLayerRequests) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mChanges) {
- return HWC2::Error::NotValidated;
- }
-
- if (outLayers == nullptr || outLayerRequests == nullptr) {
- *outNumElements = mChanges->getNumLayerRequests();
- return HWC2::Error::None;
- }
-
- // TODO
- // Display requests (HWC2::DisplayRequest) are not supported so far:
- *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 HWC2::Error::None;
-}
-
-HWC2::Error Display::getType(int32_t* outType) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- *outType = (int32_t)mType;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::present(int32_t* outRetireFencePtr) {
- ATRACE_CALL();
-
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- *outRetireFencePtr = -1;
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mChanges || (mChanges->getNumTypes() > 0)) {
- ALOGE("%s: display:%" PRIu64 " failed, not validated", __FUNCTION__, mId);
- return HWC2::Error::NotValidated;
- }
- mChanges.reset();
-
- if (mComposer == nullptr) {
- ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
- return HWC2::Error::NoResources;
- }
-
- HWC2::Error error;
- base::unique_fd outRetireFence;
- std::tie(error, outRetireFence) = mComposer->presentDisplay(this);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to present", __FUNCTION__, mId);
- return error;
- }
-
- DEBUG_LOG("%s: display:%" PRIu64 " present done!", __FUNCTION__, mId);
- *outRetireFencePtr = outRetireFence.release();
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setActiveConfig(hwc2_config_t configId) {
- DEBUG_LOG("%s: display:%" PRIu64 " setting active config to %" PRIu32,
- __FUNCTION__, mId, configId);
-
- hwc_vsync_period_change_constraints_t constraints;
- constraints.desiredTimeNanos = 0;
- constraints.seamlessRequired = false;
- hwc_vsync_period_change_timeline_t timeline;
- return setActiveConfigWithConstraints(configId, &constraints, &timeline);
-}
-
-HWC2::Error Display::setClientTarget(buffer_handle_t target,
- int32_t acquireFence,
- int32_t /*dataspace*/,
- hwc_region_t /*damage*/) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
- mClientTarget.setBuffer(target);
- mClientTarget.setFence(base::unique_fd(acquireFence));
- mComposer->onDisplayClientTargetSet(this);
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setColorMode(int32_t intMode) {
- DEBUG_LOG("%s: display:%" PRIu64 " setting color mode to %" PRId32,
- __FUNCTION__, mId, intMode);
-
- auto mode = static_cast<android_color_mode_t>(intMode);
- if (!IsValidColorMode(mode)) {
- ALOGE("%s: display:%" PRIu64 " invalid color mode %" PRId32, __FUNCTION__,
- mId, intMode);
- return HWC2::Error::BadParameter;
- }
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (mColorModes.count(mode) == 0) {
- ALOGE("%s: display %" PRIu64 " mode %d not found", __FUNCTION__, mId,
- intMode);
- return HWC2::Error::Unsupported;
- }
- mActiveColorMode = mode;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setColorTransform(const float* transformMatrix,
- int transformTypeRaw) {
- const auto transformType = static_cast<ColorTransform>(transformTypeRaw);
- return setColorTransformEnum(transformMatrix, transformType);
-}
-
-HWC2::Error Display::setColorTransformEnum(const float* transformMatrix,
- ColorTransform transformType) {
- const auto transformTypeString = toString(transformType);
- DEBUG_LOG("%s: display:%" PRIu64 " color transform type %s", __FUNCTION__,
- mId, transformTypeString.c_str());
-
- if (transformType == ColorTransform::ARBITRARY_MATRIX &&
- transformMatrix == nullptr) {
- return HWC2::Error::BadParameter;
- }
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (transformType == ColorTransform::IDENTITY) {
- mColorTransform.reset();
- } else {
- ColorTransformWithMatrix& colorTransform = mColorTransform.emplace();
- colorTransform.transformType = transformType;
-
- if (transformType == ColorTransform::ARBITRARY_MATRIX) {
- auto& colorTransformMatrix = colorTransform.transformMatrixOpt.emplace();
- std::copy_n(transformMatrix, colorTransformMatrix.size(),
- colorTransformMatrix.begin());
- }
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setOutputBuffer(buffer_handle_t /*buffer*/,
- int32_t /*releaseFence*/) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
- // TODO: for virtual display
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setPowerMode(int32_t intMode) {
- auto mode = static_cast<HWC2::PowerMode>(intMode);
- auto modeString = to_string(mode);
- DEBUG_LOG("%s: display:%" PRIu64 " setting power mode to %s", __FUNCTION__,
- mId, modeString.c_str());
-
- if (!isValidPowerMode(mode)) {
- return HWC2::Error::BadParameter;
- }
-
- if (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend) {
- ALOGE("%s display %" PRIu64 " power mode %s not supported", __FUNCTION__,
- mId, modeString.c_str());
- return HWC2::Error::Unsupported;
- }
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (IsCuttlefish()) {
- if (int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); fd != -1) {
- std::ostringstream stream;
- stream << "VIRTUAL_DEVICE_DISPLAY_POWER_MODE_CHANGED display=" << mId
- << " mode=" << modeString;
- std::string message = stream.str();
- write(fd, message.c_str(), message.length());
- close(fd);
- }
- }
-
- mPowerMode = mode;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setVsyncEnabled(int32_t intEnable) {
- auto enable = static_cast<HWC2::Vsync>(intEnable);
- auto enableString = to_string(enable);
- DEBUG_LOG("%s: display:%" PRIu64 " setting vsync to %s", __FUNCTION__, mId,
- enableString.c_str());
-
- if (enable == HWC2::Vsync::Invalid) {
- return HWC2::Error::BadParameter;
- }
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
- return mVsyncThread->setVsyncEnabled(enable == HWC2::Vsync::Enable);
-}
-
-HWC2::Error Display::setVsyncCallback(HWC2_PFN_VSYNC callback,
- hwc2_callback_data_t data) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- return mVsyncThread->setVsyncCallback(callback, data);
-}
-
-HWC2::Error Display::setVsync24Callback(HWC2_PFN_VSYNC_2_4 callback,
- hwc2_callback_data_t data) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- return mVsyncThread->setVsync24Callback(callback, data);
-}
-
-HWC2::Error Display::getDisplayVsyncPeriod(
- hwc2_vsync_period_t* outVsyncPeriod) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mActiveConfigId) {
- ALOGE("%s : display:%" PRIu64 " no active config", __FUNCTION__, mId);
- return HWC2::Error::BadConfig;
- }
-
- const auto it = mConfigs.find(*mActiveConfigId);
- if (it == mConfigs.end()) {
- ALOGE("%s : display:%" PRIu64 " failed to find active config:%" PRIu32,
- __FUNCTION__, mId, *mActiveConfigId);
- return HWC2::Error::BadConfig;
- }
- const DisplayConfig& activeConfig = it->second;
-
- *outVsyncPeriod = static_cast<hwc2_vsync_period_t>(
- activeConfig.getAttribute(HWC2::Attribute::VsyncPeriod));
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests) {
- ATRACE_CALL();
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- mOrderedLayers.clear();
- mOrderedLayers.reserve(mLayers.size());
- for (auto& [_, layerPtr] : mLayers) {
- mOrderedLayers.push_back(layerPtr.get());
- }
-
- std::sort(mOrderedLayers.begin(), mOrderedLayers.end(),
- [](const Layer* layerA, const Layer* layerB) {
- const auto zA = layerA->getZ();
- const auto zB = layerB->getZ();
- if (zA != zB) {
- return zA < zB;
- }
- return layerA->getId() < layerB->getId();
- });
-
- if (!mChanges) {
- mChanges.reset(new Changes);
- } else {
- ALOGE("Validate was called more than once!");
- }
-
- if (mComposer == nullptr) {
- ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
- return HWC2::Error::NoResources;
- }
-
- std::unordered_map<hwc2_layer_t, HWC2::Composition> changes;
-
- HWC2::Error error = mComposer->validateDisplay(this, &changes);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to validate", __FUNCTION__, mId);
- return error;
- }
-
- for (const auto& [layerId, changedCompositionType] : changes) {
- mChanges->addTypeChange(layerId, changedCompositionType);
- }
-
- *outNumTypes = mChanges->getNumTypes();
- *outNumRequests = mChanges->getNumLayerRequests();
- return *outNumTypes > 0 ? HWC2::Error::HasChanges : HWC2::Error::None;
-}
-
-HWC2::Error Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
- DEBUG_LOG("%s: display:%" PRIu64 " update layer:%" PRIu64 " z:%d",
- __FUNCTION__, mId, layerId, z);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- const auto layerIt = mLayers.find(layerId);
- if (layerIt == mLayers.end()) {
- ALOGE("%s failed to find layer %" PRIu64, __FUNCTION__, layerId);
- return HWC2::Error::BadLayer;
- }
-
- auto& layer = layerIt->second;
- layer->setZ(z);
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getClientTargetSupport(uint32_t width, uint32_t height,
- int32_t format, int32_t dataspace) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (!mActiveConfigId) {
- return HWC2::Error::Unsupported;
- }
-
- const auto it = mConfigs.find(*mActiveConfigId);
- if (it == mConfigs.end()) {
- ALOGE("%s failed to find active config:%" PRIu32, __FUNCTION__,
- *mActiveConfigId);
- return HWC2::Error::Unsupported;
- }
-
- const DisplayConfig& activeConfig = it->second;
- const uint32_t activeConfigWidth =
- static_cast<uint32_t>(activeConfig.getAttribute(HWC2::Attribute::Width));
- const uint32_t activeConfigHeight =
- static_cast<uint32_t>(activeConfig.getAttribute(HWC2::Attribute::Height));
- if (width == activeConfigWidth && height == activeConfigHeight &&
- format == HAL_PIXEL_FORMAT_RGBA_8888 &&
- dataspace == HAL_DATASPACE_UNKNOWN) {
- return HWC2::Error::None;
- }
-
- return HWC2::Error::None;
-}
-
-// thess EDIDs are carefully generated according to the EDID spec version 1.3,
-// more info can be found from the following file:
-// frameworks/native/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
-// approved pnp ids can be found here: https://uefi.org/pnp_id_list
-// pnp id: GGL, name: EMU_display_0, last byte is checksum
-// display id is local:8141603649153536
-static const uint8_t sEDID0[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78,
- 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4c, 0x00,
- 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
- 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
- 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x30, 0x00, 0x4b};
-
-// pnp id: GGL, name: EMU_display_1
-// display id is local:8140900251843329
-static const uint8_t sEDID1[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78,
- 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4c, 0x00,
- 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
- 0x2d, 0x40, 0x58, 0x2c, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
- 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x31, 0x00, 0x3b};
-
-// pnp id: GGL, name: EMU_display_2
-// display id is local:8140940453066754
-static const uint8_t sEDID2[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0xec, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x1b, 0x10, 0x01, 0x03, 0x80, 0x50, 0x2d, 0x78,
- 0x0a, 0x0d, 0xc9, 0xa0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4c, 0x00,
- 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x3a, 0x80, 0x18, 0x71, 0x38,
- 0x2d, 0x40, 0x58, 0x2c, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0x00, 0x45, 0x4d, 0x55, 0x5f, 0x64, 0x69, 0x73,
- 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x32, 0x00, 0x49};
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-
-HWC2::Error Display::setEdid(std::vector<uint8_t> edid) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- mEdid = edid;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getDisplayIdentificationData(uint8_t* outPort,
- uint32_t* outDataSize,
- uint8_t* outData) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- if (outPort == nullptr || outDataSize == nullptr) {
- return HWC2::Error::BadParameter;
- }
-
- if (mEdid) {
- if (outData) {
- *outDataSize = std::min<uint32_t>(*outDataSize, (*mEdid).size());
- memcpy(outData, (*mEdid).data(), *outDataSize);
- } else {
- *outDataSize = (*mEdid).size();
- }
- *outPort = mId;
- return HWC2::Error::None;
- }
-
- // fallback to legacy EDID implementation
- uint32_t len = std::min(*outDataSize, (uint32_t)ARRAY_SIZE(sEDID0));
- if (outData != nullptr && len < (uint32_t)ARRAY_SIZE(sEDID0)) {
- ALOGW("%s: display:%" PRIu64 " small buffer size: %u is specified",
- __FUNCTION__, mId, len);
- }
- *outDataSize = ARRAY_SIZE(sEDID0);
- switch (mId) {
- case 0:
- *outPort = 0;
- if (outData) memcpy(outData, sEDID0, len);
- break;
-
- case 1:
- *outPort = 1;
- if (outData) memcpy(outData, sEDID1, len);
- break;
-
- case 2:
- *outPort = 2;
- if (outData) memcpy(outData, sEDID2, len);
- break;
-
- default:
- *outPort = (uint8_t)mId;
- if (outData) {
- memcpy(outData, sEDID2, len);
- uint32_t size = ARRAY_SIZE(sEDID0);
- // change the name to EMU_display_<mID>
- // note the 3rd char from back is the number, _0, _1, _2, etc.
- if (len >= size - 2) outData[size - 3] = '0' + (uint8_t)mId;
- if (len >= size) {
- // update the last byte, which is checksum byte
- uint8_t checksum = -(uint8_t)std::accumulate(
- outData, outData + size - 1, static_cast<uint8_t>(0));
- outData[size - 1] = checksum;
- }
- }
- break;
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getDisplayCapabilities(uint32_t* outNumCapabilities,
- uint32_t* outCapabilities) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
- if (outNumCapabilities == nullptr) {
- return HWC2::Error::None;
- }
-
- bool brightness_support = false;
- bool doze_support = false;
-
- uint32_t count = 1 + (doze_support ? 1 : 0) + (brightness_support ? 1 : 0);
- int index = 0;
- if (outCapabilities != nullptr && (*outNumCapabilities >= count)) {
- outCapabilities[index++] =
- HWC2_DISPLAY_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
- if (doze_support) {
- outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_DOZE;
- }
- if (brightness_support) {
- outCapabilities[index++] = HWC2_DISPLAY_CAPABILITY_BRIGHTNESS;
- }
- }
-
- *outNumCapabilities = count;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::getDisplayBrightnessSupport(bool* out_support) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- *out_support = false;
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setDisplayBrightness(float brightness) {
- DEBUG_LOG("%s: display:%" PRIu64 " brightness %f", __FUNCTION__, mId,
- brightness);
-
- ALOGW("TODO: setDisplayBrightness() is not implemented yet: brightness=%f",
- brightness);
- return HWC2::Error::Unsupported;
-}
-
-HWC2::Error Display::setActiveConfigWithConstraints(
- hwc2_config_t configId,
- hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
- hwc_vsync_period_change_timeline_t* outTimeline) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- if (vsyncPeriodChangeConstraints == nullptr || outTimeline == nullptr) {
- return HWC2::Error::BadParameter;
- }
-
- if (mConfigs.find(configId) == mConfigs.end()) {
- ALOGE("%s: display:%" PRIu64 " bad config:%" PRIu32, __FUNCTION__, mId,
- configId);
- return HWC2::Error::BadConfig;
- }
-
- if (mActiveConfigId == configId) {
- return HWC2::Error::None;
- }
- mActiveConfigId = configId;
-
- if (mComposer == nullptr) {
- ALOGE("%s: display:%" PRIu64 " missing composer", __FUNCTION__, mId);
- return HWC2::Error::NoResources;
- }
-
- HWC2::Error error = mComposer->onActiveConfigChange(this);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " composer failed to handle config change",
- __FUNCTION__, mId);
- return error;
- }
-
- hwc2_vsync_period_t vsyncPeriod;
- error = getDisplayVsyncPeriod(&vsyncPeriod);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " composer failed to handle config change",
- __FUNCTION__, mId);
- return error;
- }
-
- return mVsyncThread->scheduleVsyncUpdate(
- vsyncPeriod, vsyncPeriodChangeConstraints, outTimeline);
-}
-
-HWC2::Error Display::getDisplayConnectionType(uint32_t* outType) {
- if (IsCuttlefishFoldable()) {
- // Workaround to force all displays to INTERNAL for cf_x86_64_foldable.
- // TODO(b/193568008): Allow configuring internal/external per display.
- *outType = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL;
- } else {
- // Other devices default to the first display INTERNAL, others EXTERNAL.
- *outType = mId == 0 ? HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL
- : HWC2_DISPLAY_CONNECTION_TYPE_EXTERNAL;
- }
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setAutoLowLatencyMode(bool /*on*/) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- return HWC2::Error::Unsupported;
-}
-
-HWC2::Error Display::getSupportedContentTypes(
- uint32_t* outNumSupportedContentTypes,
- const uint32_t* /*outSupportedContentTypes*/) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, mId);
-
- if (outNumSupportedContentTypes != nullptr) {
- *outNumSupportedContentTypes = 0;
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Display::setContentType(int32_t contentTypeRaw) {
- auto contentType = static_cast<HWC2::ContentType>(contentTypeRaw);
- auto contentTypeString = to_string(contentType);
- DEBUG_LOG("%s: display:%" PRIu64 " content type:%s", __FUNCTION__, mId,
- contentTypeString.c_str());
-
- if (contentType != HWC2::ContentType::None) {
- return HWC2::Error::Unsupported;
- }
-
- return HWC2::Error::None;
-}
-
-} // namespace android
diff --git a/system/hwc2/Display.h b/system/hwc2/Display.h
deleted file mode 100644
index 197d3ea..0000000
--- a/system/hwc2/Display.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * Copyright 2021 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_HWC_DISPLAY_H
-#define ANDROID_HWC_DISPLAY_H
-
-#include <android-base/unique_fd.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-
-#include <array>
-#include <mutex>
-#include <optional>
-#include <set>
-#include <thread>
-#include <unordered_map>
-#include <vector>
-
-#include "Common.h"
-#include "Composer.h"
-#include "DisplayConfig.h"
-#include "DisplayFinder.h"
-#include "FencedBuffer.h"
-#include "Layer.h"
-#include "VsyncThread.h"
-
-namespace android {
-
-class Composer;
-class Device;
-
-struct ColorTransformWithMatrix {
- android::hardware::graphics::common::V1_0::ColorTransform transformType;
- std::optional<std::array<float, 16>> transformMatrixOpt;
-};
-
-class Display {
- public:
- Display(Composer* composer, hwc2_display_t id);
- ~Display();
-
- Display(const Display& display) = delete;
- Display& operator=(const Display& display) = delete;
-
- Display(Display&& display) = delete;
- Display& operator=(Display&& display) = delete;
-
- HWC2::Error init(
- const std::vector<DisplayConfig>& configs, hwc2_config_t activeConfigId,
- const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
-
- HWC2::Error updateParameters(
- uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
- uint32_t refreshRateHz,
- const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
-
- hwc2_display_t getId() const { return mId; }
-
- Layer* getLayer(hwc2_layer_t layerHandle);
-
- FencedBuffer& getClientTarget() { return mClientTarget; }
- buffer_handle_t waitAndGetClientTargetBuffer();
-
- const std::vector<Layer*>& getOrderedLayers() { return mOrderedLayers; }
-
- 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 getDisplayAttribute(hwc2_config_t configId, int32_t attribute,
- int32_t* outValue);
- HWC2::Error getDisplayAttributeEnum(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 addReleaseFenceLocked(hwc2_layer_t layerId,
- base::unique_fd fence);
- HWC2::Error getReleaseFences(uint32_t* outNumElements,
- hwc2_layer_t* outLayers, int32_t* outFences);
- HWC2::Error clearReleaseFencesAndIdsLocked();
- HWC2::Error getRequests(int32_t* outDisplayRequests, uint32_t* outNumElements,
- hwc2_layer_t* outLayers, int32_t* outLayerRequests);
- HWC2::Error getType(int32_t* outType);
- 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(int32_t mode);
- HWC2::Error setColorTransform(const float* matrix, int transform);
- HWC2::Error setColorTransformEnum(
- const float* matrix,
- android::hardware::graphics::common::V1_0::ColorTransform transform);
- bool hasColorTransform() const { return mColorTransform.has_value(); }
- ColorTransformWithMatrix getColorTransform() const {
- return *mColorTransform;
- }
-
- HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence);
- HWC2::Error setPowerMode(int32_t mode);
- HWC2::Error setVsyncEnabled(int32_t enabled);
- HWC2::Error setVsyncCallback(HWC2_PFN_VSYNC callback,
- hwc2_callback_data_t data);
- HWC2::Error setVsync24Callback(HWC2_PFN_VSYNC_2_4 callback,
- hwc2_callback_data_t data);
- HWC2::Error getDisplayVsyncPeriod(hwc2_vsync_period_t* outVsyncPeriod);
- HWC2::Error setActiveConfigWithConstraints(
- hwc2_config_t config,
- hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
- hwc_vsync_period_change_timeline_t* timeline);
- HWC2::Error getDisplayConnectionType(uint32_t* outType);
-
- 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);
- HWC2::Error setEdid(std::vector<uint8_t> edid);
- HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
- uint32_t* outDataSize,
- uint8_t* outData);
- HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities,
- uint32_t* outCapabilities);
- HWC2::Error getDisplayBrightnessSupport(bool* out_support);
- HWC2::Error setDisplayBrightness(float brightness);
- HWC2::Error setAutoLowLatencyMode(bool on);
- HWC2::Error getSupportedContentTypes(
- uint32_t* outNumSupportedContentTypes,
- const uint32_t* outSupportedContentTypes);
- HWC2::Error setContentType(int32_t contentType);
- void lock() { mStateMutex.lock(); }
- void unlock() { mStateMutex.unlock(); }
-
- private:
- // 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;
- };
-
- private:
- // 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.
- mutable std::recursive_mutex mStateMutex;
-
- Composer* mComposer = nullptr;
- const hwc2_display_t mId;
- std::string mName;
- HWC2::DisplayType mType = HWC2::DisplayType::Physical;
- HWC2::PowerMode mPowerMode = HWC2::PowerMode::Off;
- sp<VsyncThread> mVsyncThread;
- FencedBuffer mClientTarget;
- // Will only be non-null after the Display has been validated and
- // before it has been presented
- std::unique_ptr<Changes> mChanges;
-
- std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
- // Ordered layers available after validate().
- std::vector<Layer*> mOrderedLayers;
-
- std::unordered_map<hwc2_layer_t, base::unique_fd> mReleaseFences;
- std::optional<hwc2_config_t> mActiveConfigId;
- std::unordered_map<hwc2_config_t, DisplayConfig> mConfigs;
- std::set<android_color_mode_t> mColorModes = {HAL_COLOR_MODE_NATIVE};
- android_color_mode_t mActiveColorMode = HAL_COLOR_MODE_NATIVE;
- std::optional<ColorTransformWithMatrix> mColorTransform;
- std::optional<std::vector<uint8_t>> mEdid;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/DisplayConfig.cpp b/system/hwc2/DisplayConfig.cpp
deleted file mode 100644
index abd0b89..0000000
--- a/system/hwc2/DisplayConfig.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2021 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 "DisplayConfig.h"
-
-#include <unordered_map>
-
-namespace {
-
-template <class T>
-inline void hashCombine(size_t& hash, const T& value) {
- std::hash<T> hasher;
- hash ^= hasher(value) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
-}
-
-} // namespace
-
-void DisplayConfig::setAttribute(HWC2::Attribute attribute, int32_t value) {
- if (attribute == HWC2::Attribute::Width) {
- mWidth = value;
- }
- if (attribute == HWC2::Attribute::Height) {
- mHeight = value;
- }
- if (attribute == HWC2::Attribute::DpiX) {
- mDpiX = value;
- }
- if (attribute == HWC2::Attribute::DpiY) {
- mDpiY = value;
- }
- if (attribute == HWC2::Attribute::VsyncPeriod) {
- mVsyncPeriodNanos = value;
- }
- if (attribute == HWC2::Attribute::ConfigGroup) {
- mConfigGroup = value;
- }
-}
-
-int32_t DisplayConfig::getAttribute(HWC2::Attribute attribute) const {
- if (attribute == HWC2::Attribute::Width) {
- return mWidth;
- }
- if (attribute == HWC2::Attribute::Height) {
- return mHeight;
- }
- if (attribute == HWC2::Attribute::DpiX) {
- // From hwcomposer2.h, HWC2_ATTRIBUTE_DPI_X returns "Dots per thousand
- // inches (DPI * 1000)".
- return getDotsPerThousandInchesX();
- }
- if (attribute == HWC2::Attribute::DpiY) {
- // From hwcomposer2.h, HWC2_ATTRIBUTE_DPI_Y returns "Dots per thousand
- // inches (DPI * 1000)"
- return getDotsPerThousandInchesY();
- }
- if (attribute == HWC2::Attribute::VsyncPeriod) {
- return mVsyncPeriodNanos;
- }
- if (attribute == HWC2::Attribute::ConfigGroup) {
- return mConfigGroup;
- }
- return -1;
-}
-
-std::string DisplayConfig::toString() const {
- std::string output;
- output += " w:" + std::to_string(mWidth);
- output += " h:" + std::to_string(mHeight);
- output += " dpi-x:" + std::to_string(mDpiX);
- output += " dpi-y:" + std::to_string(mDpiY);
- output += " vsync:" + std::to_string(1e9 / mVsyncPeriodNanos);
- output += " config-group:" + std::to_string(mConfigGroup);
- return output;
-}
-
-/*static*/
-void DisplayConfig::addConfigGroups(std::vector<DisplayConfig>* configs) {
- // From /hardware/interfaces/graphics/composer/2.4/IComposerClient.hal:
- // "Configurations which share the same config group are similar in all
- // attributes except for the vsync period."
- struct ConfigForGroupHash {
- size_t operator()(const DisplayConfig& config) const {
- size_t hash = 0;
- hashCombine(hash, config.mWidth);
- hashCombine(hash, config.mHeight);
- hashCombine(hash, config.mDpiX);
- hashCombine(hash, config.mDpiY);
- return hash;
- }
- };
- struct ConfigForGroupEq {
- size_t operator()(const DisplayConfig& a, const DisplayConfig& b) const {
- if (a.mWidth != b.mWidth) {
- return a.mWidth < b.mWidth;
- }
- if (a.mHeight != b.mHeight) {
- return a.mHeight < b.mHeight;
- }
- if (a.mDpiX != b.mDpiX) {
- return a.mDpiX < b.mDpiX;
- }
- return a.mDpiY < b.mDpiY;
- }
- };
-
- std::unordered_map<DisplayConfig, int32_t, ConfigForGroupHash,
- ConfigForGroupEq>
- configToConfigGroup;
-
- for (auto& config : *configs) {
- auto [it, inserted] =
- configToConfigGroup.try_emplace(config, configToConfigGroup.size());
- config.setConfigGroup(it->second);
- }
-}
\ No newline at end of file
diff --git a/system/hwc2/DisplayConfig.h b/system/hwc2/DisplayConfig.h
deleted file mode 100644
index 02d9b77..0000000
--- a/system/hwc2/DisplayConfig.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2021 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_HWC_DISPLAYCONFIG_H
-#define ANDROID_HWC_DISPLAYCONFIG_H
-
-#include <android/hardware/graphics/common/1.0/types.h>
-
-#include <vector>
-
-#include "Common.h"
-
-class DisplayConfig {
- public:
- DisplayConfig(hwc2_config_t configId) : mId(configId) {}
-
- DisplayConfig(hwc2_config_t configId, int32_t width, int32_t height,
- int32_t dpiX, int32_t dpiY, int32_t vsyncPeriodNanos)
- : mId(configId),
- mWidth(width),
- mHeight(height),
- mDpiX(dpiX),
- mDpiY(dpiY),
- mVsyncPeriodNanos(vsyncPeriodNanos) {}
-
- DisplayConfig(const DisplayConfig& other) = default;
- DisplayConfig& operator=(DisplayConfig& other) = default;
-
- DisplayConfig(DisplayConfig&& other) = default;
- DisplayConfig& operator=(DisplayConfig&& other) = default;
-
- hwc2_config_t getId() const { return mId; }
- void setId(hwc2_config_t id) { mId = id; }
-
- int32_t getAttribute(HWC2::Attribute attribute) const;
- void setAttribute(HWC2::Attribute attribute, int32_t value);
-
- int32_t getWidth() const { return mWidth; }
- void setWidth(int32_t width) { mWidth = width; }
-
- int32_t getHeight() const { return mHeight; }
- void getHeight(int32_t height) { mHeight = height; }
-
- int32_t getDpiX() const { return mDpiX; }
- void setDpiX(int32_t dpi) { mDpiX = dpi; }
-
- int32_t getDpiY() const { return mDpiY; }
- void setDpiY(int32_t dpi) { mDpiY = dpi; }
-
- int32_t getDotsPerThousandInchesX() const { return mDpiX * 1000; }
- int32_t getDotsPerThousandInchesY() const { return mDpiY * 1000; }
-
- int32_t getVsyncPeriod() const { return mVsyncPeriodNanos; }
- void setVsyncPeriod(int32_t vsync) { mVsyncPeriodNanos = vsync; }
-
- int32_t getConfigGroup() const { return mConfigGroup; }
- void setConfigGroup(int32_t group) { mConfigGroup = group; }
-
- std::string toString() const;
-
- static void addConfigGroups(std::vector<DisplayConfig>* configs);
-
- private:
- hwc2_config_t mId;
-
- int32_t mWidth;
- int32_t mHeight;
- int32_t mDpiX;
- int32_t mDpiY;
- int32_t mVsyncPeriodNanos;
- int32_t mConfigGroup;
-};
-
-#endif
diff --git a/system/hwc2/DisplayFinder.cpp b/system/hwc2/DisplayFinder.cpp
deleted file mode 100644
index 44b1f92..0000000
--- a/system/hwc2/DisplayFinder.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Copyright 2021 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 "DisplayFinder.h"
-
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <device_config_shared.h>
-
-#include "Common.h"
-#include "HostUtils.h"
-
-namespace android {
-namespace {
-
-constexpr int32_t HertzToPeriodNanos(uint32_t hertz) {
- return 1000 * 1000 * 1000 / hertz;
-}
-
-static int getVsyncHzFromProperty() {
- static constexpr const auto kVsyncProp = "ro.boot.qemu.vsync";
-
- const auto vsyncProp = android::base::GetProperty(kVsyncProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, vsyncProp.c_str());
-
- uint64_t vsyncPeriod;
- if (!android::base::ParseUint(vsyncProp, &vsyncPeriod)) {
- ALOGE("%s: failed to parse vsync period '%s', returning default 60",
- __FUNCTION__, vsyncProp.c_str());
- return 60;
- }
-
- return static_cast<int>(vsyncPeriod);
-}
-
-int32_t getVsyncForDisplay(DrmPresenter* drmPresenter, uint32_t displayId) {
- const int32_t vsyncPeriodForDisplay = drmPresenter->refreshRate(displayId);
- return vsyncPeriodForDisplay < 0
- ? HertzToPeriodNanos(getVsyncHzFromProperty())
- : HertzToPeriodNanos(vsyncPeriodForDisplay);
-}
-
-HWC2::Error findCuttlefishDisplays(
- std::vector<DisplayMultiConfigs>* outDisplays) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- // TODO: replace with initializing directly from DRM info.
- const auto deviceConfig = cuttlefish::GetDeviceConfig();
-
- hwc2_display_t displayId = 0;
- for (const auto& deviceDisplayConfig : deviceConfig.display_config()) {
- // crosvm does not fully support EDID yet, so we solely rely on the
- // device config for our vsync.
- const auto vsyncPeriodNanos =
- HertzToPeriodNanos(deviceDisplayConfig.refresh_rate_hz());
-
- DisplayMultiConfigs display = {
- .displayId = displayId,
- .activeConfigId = 0,
- .configs =
- {
- DisplayConfig(0, //
- deviceDisplayConfig.width(), //
- deviceDisplayConfig.height(), //
- deviceDisplayConfig.dpi(), //
- deviceDisplayConfig.dpi(), //
- vsyncPeriodNanos),
- },
- };
- outDisplays->push_back(display);
- ++displayId;
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error findGoldfishPrimaryDisplay(
- DrmPresenter* drmPresenter,
- std::vector<DisplayMultiConfigs>* outDisplays) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- hostCon->lock();
- DisplayMultiConfigs display;
- display.displayId = 0;
- if (rcEnc->hasHWCMultiConfigs()) {
- int count = rcEnc->rcGetFBDisplayConfigsCount(rcEnc);
- if (count <= 0) {
- ALOGE("%s failed to allocate primary display, config count %d", __func__,
- count);
- return HWC2::Error::NoResources;
- }
- display.activeConfigId = rcEnc->rcGetFBDisplayActiveConfig(rcEnc);
- for (int configId = 0; configId < count; configId++) {
- display.configs.push_back(DisplayConfig(
- configId, //
- rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_WIDTH), //
- rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_HEIGHT), //
- rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_XDPI), //
- rcEnc->rcGetFBDisplayConfigsParam(rcEnc, configId, FB_YDPI), //
- getVsyncForDisplay(drmPresenter, display.displayId) //
- ));
- }
- } else {
- display.activeConfigId = 0;
- display.configs.push_back(DisplayConfig(
- 0, //
- rcEnc->rcGetFBParam(rcEnc, FB_WIDTH), //
- rcEnc->rcGetFBParam(rcEnc, FB_HEIGHT), //
- rcEnc->rcGetFBParam(rcEnc, FB_XDPI), //
- rcEnc->rcGetFBParam(rcEnc, FB_YDPI), //
- getVsyncForDisplay(drmPresenter, 0) //
- ));
- }
- hostCon->unlock();
-
- outDisplays->push_back(display);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error findGoldfishSecondaryDisplays(
- std::vector<DisplayMultiConfigs>* outDisplays) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- static constexpr const char kExternalDisplayProp[] =
- "hwservicemanager.external.displays";
-
- const auto propString = android::base::GetProperty(kExternalDisplayProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, propString.c_str());
-
- if (propString.empty()) {
- return HWC2::Error::None;
- }
-
- const std::vector<std::string> propStringParts =
- android::base::Split(propString, ",");
- if (propStringParts.size() % 5 != 0) {
- ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
- kExternalDisplayProp, propString.c_str());
- return HWC2::Error::BadParameter;
- }
-
- std::vector<int> propIntParts;
- for (const std::string& propStringPart : propStringParts) {
- int propIntPart;
- if (!android::base::ParseInt(propStringPart, &propIntPart)) {
- ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
- kExternalDisplayProp, propString.c_str());
- return HWC2::Error::BadParameter;
- }
- propIntParts.push_back(propIntPart);
- }
-
- hwc2_display_t secondaryDisplayId = 1;
- while (!propIntParts.empty()) {
- DisplayMultiConfigs display;
- display.displayId = secondaryDisplayId;
- display.activeConfigId = 0;
- display.configs.push_back(DisplayConfig(
- 0, //
- /*width=*/propIntParts[1], //
- /*heighth=*/propIntParts[2], //
- /*dpiXh=*/propIntParts[3], //
- /*dpiYh=*/propIntParts[3], //
- /*vsyncPeriod=*/HertzToPeriodNanos(160) //
- ));
- outDisplays->push_back(display);
-
- ++secondaryDisplayId;
-
- propIntParts.erase(propIntParts.begin(), propIntParts.begin() + 5);
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error findGoldfishDisplays(
- DrmPresenter* drmPresenter,
- std::vector<DisplayMultiConfigs>* outDisplays) {
- HWC2::Error error = findGoldfishPrimaryDisplay(drmPresenter, outDisplays);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to find Goldfish primary display", __FUNCTION__);
- return error;
- }
-
- error = findGoldfishSecondaryDisplays(outDisplays);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to find Goldfish secondary displays", __FUNCTION__);
- }
-
- return error;
-}
-
-// This is currently only used for Gem5 bring-up where virtio-gpu and drm
-// are not currently available. For now, just return a placeholder display.
-HWC2::Error findNoOpDisplays(std::vector<DisplayMultiConfigs>* outDisplays) {
- outDisplays->push_back(DisplayMultiConfigs{
- .displayId = 0,
- .activeConfigId = 0,
- .configs = {DisplayConfig(0,
- /*width=*/720, //
- /*heighth=*/1280, //
- /*dpiXh=*/320, //
- /*dpiYh=*/320, //
- /*vsyncPeriod=*/HertzToPeriodNanos(30) //
- )},
- });
-
- return HWC2::Error::None;
-}
-
-HWC2::Error findDrmDisplays(const DrmPresenter& drm,
- std::vector<DisplayMultiConfigs>* outDisplays) {
- outDisplays->clear();
-
- std::vector<DrmPresenter::DisplayConfig> drmDisplayConfigs;
-
- HWC2::Error error = drm.getDisplayConfigs(&drmDisplayConfigs);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to find displays from DRM.", __FUNCTION__);
- return error;
- }
-
- for (const DrmPresenter::DisplayConfig drmDisplayConfig : drmDisplayConfigs) {
- outDisplays->push_back(DisplayMultiConfigs{
- .displayId = drmDisplayConfig.id,
- .activeConfigId = drmDisplayConfig.id,
- .configs = {
- DisplayConfig(drmDisplayConfig.id,
- drmDisplayConfig.width,
- drmDisplayConfig.height,
- drmDisplayConfig.dpiX,
- drmDisplayConfig.dpiY,
- HertzToPeriodNanos(drmDisplayConfig.refreshRateHz)),
- },
- });
- }
-
- return HWC2::Error::None;
-}
-
-} // namespace
-
-HWC2::Error findDisplays(DrmPresenter* drmPresenter,
- std::vector<DisplayMultiConfigs>* outDisplays) {
- HWC2::Error error = HWC2::Error::None;
- if (IsInNoOpDisplayFinderMode()) {
- error = findNoOpDisplays(outDisplays);
- } else if (IsInDrmDisplayFinderMode()) {
- if (drmPresenter == nullptr) {
- ALOGE("%s asked to find displays from DRM, but DRM not available.",
- __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- error = findDrmDisplays(*drmPresenter, outDisplays);
- } else if (IsCuttlefish()) {
- error = findCuttlefishDisplays(outDisplays);
- } else {
- error = findGoldfishDisplays(drmPresenter, outDisplays);
- }
-
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to find displays", __FUNCTION__);
- return error;
- }
-
- for (auto& display : *outDisplays) {
- DisplayConfig::addConfigGroups(&display.configs);
- }
-
- return HWC2::Error::None;
-}
-
-} // namespace android
diff --git a/system/hwc2/DisplayFinder.h b/system/hwc2/DisplayFinder.h
deleted file mode 100644
index 16844fa..0000000
--- a/system/hwc2/DisplayFinder.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2021 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_HWC_DISPLAYFINDER_H
-#define ANDROID_HWC_DISPLAYFINDER_H
-
-#include <optional>
-#include <vector>
-
-#include "Common.h"
-#include "DisplayConfig.h"
-#include "DrmPresenter.h"
-
-namespace android {
-
-struct DisplayMultiConfigs {
- hwc2_display_t displayId;
- hwc2_config_t activeConfigId;
- // Modes that this display can be configured to use.
- std::vector<DisplayConfig> configs;
-};
-
-HWC2::Error findDisplays(DrmPresenter* drmPresenter,
- std::vector<DisplayMultiConfigs>* outDisplays);
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/Drm.cpp b/system/hwc2/Drm.cpp
deleted file mode 100644
index 4b27fa2..0000000
--- a/system/hwc2/Drm.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2020 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 "Drm.h"
-
-#include <drm_fourcc.h>
-#include <log/log.h>
-#include <system/graphics.h>
-
-namespace android {
-
-const char* GetDrmFormatString(uint32_t drm_format) {
- switch (drm_format) {
- case DRM_FORMAT_ABGR1555:
- return "DRM_FORMAT_ABGR1555";
- case DRM_FORMAT_ABGR2101010:
- return "DRM_FORMAT_ABGR2101010";
- case DRM_FORMAT_ABGR4444:
- return "DRM_FORMAT_ABGR4444";
- case DRM_FORMAT_ABGR8888:
- return "DRM_FORMAT_ABGR8888";
- case DRM_FORMAT_ARGB1555:
- return "DRM_FORMAT_ARGB1555";
- case DRM_FORMAT_ARGB2101010:
- return "DRM_FORMAT_ARGB2101010";
- case DRM_FORMAT_ARGB4444:
- return "DRM_FORMAT_ARGB4444";
- case DRM_FORMAT_ARGB8888:
- return "DRM_FORMAT_ARGB8888";
- case DRM_FORMAT_AYUV:
- return "DRM_FORMAT_AYUV";
- case DRM_FORMAT_BGR233:
- return "DRM_FORMAT_BGR233";
- case DRM_FORMAT_BGR565:
- return "DRM_FORMAT_BGR565";
- case DRM_FORMAT_BGR888:
- return "DRM_FORMAT_BGR888";
- case DRM_FORMAT_BGRA1010102:
- return "DRM_FORMAT_BGRA1010102";
- case DRM_FORMAT_BGRA4444:
- return "DRM_FORMAT_BGRA4444";
- case DRM_FORMAT_BGRA5551:
- return "DRM_FORMAT_BGRA5551";
- case DRM_FORMAT_BGRA8888:
- return "DRM_FORMAT_BGRA8888";
- case DRM_FORMAT_BGRX1010102:
- return "DRM_FORMAT_BGRX1010102";
- case DRM_FORMAT_BGRX4444:
- return "DRM_FORMAT_BGRX4444";
- case DRM_FORMAT_BGRX5551:
- return "DRM_FORMAT_BGRX5551";
- case DRM_FORMAT_BGRX8888:
- return "DRM_FORMAT_BGRX8888";
- case DRM_FORMAT_C8:
- return "DRM_FORMAT_C8";
- case DRM_FORMAT_GR88:
- return "DRM_FORMAT_GR88";
- case DRM_FORMAT_NV12:
- return "DRM_FORMAT_NV12";
- case DRM_FORMAT_NV21:
- return "DRM_FORMAT_NV21";
- case DRM_FORMAT_R8:
- return "DRM_FORMAT_R8";
- case DRM_FORMAT_RG88:
- return "DRM_FORMAT_RG88";
- case DRM_FORMAT_RGB332:
- return "DRM_FORMAT_RGB332";
- case DRM_FORMAT_RGB565:
- return "DRM_FORMAT_RGB565";
- case DRM_FORMAT_RGB888:
- return "DRM_FORMAT_RGB888";
- case DRM_FORMAT_RGBA1010102:
- return "DRM_FORMAT_RGBA1010102";
- case DRM_FORMAT_RGBA4444:
- return "DRM_FORMAT_RGBA4444";
- case DRM_FORMAT_RGBA5551:
- return "DRM_FORMAT_RGBA5551";
- case DRM_FORMAT_RGBA8888:
- return "DRM_FORMAT_RGBA8888";
- case DRM_FORMAT_RGBX1010102:
- return "DRM_FORMAT_RGBX1010102";
- case DRM_FORMAT_RGBX4444:
- return "DRM_FORMAT_RGBX4444";
- case DRM_FORMAT_RGBX5551:
- return "DRM_FORMAT_RGBX5551";
- case DRM_FORMAT_RGBX8888:
- return "DRM_FORMAT_RGBX8888";
- case DRM_FORMAT_UYVY:
- return "DRM_FORMAT_UYVY";
- case DRM_FORMAT_VYUY:
- return "DRM_FORMAT_VYUY";
- case DRM_FORMAT_XBGR1555:
- return "DRM_FORMAT_XBGR1555";
- case DRM_FORMAT_XBGR2101010:
- return "DRM_FORMAT_XBGR2101010";
- case DRM_FORMAT_XBGR4444:
- return "DRM_FORMAT_XBGR4444";
- case DRM_FORMAT_XBGR8888:
- return "DRM_FORMAT_XBGR8888";
- case DRM_FORMAT_XRGB1555:
- return "DRM_FORMAT_XRGB1555";
- case DRM_FORMAT_XRGB2101010:
- return "DRM_FORMAT_XRGB2101010";
- case DRM_FORMAT_XRGB4444:
- return "DRM_FORMAT_XRGB4444";
- case DRM_FORMAT_XRGB8888:
- return "DRM_FORMAT_XRGB8888";
- case DRM_FORMAT_YUYV:
- return "DRM_FORMAT_YUYV";
- case DRM_FORMAT_YVU420:
- return "DRM_FORMAT_YVU420";
- case DRM_FORMAT_YVYU:
- return "DRM_FORMAT_YVYU";
- }
- return "Unknown";
-}
-
-int GetDrmFormatBytesPerPixel(uint32_t drm_format) {
- switch (drm_format) {
- case DRM_FORMAT_ABGR8888:
- case DRM_FORMAT_ARGB8888:
- case DRM_FORMAT_XBGR8888:
- return 4;
- case DRM_FORMAT_BGR888:
- return 3;
- case DRM_FORMAT_RGB565:
- case DRM_FORMAT_YVU420:
-#ifdef GRALLOC_MODULE_API_VERSION_0_2
- case DRM_FORMAT_FLEX_YCbCr_420_888:
-#endif
- return 2;
- case DRM_FORMAT_R8:
- return 1;
- }
- ALOGE("%s: format size unknown %d(%s)", __FUNCTION__, drm_format,
- GetDrmFormatString(drm_format));
- return 8;
-}
-
-int GetDrmFormatFromHalFormat(int hal_format) {
- switch (hal_format) {
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- return DRM_FORMAT_ABGR16161616F;
- case HAL_PIXEL_FORMAT_RGBA_8888:
- return DRM_FORMAT_ABGR8888;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return DRM_FORMAT_XBGR8888;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return DRM_FORMAT_ARGB8888;
- case HAL_PIXEL_FORMAT_RGB_888:
- return DRM_FORMAT_BGR888;
- case HAL_PIXEL_FORMAT_RGB_565:
- return DRM_FORMAT_BGR565;
- case HAL_PIXEL_FORMAT_YV12:
- return DRM_FORMAT_YVU420;
- case HAL_PIXEL_FORMAT_YCbCr_420_888:
- return DRM_FORMAT_YVU420;
- case HAL_PIXEL_FORMAT_BLOB:
- return DRM_FORMAT_R8;
- default:
- break;
- }
- ALOGE("%s unhandled hal format: %d", __FUNCTION__, hal_format);
- return 0;
-}
-
-} // namespace android
\ No newline at end of file
diff --git a/system/hwc2/Drm.h b/system/hwc2/Drm.h
deleted file mode 100644
index 9bc18b3..0000000
--- a/system/hwc2/Drm.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2021 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_HWC_DRM_H
-#define ANDROID_HWC_DRM_H
-
-#include <cstdlib>
-
-namespace android {
-
-const char* GetDrmFormatString(uint32_t drm_format);
-
-int GetDrmFormatBytesPerPixel(uint32_t drm_format);
-
-int GetDrmFormatFromHalFormat(int hal_format);
-
-} // namespace android
-
-#endif
\ No newline at end of file
diff --git a/system/hwc2/DrmPresenter.cpp b/system/hwc2/DrmPresenter.cpp
deleted file mode 100644
index a36bd89..0000000
--- a/system/hwc2/DrmPresenter.cpp
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * Copyright 2021 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 "DrmPresenter.h"
-
-#include <cros_gralloc_handle.h>
-#include <linux/netlink.h>
-#include <sys/socket.h>
-
-using android::base::guest::AutoReadLock;
-using android::base::guest::AutoWriteLock;
-using android::base::guest::ReadWriteLock;
-
-namespace android {
-
-DrmBuffer::DrmBuffer(DrmPresenter& DrmPresenter)
- : mDrmPresenter(DrmPresenter) {}
-
-DrmBuffer::~DrmBuffer() { mDrmPresenter.destroyDrmFramebuffer(this); }
-
-bool DrmPresenter::init(const HotplugCallback& cb) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- mHotplugCallback = cb;
- mFd = android::base::unique_fd(open("/dev/dri/card0", O_RDWR | O_CLOEXEC));
- if (mFd < 0) {
- ALOGE("%s HWC2::Error opening DrmPresenter device: %d", __FUNCTION__,
- errno);
- return false;
- }
-
- int univRet = drmSetClientCap(mFd.get(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
- if (univRet) {
- ALOGE("%s: fail to set universal plane %d\n", __FUNCTION__, univRet);
- return false;
- }
-
- int atomicRet = drmSetClientCap(mFd.get(), DRM_CLIENT_CAP_ATOMIC, 1);
- if (atomicRet) {
- ALOGE("%s: fail to set atomic operation %d, %d\n", __FUNCTION__, atomicRet,
- errno);
- return false;
- }
-
- {
- AutoWriteLock lock(mStateMutex);
- bool initDrmRet = initDrmElementsLocked();
- if (initDrmRet) {
- ALOGD("%s: Successfully initialized DRM backend", __FUNCTION__);
- } else {
- ALOGE("%s: Failed to initialize DRM backend", __FUNCTION__);
- return false;
- }
-
- constexpr const std::size_t kCachedBuffersPerDisplay = 3;
- std::size_t numDisplays = 0;
- for (const DrmConnector& connector : mConnectors) {
- if (connector.connection == DRM_MODE_CONNECTED) {
- ++numDisplays;
- }
- }
- const std::size_t bufferCacheSize = kCachedBuffersPerDisplay * numDisplays;
- DEBUG_LOG("%s: initializing DRM buffer cache to size %zu",
- __FUNCTION__, bufferCacheSize);
- mBufferCache = std::make_unique<DrmBufferCache>(bufferCacheSize);
- }
-
- mDrmEventListener = sp<DrmEventListener>::make(*this);
- if (mDrmEventListener->init()) {
- ALOGD("%s: Successfully initialized DRM event listener", __FUNCTION__);
- } else {
- ALOGE("%s: Failed to initialize DRM event listener", __FUNCTION__);
- }
- mDrmEventListener->run("", ANDROID_PRIORITY_URGENT_DISPLAY);
-
- return true;
-}
-
-bool DrmPresenter::initDrmElementsLocked() {
- drmModeRes* res;
- static const int32_t kUmPerInch = 25400;
-
- res = drmModeGetResources(mFd.get());
- if (res == nullptr) {
- ALOGE("%s HWC2::Error reading drm resources: %d", __FUNCTION__, errno);
- mFd.reset();
- return false;
- }
-
- ALOGD(
- "drmModeRes count fbs %d crtc %d connector %d encoder %d min w %d max w "
- "%d min h %d max h %d",
- res->count_fbs, res->count_crtcs, res->count_connectors,
- res->count_encoders, res->min_width, res->max_width, res->min_height,
- res->max_height);
-
- for (uint32_t i = 0; i < res->count_crtcs; i++) {
- DrmCrtc crtc = {};
-
- drmModeCrtcPtr c = drmModeGetCrtc(mFd.get(), res->crtcs[i]);
- crtc.mId = c->crtc_id;
-
- drmModeObjectPropertiesPtr crtcProps =
- drmModeObjectGetProperties(mFd.get(), c->crtc_id, DRM_MODE_OBJECT_CRTC);
-
- for (uint32_t crtcPropsIndex = 0; crtcPropsIndex < crtcProps->count_props;
- crtcPropsIndex++) {
- drmModePropertyPtr crtcProp =
- drmModeGetProperty(mFd.get(), crtcProps->props[crtcPropsIndex]);
-
- if (!strcmp(crtcProp->name, "OUT_FENCE_PTR")) {
- crtc.mOutFencePtrPropertyId = crtcProp->prop_id;
- } else if (!strcmp(crtcProp->name, "ACTIVE")) {
- crtc.mActivePropertyId = crtcProp->prop_id;
- } else if (!strcmp(crtcProp->name, "MODE_ID")) {
- crtc.mModePropertyId = crtcProp->prop_id;
- }
-
- drmModeFreeProperty(crtcProp);
- }
-
- drmModeFreeObjectProperties(crtcProps);
-
- mCrtcs.push_back(crtc);
- }
-
- drmModePlaneResPtr planeRes = drmModeGetPlaneResources(mFd.get());
- for (uint32_t i = 0; i < planeRes->count_planes; ++i) {
- DrmPlane plane = {};
-
- drmModePlanePtr p = drmModeGetPlane(mFd.get(), planeRes->planes[i]);
- plane.mId = p->plane_id;
-
- ALOGD(
- "%s: plane id: %u crtcid %u fbid %u crtc xy %d %d xy %d %d "
- "possible ctrcs 0x%x",
- __FUNCTION__, p->plane_id, p->crtc_id, p->fb_id, p->crtc_x, p->crtc_y,
- p->x, p->y, p->possible_crtcs);
-
- drmModeObjectPropertiesPtr planeProps =
- drmModeObjectGetProperties(mFd.get(), plane.mId, DRM_MODE_OBJECT_PLANE);
-
- for (uint32_t planePropIndex = 0; planePropIndex < planeProps->count_props;
- ++planePropIndex) {
- drmModePropertyPtr planeProp =
- drmModeGetProperty(mFd.get(), planeProps->props[planePropIndex]);
-
- if (!strcmp(planeProp->name, "CRTC_ID")) {
- plane.mCrtcPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "IN_FENCE_FD")) {
- plane.mInFenceFdPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "FB_ID")) {
- plane.mFbPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "CRTC_X")) {
- plane.mCrtcXPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "CRTC_Y")) {
- plane.mCrtcYPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "CRTC_W")) {
- plane.mCrtcWPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "CRTC_H")) {
- plane.mCrtcHPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "SRC_X")) {
- plane.mSrcXPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "SRC_Y")) {
- plane.mSrcYPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "SRC_W")) {
- plane.mSrcWPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "SRC_H")) {
- plane.mSrcHPropertyId = planeProp->prop_id;
- } else if (!strcmp(planeProp->name, "type")) {
- plane.mTypePropertyId = planeProp->prop_id;
- uint64_t type = planeProp->values[0];
- switch (type) {
- case DRM_PLANE_TYPE_OVERLAY:
- plane.mType = type;
- ALOGD("%s: plane %" PRIu32 " is DRM_PLANE_TYPE_OVERLAY",
- __FUNCTION__, plane.mId);
- break;
- case DRM_PLANE_TYPE_PRIMARY:
- plane.mType = type;
- ALOGD("%s: plane %" PRIu32 " is DRM_PLANE_TYPE_PRIMARY",
- __FUNCTION__, plane.mId);
- break;
- default:
- break;
- }
- }
-
- drmModeFreeProperty(planeProp);
- }
-
- drmModeFreeObjectProperties(planeProps);
-
- bool isPrimaryOrOverlay = plane.mType == DRM_PLANE_TYPE_OVERLAY ||
- plane.mType == DRM_PLANE_TYPE_PRIMARY;
- if (isPrimaryOrOverlay) {
- for (uint32_t j = 0; j < mCrtcs.size(); j++) {
- if ((0x1 << j) & p->possible_crtcs) {
- ALOGD("%s: plane %" PRIu32 " compatible with crtc mask %" PRIu32,
- __FUNCTION__, plane.mId, p->possible_crtcs);
- if (mCrtcs[j].mPlaneId == -1) {
- mCrtcs[j].mPlaneId = plane.mId;
- ALOGD("%s: plane %" PRIu32 " associated with crtc %" PRIu32,
- __FUNCTION__, plane.mId, j);
- break;
- }
- }
- }
- }
-
- drmModeFreePlane(p);
- mPlanes[plane.mId] = plane;
- }
- drmModeFreePlaneResources(planeRes);
-
- for (uint32_t i = 0; i < res->count_connectors; ++i) {
- DrmConnector connector = {};
- connector.mId = res->connectors[i];
-
- {
- drmModeObjectPropertiesPtr connectorProps = drmModeObjectGetProperties(
- mFd.get(), connector.mId, DRM_MODE_OBJECT_CONNECTOR);
-
- for (uint32_t connectorPropIndex = 0;
- connectorPropIndex < connectorProps->count_props;
- ++connectorPropIndex) {
- drmModePropertyPtr connectorProp = drmModeGetProperty(
- mFd.get(), connectorProps->props[connectorPropIndex]);
- if (!strcmp(connectorProp->name, "CRTC_ID")) {
- connector.mCrtcPropertyId = connectorProp->prop_id;
- } else if (!strcmp(connectorProp->name, "EDID")) {
- connector.mEdidBlobId =
- connectorProps->prop_values[connectorPropIndex];
- }
- drmModeFreeProperty(connectorProp);
- }
-
- drmModeFreeObjectProperties(connectorProps);
- }
- {
- drmModeConnector* c = drmModeGetConnector(mFd.get(), connector.mId);
- if (c == nullptr) {
- ALOGE("%s: Failed to get connector %" PRIu32 ": %d", __FUNCTION__,
- connector.mId, errno);
- return false;
- }
- connector.connection = c->connection;
- if (c->count_modes > 0) {
- memcpy(&connector.mMode, &c->modes[0], sizeof(drmModeModeInfo));
- drmModeCreatePropertyBlob(mFd.get(), &connector.mMode,
- sizeof(connector.mMode),
- &connector.mModeBlobId);
-
- // Dots per 1000 inches
- connector.dpiX =
- c->mmWidth ? (c->modes[0].hdisplay * kUmPerInch) / (c->mmWidth)
- : -1;
- // Dots per 1000 inches
- connector.dpiY =
- c->mmHeight ? (c->modes[0].vdisplay * kUmPerInch) / (c->mmHeight)
- : -1;
- }
- ALOGD("%s connector %" PRIu32 " dpiX %" PRIi32 " dpiY %" PRIi32
- " connection %d",
- __FUNCTION__, connector.mId, connector.dpiX, connector.dpiY,
- connector.connection);
-
- drmModeFreeConnector(c);
-
- connector.mRefreshRateAsFloat =
- 1000.0f * connector.mMode.clock /
- ((float)connector.mMode.vtotal * (float)connector.mMode.htotal);
- connector.mRefreshRateAsInteger =
- (uint32_t)(connector.mRefreshRateAsFloat + 0.5f);
- }
-
- mConnectors.push_back(connector);
- }
-
- drmModeFreeResources(res);
- return true;
-}
-
-void DrmPresenter::resetDrmElementsLocked() {
- for (auto& c : mConnectors) {
- if (c.mModeBlobId) {
- if (drmModeDestroyPropertyBlob(mFd.get(), c.mModeBlobId)) {
- ALOGE("%s: Error destroy PropertyBlob %" PRIu32, __func__,
- c.mModeBlobId);
- }
- }
- }
- mConnectors.clear();
- mCrtcs.clear();
- mPlanes.clear();
-}
-
-HWC2::Error DrmPresenter::getDisplayConfigs(std::vector<DisplayConfig>* configs) const {
- AutoReadLock lock(mStateMutex);
-
- configs->clear();
-
- for (uint32_t i = 0; i < mConnectors.size(); i++) {
- const auto& connector = mConnectors[i];
-
- if (connector.connection != DRM_MODE_CONNECTED) {
- continue;
- }
-
- configs->emplace_back(DisplayConfig{
- .id = i,
- .width = connector.mMode.hdisplay,
- .height = connector.mMode.vdisplay,
- .dpiX = 160, //static_cast<uint32_t>(connector.dpiX),
- .dpiY = 160, //static_cast<uint32_t>(connector.dpiY),
- .refreshRateHz = connector.mRefreshRateAsInteger,
- });
- }
-
- return HWC2::Error::None;
-}
-
-bool DrmPresenter::handleHotplug() {
- std::vector<DrmConnector> oldConnectors(mConnectors);
- {
- AutoReadLock lock(mStateMutex);
- oldConnectors.assign(mConnectors.begin(), mConnectors.end());
- }
- {
- AutoWriteLock lock(mStateMutex);
- resetDrmElementsLocked();
- if (!initDrmElementsLocked()) {
- ALOGE(
- "%s: failed to initialize drm elements during hotplug. Displays may "
- "not function correctly!",
- __FUNCTION__);
- return false;
- }
- }
-
- AutoReadLock lock(mStateMutex);
- for (int i = 0; i < mConnectors.size(); i++) {
- bool changed =
- oldConnectors[i].dpiX != mConnectors[i].dpiX ||
- oldConnectors[i].dpiY != mConnectors[i].dpiY ||
- oldConnectors[i].connection != mConnectors[i].connection ||
- oldConnectors[i].mMode.hdisplay != mConnectors[i].mMode.hdisplay ||
- oldConnectors[i].mMode.vdisplay != mConnectors[i].mMode.vdisplay;
- if (changed) {
- if (i == 0) {
- ALOGE(
- "%s: Ignoring changes to display:0 which is not configurable by "
- "multi-display interface.",
- __FUNCTION__);
- continue;
- }
-
- bool connected =
- mConnectors[i].connection == DRM_MODE_CONNECTED ? true : false;
- if (mHotplugCallback) {
- mHotplugCallback(connected, i, mConnectors[i].mMode.hdisplay,
- mConnectors[i].mMode.vdisplay, mConnectors[i].dpiX,
- mConnectors[i].dpiY,
- mConnectors[i].mRefreshRateAsInteger);
- }
- }
- }
- return true;
-}
-
-std::tuple<HWC2::Error, std::shared_ptr<DrmBuffer>> DrmPresenter::create(
- const native_handle_t* handle) {
- cros_gralloc_handle* crosHandle = (cros_gralloc_handle*)handle;
- if (crosHandle == nullptr) {
- ALOGE("%s: invalid cros_gralloc_handle", __FUNCTION__);
- return std::make_tuple(HWC2::Error::NoResources, nullptr);
- }
-
- DrmPrimeBufferHandle primeHandle = 0;
- int ret = drmPrimeFDToHandle(mFd.get(), crosHandle->fds[0], &primeHandle);
- if (ret) {
- ALOGE("%s: drmPrimeFDToHandle failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- return std::make_tuple(HWC2::Error::NoResources, nullptr);
- }
-
- auto drmBufferPtr = mBufferCache->get(primeHandle);
- if (drmBufferPtr != nullptr) {
- return std::make_tuple(HWC2::Error::None,
- std::shared_ptr<DrmBuffer>(*drmBufferPtr));
- }
-
- auto buffer = std::shared_ptr<DrmBuffer>(new DrmBuffer(*this));
- buffer->mWidth = crosHandle->width;
- buffer->mHeight = crosHandle->height;
- buffer->mDrmFormat = crosHandle->format;
- buffer->mPlaneFds[0] = crosHandle->fds[0];
- buffer->mPlaneHandles[0] = primeHandle;
- buffer->mPlanePitches[0] = crosHandle->strides[0];
- buffer->mPlaneOffsets[0] = crosHandle->offsets[0];
-
- uint32_t framebuffer = 0;
- ret = drmModeAddFB2(mFd.get(),
- buffer->mWidth,
- buffer->mHeight,
- buffer->mDrmFormat,
- buffer->mPlaneHandles,
- buffer->mPlanePitches,
- buffer->mPlaneOffsets,
- &framebuffer,
- 0);
- if (ret) {
- ALOGE("%s: drmModeAddFB2 failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- return std::make_tuple(HWC2::Error::NoResources, nullptr);
- }
- DEBUG_LOG("%s: created framebuffer:%" PRIu32, __FUNCTION__, framebuffer);
- buffer->mDrmFramebuffer = framebuffer;
-
- mBufferCache->set(primeHandle, std::shared_ptr<DrmBuffer>(buffer));
-
- return std::make_tuple(HWC2::Error::None,
- std::shared_ptr<DrmBuffer>(buffer));
-}
-
-HWC2::Error DrmPresenter::destroyDrmFramebuffer(DrmBuffer* buffer) {
- if (buffer->mDrmFramebuffer) {
- uint32_t framebuffer = *buffer->mDrmFramebuffer;
- if (drmModeRmFB(mFd.get(), framebuffer)) {
- ALOGE("%s: drmModeRmFB failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- return HWC2::Error::NoResources;
- }
- DEBUG_LOG("%s: destroyed framebuffer:%" PRIu32, __FUNCTION__, framebuffer);
- buffer->mDrmFramebuffer.reset();
- }
- if (buffer->mPlaneHandles[0]) {
- struct drm_gem_close gem_close = {};
- gem_close.handle = buffer->mPlaneHandles[0];
- if (drmIoctl(mFd.get(), DRM_IOCTL_GEM_CLOSE, &gem_close)) {
- ALOGE("%s: DRM_IOCTL_GEM_CLOSE failed: %s (errno %d)", __FUNCTION__,
- strerror(errno), errno);
- return HWC2::Error::NoResources;
- }
-
- mBufferCache->remove(buffer->mPlaneHandles[0]);
- }
-
- return HWC2::Error::None;
-}
-
-std::tuple<HWC2::Error, base::unique_fd> DrmPresenter::flushToDisplay(
- int display, const DrmBuffer& buffer, base::borrowed_fd inSyncFd) {
- ATRACE_CALL();
-
- if (!buffer.mDrmFramebuffer) {
- ALOGE("%s: failed, no framebuffer created.", __FUNCTION__);
- return std::make_tuple(HWC2::Error::NoResources,
- ::android::base::unique_fd());
- }
-
- AutoReadLock lock(mStateMutex);
-
- DrmConnector& connector = mConnectors[display];
- DrmCrtc& crtc = mCrtcs[display];
-
- HWC2::Error error = HWC2::Error::None;
-
- drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
-
- int ret;
-
- if (!crtc.mDidSetCrtc) {
- DEBUG_LOG("%s: Setting crtc.\n", __FUNCTION__);
- ret = drmModeAtomicAddProperty(pset, crtc.mId, crtc.mActivePropertyId, 1);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, crtc.mId, crtc.mModePropertyId,
- connector.mModeBlobId);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, connector.mId,
- connector.mCrtcPropertyId, crtc.mId);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
-
- crtc.mDidSetCrtc = true;
- } else {
- DEBUG_LOG("%s: Already set crtc\n", __FUNCTION__);
- }
-
- int rawOutSyncFd;
- uint64_t outSyncFdUint =
- static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&rawOutSyncFd));
-
- ret = drmModeAtomicAddProperty(pset, crtc.mId, crtc.mOutFencePtrPropertyId,
- outSyncFdUint);
- if (ret < 0) {
- ALOGE("%s:%d: set OUT_FENCE_PTR failed %d errno %d\n", __FUNCTION__,
- __LINE__, ret, errno);
- }
-
- if (crtc.mPlaneId == -1) {
- ALOGE("%s:%d: no plane available for crtc id %" PRIu32, __FUNCTION__,
- __LINE__, crtc.mId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- DrmPlane& plane = mPlanes[crtc.mPlaneId];
-
- DEBUG_LOG("%s: set plane: plane id %d crtc id %d fbid %d bo w h %d %d\n",
- __FUNCTION__, plane.mId, crtc.mId, *buffer.mDrmFramebuffer,
- buffer.mWidth, buffer.mHeight);
-
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcPropertyId,
- crtc.mId);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mInFenceFdPropertyId,
- inSyncFd.get());
- if (ret < 0) {
- ALOGE("%s:%d: set IN_FENCE_FD failed %d errno %d\n", __FUNCTION__, __LINE__,
- ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mFbPropertyId,
- *buffer.mDrmFramebuffer);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcXPropertyId, 0);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcYPropertyId, 0);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcWPropertyId,
- buffer.mWidth);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mCrtcHPropertyId,
- buffer.mHeight);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcXPropertyId, 0);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcYPropertyId, 0);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcWPropertyId,
- buffer.mWidth << 16);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
- ret = drmModeAtomicAddProperty(pset, plane.mId, plane.mSrcHPropertyId,
- buffer.mHeight << 16);
- if (ret < 0) {
- ALOGE("%s:%d: failed %d errno %d\n", __FUNCTION__, __LINE__, ret, errno);
- }
-
- uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
- ret = drmModeAtomicCommit(mFd.get(), pset, flags, 0);
-
- if (ret) {
- ALOGE("%s: Atomic commit failed with %d %d\n", __FUNCTION__, ret, errno);
- error = HWC2::Error::NoResources;
- }
- base::unique_fd outSyncFd(rawOutSyncFd);
-
- if (pset) {
- drmModeAtomicFree(pset);
- }
-
- DEBUG_LOG("%s: out fence: %d\n", __FUNCTION__, outSyncFd.get());
- return std::make_tuple(error, std::move(outSyncFd));
-}
-
-std::optional<std::vector<uint8_t>> DrmPresenter::getEdid(uint32_t id) {
- AutoReadLock lock(mStateMutex);
-
- if (mConnectors[id].mEdidBlobId == -1) {
- ALOGW("%s: EDID not supported", __func__);
- return std::nullopt;
- }
- drmModePropertyBlobPtr blob =
- drmModeGetPropertyBlob(mFd.get(), mConnectors[id].mEdidBlobId);
- if (!blob) {
- ALOGE("%s: fail to read EDID from DRM", __func__);
- return std::nullopt;
- }
-
- std::vector<uint8_t> edid;
- uint8_t* start = static_cast<uint8_t*>(blob->data);
- edid.insert(edid.begin(), start, start + blob->length);
-
- drmModeFreePropertyBlob(blob);
-
- return edid;
-}
-
-DrmPresenter::DrmEventListener::DrmEventListener(DrmPresenter& presenter)
- : mPresenter(presenter) {}
-
-DrmPresenter::DrmEventListener::~DrmEventListener() {}
-
-bool DrmPresenter::DrmEventListener::init() {
- mEventFd = android::base::unique_fd(
- socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT));
- if (!mEventFd.ok()) {
- ALOGE("Failed to open uevent socket: %s", strerror(errno));
- return false;
- }
- struct sockaddr_nl addr;
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
- addr.nl_pid = 0;
- addr.nl_groups = 0xFFFFFFFF;
-
- int ret = bind(mEventFd, (struct sockaddr*)&addr, sizeof(addr));
- if (ret) {
- ALOGE("Failed to bind uevent socket: %s", strerror(errno));
- return false;
- }
-
- FD_ZERO(&mMonitoredFds);
- FD_SET(mPresenter.mFd.get(), &mMonitoredFds);
- FD_SET(mEventFd.get(), &mMonitoredFds);
- mMaxFd = std::max(mPresenter.mFd.get(), mEventFd.get());
-
- return true;
-}
-
-bool DrmPresenter::DrmEventListener::threadLoop() {
- int ret;
- do {
- ret = select(mMaxFd + 1, &mMonitoredFds, NULL, NULL, NULL);
- } while (ret == -1 && errno == EINTR);
-
- // if (FD_ISSET(mPresenter.mFd, &mFds)) {
- // TODO: handle drm related events
- // }
-
- if (FD_ISSET(mEventFd.get(), &mMonitoredFds)) {
- eventThreadLoop();
- }
- return true;
-}
-
-void DrmPresenter::DrmEventListener::eventThreadLoop() {
- char buffer[1024];
- int ret;
-
- struct timespec ts;
- uint64_t timestamp = 0;
- ret = clock_gettime(CLOCK_MONOTONIC, &ts);
- if (!ret) {
- timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
- } else {
- ALOGE("Failed to get monotonic clock on hotplug %d", ret);
- }
-
- while (true) {
- ret = read(mEventFd.get(), &buffer, sizeof(buffer));
- if (ret == 0) {
- return;
- } else if (ret < 0) {
- ALOGE("Got error reading uevent %d", ret);
- return;
- }
-
- bool drmEvent = false, hotplugEvent = false;
- for (int i = 0; i < ret;) {
- char* event = buffer + i;
- if (strcmp(event, "DEVTYPE=drm_minor")) {
- drmEvent = true;
- } else if (strcmp(event, "HOTPLUG=1")) {
- hotplugEvent = true;
- }
-
- i += strlen(event) + 1;
- }
-
- if (drmEvent && hotplugEvent) {
- processHotplug(timestamp);
- }
- }
-}
-
-void DrmPresenter::DrmEventListener::processHotplug(uint64_t timestamp) {
- ALOGD("DrmEventListener detected hotplug event %" PRIu64, timestamp);
- mPresenter.handleHotplug();
-}
-} // namespace android
diff --git a/system/hwc2/DrmPresenter.h b/system/hwc2/DrmPresenter.h
deleted file mode 100644
index d42fbf7..0000000
--- a/system/hwc2/DrmPresenter.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright 2021 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_HWC_DRMPRESENTER_H
-#define ANDROID_HWC_DRMPRESENTER_H
-
-#include <android-base/unique_fd.h>
-#include <utils/Thread.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include <map>
-#include <memory>
-#include <tuple>
-#include <vector>
-
-#include "Common.h"
-#include "LruCache.h"
-#include "aemu/base/synchronization/AndroidLock.h"
-
-namespace android {
-
-class DrmBuffer;
-class DrmPresenter;
-
-// A RAII object that will clear a drm framebuffer upon destruction.
-class DrmBuffer {
- public:
- ~DrmBuffer();
-
- DrmBuffer(const DrmBuffer&) = delete;
- DrmBuffer& operator=(const DrmBuffer&) = delete;
-
- DrmBuffer(DrmBuffer&&) = delete;
- DrmBuffer& operator=(DrmBuffer&&) = delete;
-
- private:
- friend class DrmPresenter;
- DrmBuffer(DrmPresenter& drmPresenter);
-
- DrmPresenter& mDrmPresenter;
-
- uint32_t mWidth = 0;
- uint32_t mHeight = 0;
- uint32_t mDrmFormat = 0;
- uint32_t mPlaneFds[4] = {0, 0, 0, 0};
- uint32_t mPlaneHandles[4] = {0, 0, 0, 0};
- uint32_t mPlanePitches[4] = {0, 0, 0, 0};
- uint32_t mPlaneOffsets[4] = {0, 0, 0, 0};
-
- std::optional<uint32_t> mDrmFramebuffer;
-};
-
-class DrmPresenter {
- public:
- DrmPresenter() = default;
- ~DrmPresenter() = default;
-
- DrmPresenter(const DrmPresenter&) = delete;
- DrmPresenter& operator=(const DrmPresenter&) = delete;
-
- DrmPresenter(DrmPresenter&&) = delete;
- DrmPresenter& operator=(DrmPresenter&&) = delete;
-
- using HotplugCallback = std::function<void(
- bool /*connected*/, uint32_t /*id*/, uint32_t /*width*/,
- uint32_t /*height*/, uint32_t /*dpiX*/, uint32_t /*dpiY*/,
- uint32_t /*refreshRate*/)>;
-
- bool init(const HotplugCallback& cb);
-
- struct DisplayConfig {
- uint32_t id;
- uint32_t width;
- uint32_t height;
- uint32_t dpiX;
- uint32_t dpiY;
- uint32_t refreshRateHz;
- };
-
- HWC2::Error getDisplayConfigs(std::vector<DisplayConfig>* configs) const;
-
- uint32_t refreshRate(uint32_t display) const {
- if (display < mConnectors.size()) {
- return mConnectors[display].mRefreshRateAsInteger;
- }
-
- return -1;
- }
-
- std::tuple<HWC2::Error, std::shared_ptr<DrmBuffer>> create(
- const native_handle_t* handle);
-
- std::tuple<HWC2::Error, base::unique_fd> flushToDisplay(
- int display, const DrmBuffer& buffer, base::borrowed_fd inWaitSyncFd);
-
- std::optional<std::vector<uint8_t>> getEdid(uint32_t id);
-
- private:
- using DrmPrimeBufferHandle = uint32_t;
- using DrmBufferCache = LruCache<DrmPrimeBufferHandle, std::shared_ptr<DrmBuffer>>;
- std::unique_ptr<DrmBufferCache> mBufferCache;
-
- // Grant visibility for getDrmFB and clearDrmFB to DrmBuffer.
- // Grant visibility to destroyDrmFramebuffer to DrmBuffer.
- friend class DrmBuffer;
- HWC2::Error destroyDrmFramebuffer(DrmBuffer* buffer);
-
- // Grant visibility for handleHotplug to DrmEventListener.
- bool handleHotplug();
-
- bool initDrmElementsLocked();
- void resetDrmElementsLocked();
-
- // Drm device.
- android::base::unique_fd mFd;
-
- HotplugCallback mHotplugCallback;
-
- // Protects access to the below drm structs.
- mutable android::base::guest::ReadWriteLock mStateMutex;
-
- struct DrmPlane {
- uint32_t mId = -1;
- uint32_t mCrtcPropertyId = -1;
- uint32_t mInFenceFdPropertyId = -1;
- uint32_t mFbPropertyId = -1;
- uint32_t mCrtcXPropertyId = -1;
- uint32_t mCrtcYPropertyId = -1;
- uint32_t mCrtcWPropertyId = -1;
- uint32_t mCrtcHPropertyId = -1;
- uint32_t mSrcXPropertyId = -1;
- uint32_t mSrcYPropertyId = -1;
- uint32_t mSrcWPropertyId = -1;
- uint32_t mSrcHPropertyId = -1;
- uint32_t mTypePropertyId = -1;
- uint64_t mType = -1;
- };
- std::map<uint32_t, DrmPlane> mPlanes;
-
- struct DrmCrtc {
- uint32_t mId = -1;
- uint32_t mActivePropertyId = -1;
- uint32_t mModePropertyId = -1;
- uint32_t mOutFencePtrPropertyId = -1;
- uint32_t mPlaneId = -1;
-
- bool mDidSetCrtc = false;
- };
- std::vector<DrmCrtc> mCrtcs;
-
- struct DrmConnector {
- uint32_t mId = -1;
- uint32_t mCrtcPropertyId = -1;
- drmModeModeInfo mMode;
- int32_t dpiX;
- int32_t dpiY;
- drmModeConnection connection;
- uint32_t mModeBlobId = 0;
- float mRefreshRateAsFloat;
- uint32_t mRefreshRateAsInteger;
- uint64_t mEdidBlobId = -1;
- };
- std::vector<DrmConnector> mConnectors;
-
- class DrmEventListener : public Thread {
- public:
- DrmEventListener(DrmPresenter& presenter);
- virtual ~DrmEventListener();
-
- bool init();
-
- private:
- bool threadLoop() final;
- void eventThreadLoop();
- void processHotplug(uint64_t timestamp);
-
- DrmPresenter& mPresenter;
- android::base::unique_fd mEventFd;
- int mMaxFd;
- fd_set mMonitoredFds;
- };
- android::sp<DrmEventListener> mDrmEventListener;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/FencedBuffer.h b/system/hwc2/FencedBuffer.h
deleted file mode 100644
index 755eba9..0000000
--- a/system/hwc2/FencedBuffer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2021 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_HWC_FENCEDBUFFER_H
-#define ANDROID_HWC_FENCEDBUFFER_H
-
-#include <android-base/unique_fd.h>
-#include <cutils/native_handle.h>
-
-namespace android {
-
-class FencedBuffer {
- public:
- FencedBuffer() : mBuffer(nullptr) {}
-
- void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
- void setFence(base::unique_fd fence) { mFence = std::move(fence); }
-
- buffer_handle_t getBuffer() const { return mBuffer; }
- base::unique_fd getFence() const {
- if (mFence.ok()) {
- return base::unique_fd(dup(mFence.get()));
- } else {
- return base::unique_fd();
- }
- }
-
- private:
- buffer_handle_t mBuffer;
- android::base::unique_fd mFence;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/Gralloc.cpp b/system/hwc2/Gralloc.cpp
deleted file mode 100644
index ec33240..0000000
--- a/system/hwc2/Gralloc.cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2020 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 "Gralloc.h"
-
-#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
-#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
-#include <drm_fourcc.h>
-#include <gralloctypes/Gralloc4.h>
-#include <hidl/ServiceManagement.h>
-#include <log/log.h>
-
-#include <algorithm>
-
-#include "Drm.h"
-
-using aidl::android::hardware::graphics::common::PlaneLayout;
-using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
-using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
-using android::hardware::hidl_handle;
-using android::hardware::hidl_vec;
-using android::hardware::graphics::common::V1_2::BufferUsage;
-using android::hardware::graphics::mapper::V4_0::Error;
-using android::hardware::graphics::mapper::V4_0::IMapper;
-using MetadataType =
- android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
-
-namespace android {
-
-Gralloc::Gralloc() {
- android::hardware::preloadPassthroughService<IMapper>();
-
- gralloc4_ = IMapper::getService();
- if (gralloc4_ != nullptr) {
- ALOGE("%s using Gralloc4.", __FUNCTION__);
- return;
- }
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
-
- ALOGE("%s No Grallocs available!", __FUNCTION__);
-}
-
-Error Gralloc::GetMetadata(buffer_handle_t buffer, MetadataType type,
- hidl_vec<uint8_t>* metadata) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return Error::NO_RESOURCES;
- }
-
- if (metadata == nullptr) {
- return Error::BAD_VALUE;
- }
-
- Error error = Error::NONE;
-
- auto native_handle = const_cast<native_handle_t*>(buffer);
-
- auto ret =
- gralloc4_->get(native_handle, type,
- [&](const auto& get_error, const auto& get_metadata) {
- error = get_error;
- *metadata = get_metadata;
- });
-
- if (!ret.isOk()) {
- error = Error::NO_RESOURCES;
- }
-
- if (error != Error::NONE) {
- ALOGE("%s failed to get metadata %s", __FUNCTION__, type.name.c_str());
- }
- return error;
-}
-
-std::optional<uint32_t> Gralloc::GetWidth(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- hidl_vec<uint8_t> encoded_width;
-
- Error error = GetMetadata(buffer, android::gralloc4::MetadataType_Width,
- &encoded_width);
- if (error != Error::NONE) {
- return std::nullopt;
- }
-
- uint64_t width = 0;
- android::gralloc4::decodeWidth(encoded_width, &width);
- return static_cast<uint32_t>(width);
-}
-
-std::optional<uint32_t> Gralloc::GetHeight(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- hidl_vec<uint8_t> encoded_height;
-
- Error error = GetMetadata(buffer, android::gralloc4::MetadataType_Height,
- &encoded_height);
- if (error != Error::NONE) {
- return std::nullopt;
- }
-
- uint64_t height = 0;
- android::gralloc4::decodeHeight(encoded_height, &height);
- return static_cast<uint32_t>(height);
-}
-
-std::optional<uint32_t> Gralloc::GetDrmFormat(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- hidl_vec<uint8_t> encoded_format;
-
- Error error =
- GetMetadata(buffer, android::gralloc4::MetadataType_PixelFormatFourCC,
- &encoded_format);
- if (error != Error::NONE) {
- return std::nullopt;
- }
-
- uint32_t format = 0;
- android::gralloc4::decodePixelFormatFourCC(encoded_format, &format);
- return static_cast<uint32_t>(format);
-}
-
-std::optional<std::vector<PlaneLayout>> Gralloc::GetPlaneLayouts(
- buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- hidl_vec<uint8_t> encoded_layouts;
-
- Error error = GetMetadata(
- buffer, android::gralloc4::MetadataType_PlaneLayouts, &encoded_layouts);
- if (error != Error::NONE) {
- return std::nullopt;
- }
-
- std::vector<PlaneLayout> plane_layouts;
- android::gralloc4::decodePlaneLayouts(encoded_layouts, &plane_layouts);
- return plane_layouts;
-}
-
-std::optional<uint32_t> Gralloc::GetMonoPlanarStrideBytes(
- buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- auto plane_layouts_opt = GetPlaneLayouts(buffer);
- if (!plane_layouts_opt) {
- return std::nullopt;
- }
-
- std::vector<PlaneLayout>& plane_layouts = *plane_layouts_opt;
- if (plane_layouts.size() != 1) {
- return std::nullopt;
- }
-
- return static_cast<uint32_t>(plane_layouts[0].strideInBytes);
-}
-
-std::optional<GrallocBuffer> Gralloc::Import(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- buffer_handle_t imported_buffer;
-
- Error error;
- auto ret =
- gralloc4_->importBuffer(buffer, [&](const auto& err, const auto& buf) {
- error = err;
- if (err == Error::NONE) {
- imported_buffer = static_cast<buffer_handle_t>(buf);
- }
- });
-
- if (!ret.isOk() || error != Error::NONE) {
- ALOGE("%s failed to import buffer", __FUNCTION__);
- return std::nullopt;
- }
- return GrallocBuffer(this, imported_buffer);
-}
-
-void Gralloc::Release(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return;
- }
-
- auto native_buffer = const_cast<native_handle_t*>(buffer);
- auto ret = gralloc4_->freeBuffer(native_buffer);
-
- if (!ret.isOk()) {
- ALOGE("%s failed to release buffer", __FUNCTION__);
- }
-}
-
-std::optional<void*> Gralloc::Lock(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- auto native_buffer = const_cast<native_handle_t*>(buffer);
-
- const auto buffer_usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN |
- BufferUsage::CPU_WRITE_OFTEN);
-
- auto width_opt = GetWidth(buffer);
- if (!width_opt) {
- return std::nullopt;
- }
-
- auto height_opt = GetHeight(buffer);
- if (!height_opt) {
- return std::nullopt;
- }
-
- IMapper::Rect buffer_region;
- buffer_region.left = 0;
- buffer_region.top = 0;
- buffer_region.width = *width_opt;
- buffer_region.height = *height_opt;
-
- // Empty fence, lock immedietly.
- hidl_handle fence;
-
- Error error = Error::NONE;
- void* data = nullptr;
-
- auto ret =
- gralloc4_->lock(native_buffer, buffer_usage, buffer_region, fence,
- [&](const auto& lock_error, const auto& lock_data) {
- error = lock_error;
- if (lock_error == Error::NONE) {
- data = lock_data;
- }
- });
-
- if (!ret.isOk()) {
- error = Error::NO_RESOURCES;
- }
-
- if (error != Error::NONE) {
- ALOGE("%s failed to lock buffer", __FUNCTION__);
- return std::nullopt;
- }
-
- return data;
-}
-
-std::optional<android_ycbcr> Gralloc::LockYCbCr(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return std::nullopt;
- }
-
- auto format_opt = GetDrmFormat(buffer);
- if (!format_opt) {
- ALOGE("%s failed to check format of buffer", __FUNCTION__);
- return std::nullopt;
- }
-
- if (*format_opt != DRM_FORMAT_NV12 && *format_opt != DRM_FORMAT_NV21 &&
- *format_opt != DRM_FORMAT_YVU420) {
- ALOGE("%s called on non-ycbcr buffer", __FUNCTION__);
- return std::nullopt;
- }
-
- auto lock_opt = Lock(buffer);
- if (!lock_opt) {
- ALOGE("%s failed to lock buffer", __FUNCTION__);
- return std::nullopt;
- }
-
- auto plane_layouts_opt = GetPlaneLayouts(buffer);
- if (!plane_layouts_opt) {
- ALOGE("%s failed to get plane layouts", __FUNCTION__);
- return std::nullopt;
- }
-
- android_ycbcr buffer_ycbcr;
- buffer_ycbcr.y = nullptr;
- buffer_ycbcr.cb = nullptr;
- buffer_ycbcr.cr = nullptr;
- buffer_ycbcr.ystride = 0;
- buffer_ycbcr.cstride = 0;
- buffer_ycbcr.chroma_step = 0;
-
- for (const auto& plane_layout : *plane_layouts_opt) {
- for (const auto& plane_layout_component : plane_layout.components) {
- const auto& type = plane_layout_component.type;
-
- if (!android::gralloc4::isStandardPlaneLayoutComponentType(type)) {
- continue;
- }
-
- auto* component_data = reinterpret_cast<uint8_t*>(*lock_opt) +
- plane_layout.offsetInBytes +
- plane_layout_component.offsetInBits / 8;
-
- switch (static_cast<PlaneLayoutComponentType>(type.value)) {
- case PlaneLayoutComponentType::Y:
- buffer_ycbcr.y = component_data;
- buffer_ycbcr.ystride = plane_layout.strideInBytes;
- break;
- case PlaneLayoutComponentType::CB:
- buffer_ycbcr.cb = component_data;
- buffer_ycbcr.cstride = plane_layout.strideInBytes;
- buffer_ycbcr.chroma_step = plane_layout.sampleIncrementInBits / 8;
- break;
- case PlaneLayoutComponentType::CR:
- buffer_ycbcr.cr = component_data;
- buffer_ycbcr.cstride = plane_layout.strideInBytes;
- buffer_ycbcr.chroma_step = plane_layout.sampleIncrementInBits / 8;
- break;
- default:
- break;
- }
- }
- }
-
- return buffer_ycbcr;
-}
-
-void Gralloc::Unlock(buffer_handle_t buffer) {
- if (gralloc4_ == nullptr) {
- ALOGE("%s Gralloc4 not available.", __FUNCTION__);
- return;
- }
-
- auto native_handle = const_cast<native_handle_t*>(buffer);
-
- Error error = Error::NONE;
- auto ret = gralloc4_->unlock(
- native_handle,
- [&](const auto& unlock_error, const auto&) { error = unlock_error; });
-
- if (!ret.isOk()) {
- error = Error::NO_RESOURCES;
- }
-
- if (error != Error::NONE) {
- ALOGE("%s failed to unlock buffer", __FUNCTION__);
- }
-}
-
-GrallocBuffer::GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer)
- : gralloc_(gralloc), buffer_(buffer) {}
-
-GrallocBuffer::~GrallocBuffer() { Release(); }
-
-GrallocBuffer::GrallocBuffer(GrallocBuffer&& rhs) { *this = std::move(rhs); }
-
-GrallocBuffer& GrallocBuffer::operator=(GrallocBuffer&& rhs) {
- gralloc_ = rhs.gralloc_;
- buffer_ = rhs.buffer_;
- rhs.gralloc_ = nullptr;
- rhs.buffer_ = nullptr;
- return *this;
-}
-
-void GrallocBuffer::Release() {
- if (gralloc_ && buffer_) {
- gralloc_->Release(buffer_);
- gralloc_ = nullptr;
- buffer_ = nullptr;
- }
-}
-
-std::optional<GrallocBufferView> GrallocBuffer::Lock() {
- if (gralloc_ && buffer_) {
- auto format_opt = GetDrmFormat();
- if (!format_opt) {
- ALOGE("%s failed to check format of buffer", __FUNCTION__);
- return std::nullopt;
- }
- if (*format_opt != DRM_FORMAT_NV12 && *format_opt != DRM_FORMAT_NV21 &&
- *format_opt != DRM_FORMAT_YVU420) {
- auto locked_opt = gralloc_->Lock(buffer_);
- if (!locked_opt) {
- return std::nullopt;
- }
- return GrallocBufferView(this, *locked_opt);
- } else {
- auto locked_ycbcr_opt = gralloc_->LockYCbCr(buffer_);
- if (!locked_ycbcr_opt) {
- ALOGE("%s failed to lock ycbcr buffer", __FUNCTION__);
- return std::nullopt;
- }
- return GrallocBufferView(this, *locked_ycbcr_opt);
- }
- }
- return std::nullopt;
-}
-
-void GrallocBuffer::Unlock() {
- if (gralloc_ && buffer_) {
- gralloc_->Unlock(buffer_);
- }
-}
-
-std::optional<uint32_t> GrallocBuffer::GetWidth() {
- if (gralloc_ && buffer_) {
- return gralloc_->GetWidth(buffer_);
- }
- return std::nullopt;
-}
-
-std::optional<uint32_t> GrallocBuffer::GetHeight() {
- if (gralloc_ && buffer_) {
- return gralloc_->GetHeight(buffer_);
- }
- return std::nullopt;
-}
-
-std::optional<uint32_t> GrallocBuffer::GetDrmFormat() {
- if (gralloc_ && buffer_) {
- return gralloc_->GetDrmFormat(buffer_);
- }
- return std::nullopt;
-}
-
-std::optional<std::vector<PlaneLayout>> GrallocBuffer::GetPlaneLayouts() {
- if (gralloc_ && buffer_) {
- return gralloc_->GetPlaneLayouts(buffer_);
- }
- return std::nullopt;
-}
-
-std::optional<uint32_t> GrallocBuffer::GetMonoPlanarStrideBytes() {
- if (gralloc_ && buffer_) {
- return gralloc_->GetMonoPlanarStrideBytes(buffer_);
- }
- return std::nullopt;
-}
-
-GrallocBufferView::GrallocBufferView(GrallocBuffer* buffer, void* raw)
- : gralloc_buffer_(buffer), locked_(raw) {}
-
-GrallocBufferView::GrallocBufferView(GrallocBuffer* buffer, android_ycbcr raw)
- : gralloc_buffer_(buffer), locked_ycbcr_(raw) {}
-
-GrallocBufferView::~GrallocBufferView() {
- if (gralloc_buffer_) {
- gralloc_buffer_->Unlock();
- }
-}
-
-GrallocBufferView::GrallocBufferView(GrallocBufferView&& rhs) {
- *this = std::move(rhs);
-}
-
-GrallocBufferView& GrallocBufferView::operator=(GrallocBufferView&& rhs) {
- std::swap(gralloc_buffer_, rhs.gralloc_buffer_);
- std::swap(locked_, rhs.locked_);
- std::swap(locked_ycbcr_, rhs.locked_ycbcr_);
- return *this;
-}
-
-const std::optional<void*> GrallocBufferView::Get() const { return locked_; }
-
-const std::optional<android_ycbcr>& GrallocBufferView::GetYCbCr() const {
- return locked_ycbcr_;
-}
-
-} // namespace android
\ No newline at end of file
diff --git a/system/hwc2/Gralloc.h b/system/hwc2/Gralloc.h
deleted file mode 100644
index 9cb5153..0000000
--- a/system/hwc2/Gralloc.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2020 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_HWC_GRALLOC_H
-#define ANDROID_HWC_GRALLOC_H
-
-#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
-#include <android/hardware/graphics/mapper/4.0/IMapper.h>
-#include <hardware/gralloc.h>
-#include <system/graphics.h>
-#include <utils/StrongPointer.h>
-
-#include <memory>
-#include <optional>
-#include <vector>
-
-namespace android {
-
-class Gralloc;
-class GrallocBuffer;
-
-// An RAII object that will Unlock() a GrallocBuffer upon destruction.
-class GrallocBufferView {
- public:
- virtual ~GrallocBufferView();
-
- GrallocBufferView(const GrallocBufferView& rhs) = delete;
- GrallocBufferView& operator=(const GrallocBufferView& rhs) = delete;
-
- GrallocBufferView(GrallocBufferView&& rhs);
- GrallocBufferView& operator=(GrallocBufferView&& rhs);
-
- const std::optional<void*> Get() const;
-
- const std::optional<android_ycbcr>& GetYCbCr() const;
-
- private:
- friend class GrallocBuffer;
- GrallocBufferView(GrallocBuffer* buffer, void* raw);
- GrallocBufferView(GrallocBuffer* buffer, android_ycbcr raw);
-
- // The GrallocBuffer that should be unlocked upon destruction of this object.
- GrallocBuffer* gralloc_buffer_ = nullptr;
-
- std::optional<void*> locked_;
- std::optional<android_ycbcr> locked_ycbcr_;
-};
-
-// A gralloc 4.0 buffer that has been imported in the current process and
-// that will be released upon destruction. Users must ensure that the Gralloc
-// instance that this buffer is created with out lives this buffer.
-class GrallocBuffer {
- public:
- GrallocBuffer(Gralloc* gralloc, buffer_handle_t buffer);
- virtual ~GrallocBuffer();
-
- GrallocBuffer(const GrallocBuffer& rhs) = delete;
- GrallocBuffer& operator=(const GrallocBuffer& rhs) = delete;
-
- GrallocBuffer(GrallocBuffer&& rhs);
- GrallocBuffer& operator=(GrallocBuffer&& rhs);
-
- // Locks the buffer for reading and returns a view if successful.
- std::optional<GrallocBufferView> Lock();
-
- std::optional<uint32_t> GetWidth();
- std::optional<uint32_t> GetHeight();
- std::optional<uint32_t> GetDrmFormat();
-
- // Returns the stride of the buffer if it is a single plane buffer or fails
- // and returns nullopt if the buffer is for a multi plane buffer.
- std::optional<uint32_t> GetMonoPlanarStrideBytes();
-
- std::optional<
- std::vector<aidl::android::hardware::graphics::common::PlaneLayout>>
- GetPlaneLayouts();
-
- private:
- // Internal visibility for Unlock().
- friend class GrallocBufferView;
-
- // Unlocks the buffer from reading.
- void Unlock();
-
- void Release();
-
- Gralloc* gralloc_ = nullptr;
- buffer_handle_t buffer_ = nullptr;
-};
-
-class Gralloc {
- public:
- Gralloc();
- virtual ~Gralloc() = default;
-
- // Imports the given buffer handle into the current process and returns an
- // imported buffer which can be used for reading. Users must ensure that the
- // Gralloc instance outlives any GrallocBuffers.
- std::optional<GrallocBuffer> Import(buffer_handle_t buffer);
-
- private:
- // The below functions are made avaialble only to GrallocBuffer so that
- // users only call gralloc functions on *imported* buffers.
- friend class GrallocBuffer;
-
- // See GrallocBuffer::Release.
- void Release(buffer_handle_t buffer);
-
- // See GrallocBuffer::Lock.
- std::optional<void*> Lock(buffer_handle_t buffer);
-
- // See GrallocBuffer::LockYCbCr.
- std::optional<android_ycbcr> LockYCbCr(buffer_handle_t buffer);
-
- // See GrallocBuffer::Unlock.
- void Unlock(buffer_handle_t buffer);
-
- // See GrallocBuffer::GetWidth.
- std::optional<uint32_t> GetWidth(buffer_handle_t buffer);
-
- // See GrallocBuffer::GetHeight.
- std::optional<uint32_t> GetHeight(buffer_handle_t buffer);
-
- // See GrallocBuffer::GetDrmFormat.
- std::optional<uint32_t> GetDrmFormat(buffer_handle_t buffer);
-
- // See GrallocBuffer::GetPlaneLayouts.
- std::optional<
- std::vector<aidl::android::hardware::graphics::common::PlaneLayout>>
- GetPlaneLayouts(buffer_handle_t buffer);
-
- // Returns the stride of the buffer if it is a single plane buffer or fails
- // and returns nullopt if the buffer is for a multi plane buffer.
- std::optional<uint32_t> GetMonoPlanarStrideBytes(buffer_handle_t);
-
- // See GrallocBuffer::GetMetadata.
- android::hardware::graphics::mapper::V4_0::Error GetMetadata(
- buffer_handle_t buffer,
- android::hardware::graphics::mapper::V4_0::IMapper::MetadataType type,
- android::hardware::hidl_vec<uint8_t>* metadata);
-
- android::sp<android::hardware::graphics::mapper::V4_0::IMapper> gralloc4_;
-};
-
-} // namespace android
-
-#endif
\ No newline at end of file
diff --git a/system/hwc2/GuestComposer.cpp b/system/hwc2/GuestComposer.cpp
deleted file mode 100644
index 2c91192..0000000
--- a/system/hwc2/GuestComposer.cpp
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * Copyright 2021 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 "GuestComposer.h"
-
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <device_config_shared.h>
-#include <drm_fourcc.h>
-#include <libyuv.h>
-#include <sync/sync.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
-#include <ui/GraphicBufferMapper.h>
-
-#include "Device.h"
-#include "Display.h"
-#include "Drm.h"
-#include "Layer.h"
-
-namespace android {
-namespace {
-
-using android::hardware::graphics::common::V1_0::ColorTransform;
-
-uint64_t AlignToPower2(uint64_t val, uint8_t align_log) {
- uint64_t align = 1ULL << align_log;
- return ((val + (align - 1)) / align) * align;
-}
-
-bool LayerNeedsScaling(const Layer& layer) {
- hwc_rect_t crop = layer.getSourceCropInt();
- hwc_rect_t frame = layer.getDisplayFrame();
-
- int fromW = crop.right - crop.left;
- int fromH = crop.bottom - crop.top;
- int toW = frame.right - frame.left;
- int toH = frame.bottom - frame.top;
-
- bool not_rot_scale = fromW != toW || fromH != toH;
- bool rot_scale = fromW != toH || fromH != toW;
-
- bool needs_rot = layer.getTransform() & HAL_TRANSFORM_ROT_90;
-
- return needs_rot ? rot_scale : not_rot_scale;
-}
-
-bool LayerNeedsBlending(const Layer& layer) {
- return layer.getBlendMode() != HWC2::BlendMode::None;
-}
-
-bool LayerNeedsAttenuation(const Layer& layer) {
- return layer.getBlendMode() == HWC2::BlendMode::Coverage;
-}
-
-struct BufferSpec;
-typedef int (*ConverterFunction)(const BufferSpec& src, const BufferSpec& dst,
- bool v_flip);
-int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool vFlip);
-int ConvertFromRGB565(const BufferSpec& src, const BufferSpec& dst, bool vFlip);
-int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool vFlip);
-
-ConverterFunction GetConverterForDrmFormat(uint32_t drmFormat) {
- switch (drmFormat) {
- case DRM_FORMAT_ABGR8888:
- case DRM_FORMAT_XBGR8888:
- return &DoCopy;
- case DRM_FORMAT_RGB565:
- return &ConvertFromRGB565;
- case DRM_FORMAT_YVU420:
- return &ConvertFromYV12;
- }
- DEBUG_LOG("Unsupported drm format: %d(%s), returning null converter",
- drmFormat, GetDrmFormatString(drmFormat));
- return nullptr;
-}
-
-bool IsDrmFormatSupported(uint32_t drmFormat) {
- return GetConverterForDrmFormat(drmFormat) != nullptr;
-}
-
-// Libyuv's convert functions only allow the combination of any rotation
-// (multiple of 90 degrees) and a vertical flip, but not horizontal flips.
-// Surfaceflinger's transformations are expressed in terms of a vertical flip,
-// a horizontal flip and/or a single 90 degrees clockwise rotation (see
-// NATIVE_WINDOW_TRANSFORM_HINT documentation on system/window.h for more
-// insight). The following code allows to turn a horizontal flip into a 180
-// degrees rotation and a vertical flip.
-libyuv::RotationMode GetRotationFromTransform(uint32_t transform) {
- uint32_t rotation =
- (transform & HAL_TRANSFORM_ROT_90) ? 1 : 0; // 1 * ROT90 bit
- rotation += (transform & HAL_TRANSFORM_FLIP_H) ? 2 : 0; // 2 * VFLIP bit
- return static_cast<libyuv::RotationMode>(90 * rotation);
-}
-
-bool GetVFlipFromTransform(uint32_t transform) {
- // vertical flip xor horizontal flip
- return ((transform & HAL_TRANSFORM_FLIP_V) >> 1) ^
- (transform & HAL_TRANSFORM_FLIP_H);
-}
-
-struct BufferSpec {
- uint8_t* buffer;
- std::optional<android_ycbcr> buffer_ycbcr;
- int width;
- int height;
- int cropX;
- int cropY;
- int cropWidth;
- int cropHeight;
- uint32_t drmFormat;
- int strideBytes;
- int sampleBytes;
-
- BufferSpec(uint8_t* buffer, std::optional<android_ycbcr> buffer_ycbcr,
- int width, int height, int cropX, int cropY, int cropWidth,
- int cropHeight, uint32_t drmFormat, int strideBytes,
- int sampleBytes)
- : buffer(buffer),
- buffer_ycbcr(buffer_ycbcr),
- width(width),
- height(height),
- cropX(cropX),
- cropY(cropY),
- cropWidth(cropWidth),
- cropHeight(cropHeight),
- drmFormat(drmFormat),
- strideBytes(strideBytes),
- sampleBytes(sampleBytes) {}
-
- BufferSpec(uint8_t* buffer, int width, int height, int strideBytes)
- : BufferSpec(buffer,
- /*buffer_ycbcr=*/std::nullopt, width, height,
- /*cropX=*/0,
- /*cropY=*/0,
- /*cropWidth=*/width,
- /*cropHeight=*/height,
- /*drmFormat=*/DRM_FORMAT_ABGR8888, strideBytes,
- /*sampleBytes=*/4) {}
-};
-
-int ConvertFromRGB565(const BufferSpec& src, const BufferSpec& dst,
- bool vFlip) {
- ATRACE_CALL();
-
- // Point to the upper left corner of the crop rectangle
- uint8_t* srcBuffer =
- src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
-
- int width = src.cropWidth;
- int height = src.cropHeight;
- if (vFlip) {
- height = -height;
- }
-
- return libyuv::RGB565ToARGB(srcBuffer, src.strideBytes, //
- dstBuffer, dst.strideBytes, //
- width, height);
-}
-
-int ConvertFromYV12(const BufferSpec& src, const BufferSpec& dst, bool vFlip) {
- ATRACE_CALL();
-
- // The following calculation of plane offsets and alignments are based on
- // swiftshader's Sampler::setTextureLevel() implementation
- // (Renderer/Sampler.cpp:225)
-
- auto& srcBufferYCbCrOpt = src.buffer_ycbcr;
- if (!srcBufferYCbCrOpt) {
- ALOGE("%s called on non ycbcr buffer", __FUNCTION__);
- return -1;
- }
- auto& srcBufferYCbCr = *srcBufferYCbCrOpt;
-
- // The libyuv::I420ToARGB() function is for tri-planar.
- if (srcBufferYCbCr.chroma_step != 1) {
- ALOGE("%s called with bad chroma step", __FUNCTION__);
- return -1;
- }
-
- uint8_t* srcY = reinterpret_cast<uint8_t*>(srcBufferYCbCr.y);
- int strideY = srcBufferYCbCr.ystride;
- uint8_t* srcU = reinterpret_cast<uint8_t*>(srcBufferYCbCr.cb);
- int strideU = srcBufferYCbCr.cstride;
- uint8_t* srcV = reinterpret_cast<uint8_t*>(srcBufferYCbCr.cr);
- int strideV = srcBufferYCbCr.cstride;
-
- // Adjust for crop
- srcY += src.cropY * strideY + src.cropX;
- srcV += (src.cropY / 2) * strideV + (src.cropX / 2);
- srcU += (src.cropY / 2) * strideU + (src.cropX / 2);
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
-
- int width = dst.cropWidth;
- int height = dst.cropHeight;
-
- if (vFlip) {
- height = -height;
- }
-
- // YV12 is the same as I420, with the U and V planes swapped
- return libyuv::I420ToARGB(srcY, strideY, srcV, strideV, srcU, strideU,
- dstBuffer, dst.strideBytes, width, height);
-}
-
-int DoConversion(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
- ConverterFunction func = GetConverterForDrmFormat(src.drmFormat);
- if (!func) {
- // GetConverterForDrmFormat should've logged the issue for us.
- return -1;
- }
- return func(src, dst, v_flip);
-}
-
-int DoCopy(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
- ATRACE_CALL();
-
- // Point to the upper left corner of the crop rectangle
- uint8_t* srcBuffer =
- src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
- int width = src.cropWidth;
- int height = src.cropHeight;
-
- if (v_flip) {
- height = -height;
- }
-
- // HAL formats are named based on the order of the pixel components on the
- // byte stream, while libyuv formats are named based on the order of those
- // pixel components in an integer written from left to right. So
- // libyuv::FOURCC_ARGB is equivalent to HAL_PIXEL_FORMAT_BGRA_8888.
- auto ret = libyuv::ARGBCopy(srcBuffer, src.strideBytes, dstBuffer,
- dst.strideBytes, width, height);
- return ret;
-}
-
-int DoRotation(const BufferSpec& src, const BufferSpec& dst,
- libyuv::RotationMode rotation, bool v_flip) {
- ATRACE_CALL();
-
- // Point to the upper left corner of the crop rectangles
- uint8_t* srcBuffer =
- src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
- int width = src.cropWidth;
- int height = src.cropHeight;
-
- if (v_flip) {
- height = -height;
- }
-
- return libyuv::ARGBRotate(srcBuffer, src.strideBytes, dstBuffer,
- dst.strideBytes, width, height, rotation);
-}
-
-int DoScaling(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
- ATRACE_CALL();
-
- // Point to the upper left corner of the crop rectangles
- uint8_t* srcBuffer =
- src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
- int srcWidth = src.cropWidth;
- int srcHeight = src.cropHeight;
- int dstWidth = dst.cropWidth;
- int dstHeight = dst.cropHeight;
-
- if (v_flip) {
- srcHeight = -srcHeight;
- }
-
- return libyuv::ARGBScale(srcBuffer, src.strideBytes, srcWidth, srcHeight,
- dstBuffer, dst.strideBytes, dstWidth, dstHeight,
- libyuv::kFilterBilinear);
-}
-
-int DoAttenuation(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
- ATRACE_CALL();
-
- // Point to the upper left corner of the crop rectangles
- uint8_t* srcBuffer =
- src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
- int width = dst.cropWidth;
- int height = dst.cropHeight;
-
- if (v_flip) {
- height = -height;
- }
-
- return libyuv::ARGBAttenuate(srcBuffer, src.strideBytes, dstBuffer,
- dst.strideBytes, width, height);
-}
-
-int DoBlending(const BufferSpec& src, const BufferSpec& dst, bool v_flip) {
- ATRACE_CALL();
-
- // Point to the upper left corner of the crop rectangles
- uint8_t* srcBuffer =
- src.buffer + src.cropY * src.strideBytes + src.cropX * src.sampleBytes;
- uint8_t* dstBuffer =
- dst.buffer + dst.cropY * dst.strideBytes + dst.cropX * dst.sampleBytes;
- int width = dst.cropWidth;
- int height = dst.cropHeight;
-
- if (v_flip) {
- height = -height;
- }
-
- // libyuv's ARGB format is hwcomposer's BGRA format, since blending only cares
- // for the position of alpha in the pixel and not the position of the colors
- // this function is perfectly usable.
- return libyuv::ARGBBlend(srcBuffer, src.strideBytes, dstBuffer,
- dst.strideBytes, dstBuffer, dst.strideBytes, width,
- height);
-}
-
-std::optional<BufferSpec> GetBufferSpec(GrallocBuffer& buffer,
- GrallocBufferView& bufferView,
- const hwc_rect_t& bufferCrop) {
- auto bufferFormatOpt = buffer.GetDrmFormat();
- if (!bufferFormatOpt) {
- ALOGE("Failed to get gralloc buffer format.");
- return std::nullopt;
- }
- uint32_t bufferFormat = *bufferFormatOpt;
-
- auto bufferWidthOpt = buffer.GetWidth();
- if (!bufferWidthOpt) {
- ALOGE("Failed to get gralloc buffer width.");
- return std::nullopt;
- }
- uint32_t bufferWidth = *bufferWidthOpt;
-
- auto bufferHeightOpt = buffer.GetHeight();
- if (!bufferHeightOpt) {
- ALOGE("Failed to get gralloc buffer height.");
- return std::nullopt;
- }
- uint32_t bufferHeight = *bufferHeightOpt;
-
- uint8_t* bufferData = nullptr;
- uint32_t bufferStrideBytes = 0;
- std::optional<android_ycbcr> bufferYCbCrData;
-
- if (bufferFormat == DRM_FORMAT_NV12 || bufferFormat == DRM_FORMAT_NV21 ||
- bufferFormat == DRM_FORMAT_YVU420) {
- bufferYCbCrData = bufferView.GetYCbCr();
- if (!bufferYCbCrData) {
- ALOGE("%s failed to get raw ycbcr from view.", __FUNCTION__);
- return std::nullopt;
- }
- } else {
- auto bufferDataOpt = bufferView.Get();
- if (!bufferDataOpt) {
- ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
- return std::nullopt;
- }
- bufferData = reinterpret_cast<uint8_t*>(*bufferDataOpt);
-
- auto bufferStrideBytesOpt = buffer.GetMonoPlanarStrideBytes();
- if (!bufferStrideBytesOpt) {
- ALOGE("%s failed to get plane stride.", __FUNCTION__);
- return std::nullopt;
- }
- bufferStrideBytes = *bufferStrideBytesOpt;
- }
-
- return BufferSpec(bufferData, bufferYCbCrData, bufferWidth, bufferHeight,
- bufferCrop.left, bufferCrop.top,
- bufferCrop.right - bufferCrop.left,
- bufferCrop.bottom - bufferCrop.top, bufferFormat,
- bufferStrideBytes, GetDrmFormatBytesPerPixel(bufferFormat));
-}
-
-} // namespace
-
-GuestComposer::GuestComposer(DrmPresenter* drmPresenter)
- : mDrmPresenter(drmPresenter) {}
-
-HWC2::Error GuestComposer::init() {
- DEBUG_LOG("%s", __FUNCTION__);
- return HWC2::Error::None;
-}
-
-HWC2::Error GuestComposer::onDisplayCreate(Display* display) {
- hwc2_display_t displayId = display->getId();
- hwc2_config_t displayConfigId;
- int32_t displayWidth;
- int32_t displayHeight;
-
- HWC2::Error error = display->getActiveConfig(&displayConfigId);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " has no active config", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(
- displayConfigId, HWC2::Attribute::Width, &displayWidth);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get width", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(
- displayConfigId, HWC2::Attribute::Height, &displayHeight);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
- displayId);
- return error;
- }
-
- auto it = mDisplayInfos.find(displayId);
- if (it != mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " already created?", __FUNCTION__, displayId);
- }
-
- GuestComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
-
- uint32_t bufferStride;
- buffer_handle_t bufferHandle;
-
- auto status = GraphicBufferAllocator::get().allocate(
- displayWidth, //
- displayHeight, //
- PIXEL_FORMAT_RGBA_8888, //
- /*layerCount=*/1, //
- GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_SW_READ_OFTEN |
- GraphicBuffer::USAGE_SW_WRITE_OFTEN, //
- &bufferHandle, //
- &bufferStride, //
- "RanchuHwc");
- if (status != OK) {
- ALOGE("%s failed to allocate composition buffer for display:%" PRIu64,
- __FUNCTION__, displayId);
- return HWC2::Error::NoResources;
- }
-
- displayInfo.compositionResultBuffer = bufferHandle;
-
- auto [drmBufferCreateError, drmBuffer] = mDrmPresenter->create(bufferHandle);
- if (drmBufferCreateError != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer",
- __FUNCTION__, displayId);
- return HWC2::Error::NoResources;
- }
- displayInfo.compositionResultDrmBuffer = std::move(drmBuffer);
-
- if (displayId == 0) {
- auto [flushError, flushSyncFd] = mDrmPresenter->flushToDisplay(
- displayId, *displayInfo.compositionResultDrmBuffer, -1);
- if (flushError != HWC2::Error::None) {
- ALOGW(
- "%s: Initial display flush failed. HWComposer assuming that we are "
- "running in QEMU without a display and disabling presenting.",
- __FUNCTION__);
- mPresentDisabled = true;
- }
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error GuestComposer::onDisplayDestroy(Display* display) {
- auto displayId = display->getId();
-
- auto it = mDisplayInfos.find(displayId);
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__,
- displayId);
- return HWC2::Error::BadDisplay;
- }
-
- GuestComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
-
- GraphicBufferAllocator::get().free(displayInfo.compositionResultBuffer);
-
- mDisplayInfos.erase(it);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error GuestComposer::getDisplayConfigsFromDeviceConfig(
- std::vector<GuestComposer::DisplayConfig>* configs) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- const auto deviceConfig = cuttlefish::GetDeviceConfig();
- for (const auto& deviceDisplayConfig : deviceConfig.display_config()) {
- DisplayConfig displayConfig = {
- .width = deviceDisplayConfig.width(),
- .height = deviceDisplayConfig.height(),
- .dpiX = deviceDisplayConfig.dpi(),
- .dpiY = deviceDisplayConfig.dpi(),
- .refreshRateHz = deviceDisplayConfig.refresh_rate_hz(),
- };
-
- configs->push_back(displayConfig);
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error GuestComposer::getDisplayConfigsFromSystemProp(
- std::vector<GuestComposer::DisplayConfig>* configs) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- static constexpr const char kExternalDisplayProp[] =
- "hwservicemanager.external.displays";
-
- const auto propString = android::base::GetProperty(kExternalDisplayProp, "");
- DEBUG_LOG("%s: prop value is: %s", __FUNCTION__, propString.c_str());
-
- if (propString.empty()) {
- return HWC2::Error::None;
- }
-
- const std::vector<std::string> propStringParts =
- android::base::Split(propString, ",");
- if (propStringParts.size() % 5 != 0) {
- ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
- kExternalDisplayProp, propString.c_str());
- return HWC2::Error::BadParameter;
- }
-
- std::vector<int> propIntParts;
- for (const std::string& propStringPart : propStringParts) {
- int propIntPart;
- if (!android::base::ParseInt(propStringPart, &propIntPart)) {
- ALOGE("%s: Invalid syntax for system prop %s which is %s", __FUNCTION__,
- kExternalDisplayProp, propString.c_str());
- return HWC2::Error::BadParameter;
- }
- propIntParts.push_back(propIntPart);
- }
-
- while (!propIntParts.empty()) {
- DisplayConfig display_config = {
- .width = propIntParts[1],
- .height = propIntParts[2],
- .dpiX = propIntParts[3],
- .dpiY = propIntParts[3],
- .refreshRateHz = 160,
- };
-
- configs->push_back(display_config);
-
- propIntParts.erase(propIntParts.begin(), propIntParts.begin() + 5);
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error GuestComposer::validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- outLayerCompositionChanges) {
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- const std::vector<Layer*>& layers = display->getOrderedLayers();
-
- bool fallbackToClientComposition = false;
- for (Layer* layer : layers) {
- const auto layerId = layer->getId();
- const auto layerCompositionType = layer->getCompositionType();
- const auto layerCompositionTypeString = to_string(layerCompositionType);
-
- if (layerCompositionType == HWC2::Composition::Invalid) {
- ALOGE("%s display:%" PRIu64 " layer:%" PRIu64 " has Invalid composition",
- __FUNCTION__, displayId, layerId);
- continue;
- }
-
- if (layerCompositionType == HWC2::Composition::Client ||
- layerCompositionType == HWC2::Composition::Cursor ||
- layerCompositionType == HWC2::Composition::Sideband ||
- layerCompositionType == HWC2::Composition::SolidColor) {
- DEBUG_LOG("%s: display:%" PRIu64 " layer:%" PRIu64
- " has composition type %s, falling back to client composition",
- __FUNCTION__, displayId, layerId,
- layerCompositionTypeString.c_str());
- fallbackToClientComposition = true;
- break;
- }
-
- if (!canComposeLayer(layer)) {
- DEBUG_LOG(
- "%s: display:%" PRIu64 " layer:%" PRIu64
- " composition not supported, falling back to client composition",
- __FUNCTION__, displayId, layerId);
- fallbackToClientComposition = true;
- break;
- }
- }
-
- if (fallbackToClientComposition) {
- for (Layer* layer : layers) {
- const auto layerId = layer->getId();
- const auto layerCompositionType = layer->getCompositionType();
-
- if (layerCompositionType == HWC2::Composition::Invalid) {
- continue;
- }
- if (layerCompositionType != HWC2::Composition::Client) {
- DEBUG_LOG("%s display:%" PRIu64 " layer:%" PRIu64
- "composition updated to Client",
- __FUNCTION__, displayId, layerId);
- (*outLayerCompositionChanges)[layerId] = HWC2::Composition::Client;
- }
- }
- }
-
- // We can not draw below a Client (SurfaceFlinger) composed layer. Change all
- // layers below a Client composed layer to also be Client composed.
- if (layers.size() > 1) {
- for (std::size_t layerIndex = layers.size() - 1; layerIndex > 0;
- layerIndex--) {
- auto layer = layers[layerIndex];
- auto layerCompositionType = layer->getCompositionType();
-
- if (layerCompositionType == HWC2::Composition::Client) {
- for (std::size_t lowerLayerIndex = 0; lowerLayerIndex < layerIndex;
- lowerLayerIndex++) {
- auto lowerLayer = layers[lowerLayerIndex];
- auto lowerLayerId = lowerLayer->getId();
- auto lowerLayerCompositionType = lowerLayer->getCompositionType();
-
- if (lowerLayerCompositionType != HWC2::Composition::Client) {
- DEBUG_LOG("%s: display:%" PRIu64 " changing layer:%" PRIu64
- " to Client because"
- "hwcomposer can not draw below the Client composed "
- "layer:%" PRIu64,
- __FUNCTION__, displayId, lowerLayerId, layer->getId());
-
- (*outLayerCompositionChanges)[lowerLayerId] =
- HWC2::Composition::Client;
- }
- }
- }
- }
- }
-
- return HWC2::Error::None;
-}
-
-std::tuple<HWC2::Error, base::unique_fd> GuestComposer::presentDisplay(
- Display* display) {
- ATRACE_CALL();
-
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- if (mPresentDisabled) {
- return std::make_tuple(HWC2::Error::None, base::unique_fd());
- }
-
- auto it = mDisplayInfos.find(displayId);
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " not found", __FUNCTION__, displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- GuestComposerDisplayInfo& displayInfo = it->second;
-
- if (displayInfo.compositionResultBuffer == nullptr) {
- ALOGE("%s: display:%" PRIu64 " missing composition result buffer",
- __FUNCTION__, displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- std::optional<GrallocBuffer> compositionResultBufferOpt =
- mGralloc.Import(displayInfo.compositionResultBuffer);
- if (!compositionResultBufferOpt) {
- ALOGE("%s: display:%" PRIu64 " failed to import buffer", __FUNCTION__,
- displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- std::optional<uint32_t> compositionResultBufferWidthOpt =
- compositionResultBufferOpt->GetWidth();
- if (!compositionResultBufferWidthOpt) {
- ALOGE("%s: display:%" PRIu64 " failed to query buffer width", __FUNCTION__,
- displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- std::optional<uint32_t> compositionResultBufferHeightOpt =
- compositionResultBufferOpt->GetHeight();
- if (!compositionResultBufferHeightOpt) {
- ALOGE("%s: display:%" PRIu64 " failed to query buffer height", __FUNCTION__,
- displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- std::optional<uint32_t> compositionResultBufferStrideOpt =
- compositionResultBufferOpt->GetMonoPlanarStrideBytes();
- if (!compositionResultBufferStrideOpt) {
- ALOGE("%s: display:%" PRIu64 " failed to query buffer stride", __FUNCTION__,
- displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- std::optional<GrallocBufferView> compositionResultBufferViewOpt =
- compositionResultBufferOpt->Lock();
- if (!compositionResultBufferViewOpt) {
- ALOGE("%s: display:%" PRIu64 " failed to get buffer view", __FUNCTION__,
- displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- const std::optional<void*> compositionResultBufferDataOpt =
- compositionResultBufferViewOpt->Get();
- if (!compositionResultBufferDataOpt) {
- ALOGE("%s: display:%" PRIu64 " failed to get buffer data", __FUNCTION__,
- displayId);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- uint32_t compositionResultBufferWidth = *compositionResultBufferWidthOpt;
- uint32_t compositionResultBufferHeight = *compositionResultBufferHeightOpt;
- uint32_t compositionResultBufferStride = *compositionResultBufferStrideOpt;
- uint8_t* compositionResultBufferData =
- reinterpret_cast<uint8_t*>(*compositionResultBufferDataOpt);
-
- const std::vector<Layer*>& layers = display->getOrderedLayers();
-
- const bool noOpComposition = layers.empty();
- const bool allLayersClientComposed = std::all_of(
- layers.begin(), //
- layers.end(), //
- [](const Layer* layer) {
- return layer->getCompositionType() == HWC2::Composition::Client;
- });
-
- if (noOpComposition) {
- ALOGW("%s: display:%" PRIu64 " empty composition", __FUNCTION__, displayId);
- } else if (allLayersClientComposed) {
- auto clientTargetBufferOpt =
- mGralloc.Import(display->waitAndGetClientTargetBuffer());
- if (!clientTargetBufferOpt) {
- ALOGE("%s: failed to import client target buffer.", __FUNCTION__);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
- GrallocBuffer& clientTargetBuffer = *clientTargetBufferOpt;
-
- auto clientTargetBufferViewOpt = clientTargetBuffer.Lock();
- if (!clientTargetBufferViewOpt) {
- ALOGE("%s: failed to lock client target buffer.", __FUNCTION__);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
- GrallocBufferView& clientTargetBufferView = *clientTargetBufferViewOpt;
-
- auto clientTargetPlaneLayoutsOpt = clientTargetBuffer.GetPlaneLayouts();
- if (!clientTargetPlaneLayoutsOpt) {
- ALOGE("Failed to get client target buffer plane layouts.");
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
- auto& clientTargetPlaneLayouts = *clientTargetPlaneLayoutsOpt;
-
- if (clientTargetPlaneLayouts.size() != 1) {
- ALOGE("Unexpected number of plane layouts for client target buffer.");
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
-
- std::size_t clientTargetPlaneSize =
- clientTargetPlaneLayouts[0].totalSizeInBytes;
-
- auto clientTargetDataOpt = clientTargetBufferView.Get();
- if (!clientTargetDataOpt) {
- ALOGE("%s failed to lock gralloc buffer.", __FUNCTION__);
- return std::make_tuple(HWC2::Error::NoResources, base::unique_fd());
- }
- auto* clientTargetData = reinterpret_cast<uint8_t*>(*clientTargetDataOpt);
-
- std::memcpy(compositionResultBufferData, clientTargetData,
- clientTargetPlaneSize);
- } else {
- for (Layer* layer : layers) {
- const auto layerId = layer->getId();
- const auto layerCompositionType = layer->getCompositionType();
- if (layerCompositionType != HWC2::Composition::Device) {
- continue;
- }
-
- HWC2::Error error = composeLayerInto(layer, //
- compositionResultBufferData, //
- compositionResultBufferWidth, //
- compositionResultBufferHeight, //
- compositionResultBufferStride, //
- 4);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to compose layer:%" PRIu64,
- __FUNCTION__, displayId, layerId);
- return std::make_tuple(error, base::unique_fd());
- }
- }
- }
-
- if (display->hasColorTransform()) {
- const ColorTransformWithMatrix colorTransform =
- display->getColorTransform();
-
- HWC2::Error error =
- applyColorTransformToRGBA(colorTransform, //
- compositionResultBufferData, //
- compositionResultBufferWidth, //
- compositionResultBufferHeight, //
- compositionResultBufferStride);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to apply color transform",
- __FUNCTION__, displayId);
- return std::make_tuple(error, base::unique_fd());
- }
- }
-
- DEBUG_LOG("%s display:%" PRIu64 " flushing drm buffer", __FUNCTION__,
- displayId);
-
- auto [error, outRetireFence] = mDrmPresenter->flushToDisplay(
- displayId, *displayInfo.compositionResultDrmBuffer, -1);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to flush drm buffer" PRIu64,
- __FUNCTION__, displayId);
- }
- return std::make_tuple(error, std::move(outRetireFence));
-}
-
-bool GuestComposer::canComposeLayer(Layer* layer) {
- buffer_handle_t bufferHandle = layer->getBuffer().getBuffer();
- if (bufferHandle == nullptr) {
- ALOGW("%s received a layer with a null handle", __FUNCTION__);
- return false;
- }
-
- auto bufferOpt = mGralloc.Import(bufferHandle);
- if (!bufferOpt) {
- ALOGE("Failed to import layer buffer.");
- return false;
- }
- GrallocBuffer& buffer = *bufferOpt;
-
- auto bufferFormatOpt = buffer.GetDrmFormat();
- if (!bufferFormatOpt) {
- ALOGE("Failed to get layer buffer format.");
- return false;
- }
- uint32_t bufferFormat = *bufferFormatOpt;
-
- if (!IsDrmFormatSupported(bufferFormat)) {
- return false;
- }
-
- return true;
-}
-
-HWC2::Error GuestComposer::composeLayerInto(
- Layer* srcLayer, std::uint8_t* dstBuffer, std::uint32_t dstBufferWidth,
- std::uint32_t dstBufferHeight, std::uint32_t dstBufferStrideBytes,
- std::uint32_t dstBufferBytesPerPixel) {
- ATRACE_CALL();
-
- libyuv::RotationMode rotation =
- GetRotationFromTransform(srcLayer->getTransform());
-
- auto srcBufferOpt = mGralloc.Import(srcLayer->waitAndGetBuffer());
- if (!srcBufferOpt) {
- ALOGE("%s: failed to import layer buffer.", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- GrallocBuffer& srcBuffer = *srcBufferOpt;
-
- auto srcBufferViewOpt = srcBuffer.Lock();
- if (!srcBufferViewOpt) {
- ALOGE("%s: failed to lock import layer buffer.", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- GrallocBufferView& srcBufferView = *srcBufferViewOpt;
-
- hwc_rect_t srcLayerCrop = srcLayer->getSourceCropInt();
- hwc_rect_t srcLayerDisplayFrame = srcLayer->getDisplayFrame();
-
- auto srcLayerSpecOpt = GetBufferSpec(srcBuffer, srcBufferView, srcLayerCrop);
- if (!srcLayerSpecOpt) {
- return HWC2::Error::NoResources;
- }
- BufferSpec srcLayerSpec = *srcLayerSpecOpt;
-
- // TODO(jemoreira): Remove the hardcoded fomat.
- bool needsConversion = srcLayerSpec.drmFormat != DRM_FORMAT_XBGR8888 &&
- srcLayerSpec.drmFormat != DRM_FORMAT_ABGR8888;
- bool needsScaling = LayerNeedsScaling(*srcLayer);
- bool needsRotation = rotation != libyuv::kRotate0;
- bool needsTranspose = needsRotation && rotation != libyuv::kRotate180;
- bool needsVFlip = GetVFlipFromTransform(srcLayer->getTransform());
- bool needsAttenuation = LayerNeedsAttenuation(*srcLayer);
- bool needsBlending = LayerNeedsBlending(*srcLayer);
- bool needsCopy = !(needsConversion || needsScaling || needsRotation ||
- needsVFlip || needsAttenuation || needsBlending);
-
- BufferSpec dstLayerSpec(
- dstBuffer,
- /*buffer_ycbcr=*/std::nullopt, dstBufferWidth, dstBufferHeight,
- srcLayerDisplayFrame.left, srcLayerDisplayFrame.top,
- srcLayerDisplayFrame.right - srcLayerDisplayFrame.left,
- srcLayerDisplayFrame.bottom - srcLayerDisplayFrame.top,
- DRM_FORMAT_XBGR8888, dstBufferStrideBytes, dstBufferBytesPerPixel);
-
- // Add the destination layer to the bottom of the buffer stack
- std::vector<BufferSpec> dstBufferStack(1, dstLayerSpec);
-
- // If more than operation is to be performed, a temporary buffer is needed for
- // each additional operation
-
- // N operations need N destination buffers, the destination layer (the
- // framebuffer) is one of them, so only N-1 temporary buffers are needed.
- // Vertical flip is not taken into account because it can be done together
- // with any other operation.
- int neededScratchBuffers = (needsConversion ? 1 : 0) +
- (needsScaling ? 1 : 0) + (needsRotation ? 1 : 0) +
- (needsAttenuation ? 1 : 0) +
- (needsBlending ? 1 : 0) + (needsCopy ? 1 : 0) - 1;
-
- int mScratchBufferWidth =
- srcLayerDisplayFrame.right - srcLayerDisplayFrame.left;
- int mScratchBufferHeight =
- srcLayerDisplayFrame.bottom - srcLayerDisplayFrame.top;
- int mScratchBufferStrideBytes =
- AlignToPower2(mScratchBufferWidth * dstBufferBytesPerPixel, 4);
- int mScratchBufferSizeBytes =
- mScratchBufferHeight * mScratchBufferStrideBytes;
-
- for (int i = 0; i < neededScratchBuffers; i++) {
- BufferSpec mScratchBufferspec(
- getRotatingScratchBuffer(mScratchBufferSizeBytes, i),
- mScratchBufferWidth, mScratchBufferHeight, mScratchBufferStrideBytes);
- dstBufferStack.push_back(mScratchBufferspec);
- }
-
- // Conversion and scaling should always be the first operations, so that every
- // other operation works on equally sized frames (guaranteed to fit in the
- // scratch buffers).
-
- // TODO(jemoreira): We are converting to ARGB as the first step under the
- // assumption that scaling ARGB is faster than scaling I420 (the most common).
- // This should be confirmed with testing.
- if (needsConversion) {
- BufferSpec& dstBufferSpec = dstBufferStack.back();
- if (needsScaling || needsTranspose) {
- // If a rotation or a scaling operation are needed the dimensions at the
- // top of the buffer stack are wrong (wrong sizes for scaling, swapped
- // width and height for 90 and 270 rotations).
- // Make width and height match the crop sizes on the source
- int srcWidth = srcLayerSpec.cropWidth;
- int srcHeight = srcLayerSpec.cropHeight;
- int dst_stride_bytes =
- AlignToPower2(srcWidth * dstBufferBytesPerPixel, 4);
- size_t needed_size = dst_stride_bytes * srcHeight;
- dstBufferSpec.width = srcWidth;
- dstBufferSpec.height = srcHeight;
- // Adjust the stride accordingly
- dstBufferSpec.strideBytes = dst_stride_bytes;
- // Crop sizes also need to be adjusted
- dstBufferSpec.cropWidth = srcWidth;
- dstBufferSpec.cropHeight = srcHeight;
- // cropX and y are fine at 0, format is already set to match destination
-
- // In case of a scale, the source frame may be bigger than the default tmp
- // buffer size
- dstBufferSpec.buffer = getSpecialScratchBuffer(needed_size);
- }
-
- int retval = DoConversion(srcLayerSpec, dstBufferSpec, needsVFlip);
- if (retval) {
- ALOGE("Got error code %d from DoConversion function", retval);
- }
- needsVFlip = false;
- srcLayerSpec = dstBufferSpec;
- dstBufferStack.pop_back();
- }
-
- if (needsScaling) {
- BufferSpec& dstBufferSpec = dstBufferStack.back();
- if (needsTranspose) {
- // If a rotation is needed, the temporary buffer has the correct size but
- // needs to be transposed and have its stride updated accordingly. The
- // crop sizes also needs to be transposed, but not the x and y since they
- // are both zero in a temporary buffer (and it is a temporary buffer
- // because a rotation will be performed next).
- std::swap(dstBufferSpec.width, dstBufferSpec.height);
- std::swap(dstBufferSpec.cropWidth, dstBufferSpec.cropHeight);
- // TODO (jemoreira): Aligment (To align here may cause the needed size to
- // be bigger than the buffer, so care should be taken)
- dstBufferSpec.strideBytes = dstBufferSpec.width * dstBufferBytesPerPixel;
- }
- int retval = DoScaling(srcLayerSpec, dstBufferSpec, needsVFlip);
- needsVFlip = false;
- if (retval) {
- ALOGE("Got error code %d from DoScaling function", retval);
- }
- srcLayerSpec = dstBufferSpec;
- dstBufferStack.pop_back();
- }
-
- if (needsRotation) {
- int retval =
- DoRotation(srcLayerSpec, dstBufferStack.back(), rotation, needsVFlip);
- needsVFlip = false;
- if (retval) {
- ALOGE("Got error code %d from DoTransform function", retval);
- }
- srcLayerSpec = dstBufferStack.back();
- dstBufferStack.pop_back();
- }
-
- if (needsAttenuation) {
- int retval = DoAttenuation(srcLayerSpec, dstBufferStack.back(), needsVFlip);
- needsVFlip = false;
- if (retval) {
- ALOGE("Got error code %d from DoBlending function", retval);
- }
- srcLayerSpec = dstBufferStack.back();
- dstBufferStack.pop_back();
- }
-
- if (needsCopy) {
- int retval = DoCopy(srcLayerSpec, dstBufferStack.back(), needsVFlip);
- needsVFlip = false;
- if (retval) {
- ALOGE("Got error code %d from DoBlending function", retval);
- }
- srcLayerSpec = dstBufferStack.back();
- dstBufferStack.pop_back();
- }
-
- // Blending (if needed) should always be the last operation, so that it reads
- // and writes in the destination layer and not some temporary buffer.
- if (needsBlending) {
- int retval = DoBlending(srcLayerSpec, dstBufferStack.back(), needsVFlip);
- needsVFlip = false;
- if (retval) {
- ALOGE("Got error code %d from DoBlending function", retval);
- }
- // Don't need to assign destination to source in the last one
- dstBufferStack.pop_back();
- }
-
- return HWC2::Error::None;
-}
-
-namespace {
-
-static constexpr const std::array<float, 16> kInvertColorMatrix = {
- // clang-format off
- -1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, -1.0f, 0.0f,
- 1.0f, 1.0f, 1.0f, 1.0f,
- // clang-format on
-};
-
-// Returns a color matrix that can be used with libyuv by converting values
-// in -1 to 1 into -64 to 64 and transposing.
-std::array<std::int8_t, 16> ToLibyuvColorMatrix(
- const std::array<float, 16>& in) {
- std::array<std::int8_t, 16> out;
-
- for (int r = 0; r < 4; r++) {
- for (int c = 0; c < 4; c++) {
- int indexIn = (4 * r) + c;
- int indexOut = (4 * c) + r;
-
- out[indexOut] = std::max(
- -128, std::min(127, static_cast<int>(in[indexIn] * 64.0f + 0.5f)));
- }
- }
-
- return out;
-}
-
-} // namespace
-
-HWC2::Error GuestComposer::applyColorTransformToRGBA(
- const ColorTransformWithMatrix& transform, //
- std::uint8_t* buffer, //
- std::uint32_t bufferWidth, //
- std::uint32_t bufferHeight, //
- std::uint32_t bufferStrideBytes) {
- ATRACE_CALL();
-
- if (transform.transformType == ColorTransform::ARBITRARY_MATRIX) {
- if (!transform.transformMatrixOpt.has_value()) {
- ALOGE("%s: color transform matrix missing", __FUNCTION__);
- return HWC2::Error::BadParameter;
- }
- const auto& transformMatrix = *transform.transformMatrixOpt;
- const auto transformMatrixLibyuv = ToLibyuvColorMatrix(transformMatrix);
- libyuv::ARGBColorMatrix(buffer, bufferStrideBytes, // in buffer params
- buffer, bufferStrideBytes, // out buffer params
- transformMatrixLibyuv.data(), //
- bufferWidth, //
- bufferHeight);
- } else if (transform.transformType == ColorTransform::VALUE_INVERSE) {
- const auto transformMatrixLibyuv = ToLibyuvColorMatrix(kInvertColorMatrix);
- libyuv::ARGBColorMatrix(buffer, bufferStrideBytes, // in buffer params
- buffer, bufferStrideBytes, // out buffer params
- transformMatrixLibyuv.data(), //
- bufferWidth, //
- bufferHeight);
- } else if (transform.transformType == ColorTransform::GRAYSCALE) {
- libyuv::ARGBGrayTo(buffer, bufferStrideBytes, // in buffer params
- buffer, bufferStrideBytes, // out buffer params
- bufferWidth, //
- bufferHeight);
- } else {
- const auto transformTypeString = toString(transform.transformType);
- ALOGE("%s: unhandled color transform type %s", __FUNCTION__,
- transformTypeString.c_str());
- return HWC2::Error::BadParameter;
- }
-
- return HWC2::Error::None;
-}
-
-uint8_t* GuestComposer::getRotatingScratchBuffer(std::size_t neededSize,
- std::uint32_t order) {
- static constexpr const int kNumScratchBufferPieces = 2;
-
- std::size_t totalNeededSize = neededSize * kNumScratchBufferPieces;
- if (mScratchBuffer.size() < totalNeededSize) {
- mScratchBuffer.resize(totalNeededSize);
- }
-
- std::size_t bufferIndex = order % kNumScratchBufferPieces;
- std::size_t bufferOffset = bufferIndex * neededSize;
- return &mScratchBuffer[bufferOffset];
-}
-
-uint8_t* GuestComposer::getSpecialScratchBuffer(size_t neededSize) {
- if (mSpecialScratchBuffer.size() < neededSize) {
- mSpecialScratchBuffer.resize(neededSize);
- }
-
- return &mSpecialScratchBuffer[0];
-}
-
-} // namespace android
diff --git a/system/hwc2/GuestComposer.h b/system/hwc2/GuestComposer.h
deleted file mode 100644
index d9579a0..0000000
--- a/system/hwc2/GuestComposer.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2021 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_HWC_GUESTCOMPOSER_H
-#define ANDROID_HWC_GUESTCOMPOSER_H
-
-#include "Common.h"
-#include "Composer.h"
-#include "Display.h"
-#include "DrmPresenter.h"
-#include "Gralloc.h"
-#include "Layer.h"
-
-namespace android {
-
-class GuestComposer : public Composer {
- public:
- GuestComposer(DrmPresenter* drmPresenter);
-
- GuestComposer(const GuestComposer&) = delete;
- GuestComposer& operator=(const GuestComposer&) = delete;
-
- GuestComposer(GuestComposer&&) = delete;
- GuestComposer& operator=(GuestComposer&&) = delete;
-
- HWC2::Error init() override;
-
- HWC2::Error onDisplayCreate(Display*) override;
-
- HWC2::Error onDisplayDestroy(Display*) override;
-
- HWC2::Error onDisplayClientTargetSet(Display*) override {
- return HWC2::Error::None;
- }
-
- // Determines if this composer can compose the given layers on the given
- // display and requests changes for layers that can't not be composed.
- HWC2::Error validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- outLayerCompositionChanges) override;
-
- // Performs the actual composition of layers and presents the composed result
- // to the display.
- std::tuple<HWC2::Error, base::unique_fd> presentDisplay(
- Display* display) override;
-
- HWC2::Error onActiveConfigChange(Display* /*display*/) override {
- return HWC2::Error::None;
- };
-
- private:
- struct DisplayConfig {
- int width;
- int height;
- int dpiX;
- int dpiY;
- int refreshRateHz;
- };
-
- HWC2::Error getDisplayConfigsFromDeviceConfig(
- std::vector<DisplayConfig>* configs);
-
- HWC2::Error getDisplayConfigsFromSystemProp(
- std::vector<DisplayConfig>* configs);
-
- // Returns true if the given layer's buffer has supported format.
- bool canComposeLayer(Layer* layer);
-
- // Composes the given layer into the given destination buffer.
- HWC2::Error composeLayerInto(Layer* layer, std::uint8_t* dstBuffer,
- std::uint32_t dstBufferWidth,
- std::uint32_t dstBufferHeight,
- std::uint32_t dstBufferStrideBytes,
- std::uint32_t dstBufferBytesPerPixel);
-
- struct GuestComposerDisplayInfo {
- // Additional per display buffer for the composition result.
- buffer_handle_t compositionResultBuffer = nullptr;
-
- std::shared_ptr<DrmBuffer> compositionResultDrmBuffer;
- };
-
- std::unordered_map<hwc2_display_t, GuestComposerDisplayInfo> mDisplayInfos;
-
- Gralloc mGralloc;
-
- DrmPresenter* mDrmPresenter;
-
- // Cuttlefish on QEMU does not have a display. Disable presenting to avoid
- // spamming logcat with DRM commit failures.
- bool mPresentDisabled = false;
-
- uint8_t* getRotatingScratchBuffer(std::size_t neededSize,
- std::uint32_t order);
- uint8_t* getSpecialScratchBuffer(std::size_t neededSize);
-
- HWC2::Error applyColorTransformToRGBA(
- const ColorTransformWithMatrix& colotTransform, //
- std::uint8_t* buffer, //
- std::uint32_t bufferWidth, //
- std::uint32_t bufferHeight, //
- std::uint32_t bufferStrideBytes);
-
- std::vector<uint8_t> mScratchBuffer;
- std::vector<uint8_t> mSpecialScratchBuffer;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/HostComposer.cpp b/system/hwc2/HostComposer.cpp
deleted file mode 100644
index 48b8d51..0000000
--- a/system/hwc2/HostComposer.cpp
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * Copyright 2021 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 "HostComposer.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <poll.h>
-#include <sync/sync.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
-#include <ui/GraphicBufferMapper.h>
-
-#include <algorithm>
-#include <iterator>
-#include <optional>
-#include <tuple>
-
-#include "../egl/goldfish_sync.h"
-#include "Device.h"
-#include "Display.h"
-#include "HostUtils.h"
-#include "virtgpu_drm.h"
-
-namespace android {
-namespace {
-
-typedef struct compose_layer {
- uint32_t cbHandle;
- hwc2_composition_t composeMode;
- hwc_rect_t displayFrame;
- hwc_frect_t crop;
- int32_t blendMode;
- float alpha;
- hwc_color_t color;
- hwc_transform_t transform;
-} ComposeLayer;
-
-typedef struct compose_device {
- uint32_t version;
- uint32_t targetHandle;
- uint32_t numLayers;
- struct compose_layer layer[0];
-} ComposeDevice;
-
-typedef struct compose_device_v2 {
- uint32_t version;
- uint32_t displayId;
- uint32_t targetHandle;
- uint32_t numLayers;
- struct compose_layer layer[0];
-} ComposeDevice_v2;
-
-class ComposeMsg {
- public:
- ComposeMsg(uint32_t layerCnt = 0)
- : mData(sizeof(ComposeDevice) + layerCnt * sizeof(ComposeLayer)) {
- mComposeDevice = reinterpret_cast<ComposeDevice*>(mData.data());
- mLayerCnt = layerCnt;
- }
-
- ComposeDevice* get() { return mComposeDevice; }
-
- uint32_t getLayerCnt() { return mLayerCnt; }
-
- private:
- std::vector<uint8_t> mData;
- uint32_t mLayerCnt;
- ComposeDevice* mComposeDevice;
-};
-
-class ComposeMsg_v2 {
- public:
- ComposeMsg_v2(uint32_t layerCnt = 0)
- : mData(sizeof(ComposeDevice_v2) + layerCnt * sizeof(ComposeLayer)) {
- mComposeDevice = reinterpret_cast<ComposeDevice_v2*>(mData.data());
- mLayerCnt = layerCnt;
- }
-
- ComposeDevice_v2* get() { return mComposeDevice; }
-
- uint32_t getLayerCnt() { return mLayerCnt; }
-
- private:
- std::vector<uint8_t> mData;
- uint32_t mLayerCnt;
- ComposeDevice_v2* mComposeDevice;
-};
-
-} // namespace
-
-std::unique_ptr<HostComposer::CompositionResultBuffer>
-HostComposer::CompositionResultBuffer::create(int32_t width, int32_t height) {
- const uint32_t layerCount = 1;
- const uint64_t graphicBufferId = 0; // not used
- buffer_handle_t handle;
- uint32_t stride;
-
- if (GraphicBufferAllocator::get().allocate(
- width, height, PIXEL_FORMAT_RGBA_8888, layerCount,
- (GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_HW_RENDER),
- &handle, &stride, graphicBufferId, "EmuHWC2") != OK) {
- return nullptr;
- }
-
- std::unique_ptr<FencedBuffer> fencedBuffer = std::make_unique<FencedBuffer>();
- fencedBuffer->setBuffer(handle);
- std::unique_ptr<CompositionResultBuffer> res(new CompositionResultBuffer());
- res->mFencedBuffer = std::move(fencedBuffer);
- return res;
-}
-
-std::unique_ptr<HostComposer::CompositionResultBuffer>
-HostComposer::CompositionResultBuffer::createWithDrmBuffer(
- int32_t width, int32_t height, DrmPresenter& drmPresenter) {
- std::unique_ptr<CompositionResultBuffer> res = create(width, height);
- if (!res) {
- return nullptr;
- }
-
- auto [error, buffer] = drmPresenter.create(res->mFencedBuffer->getBuffer());
- if (error != HWC2::Error::None) {
- return nullptr;
- }
- res->mDrmBuffer = std::move(buffer);
-
- return res;
-}
-
-HostComposer::CompositionResultBuffer::~CompositionResultBuffer() {
- mDrmBuffer = nullptr;
- waitForFence();
- buffer_handle_t handle = mFencedBuffer->getBuffer();
- mFencedBuffer = nullptr;
- GraphicBufferAllocator::get().free(handle);
-}
-
-DrmBuffer& HostComposer::CompositionResultBuffer::waitAndGetDrmBuffer() {
- waitForFence();
- return *mDrmBuffer;
-}
-
-buffer_handle_t
-HostComposer::CompositionResultBuffer::waitAndGetBufferHandle() {
- waitForFence();
- return mFencedBuffer->getBuffer();
-}
-
-bool HostComposer::CompositionResultBuffer::isReady() const {
- base::unique_fd fence = mFencedBuffer->getFence();
- if (!fence.ok()) {
- return true;
- }
- if (sync_wait(fence, 0) == 0) {
- return true;
- }
- if (errno != ETIME) {
- ALOGE("%s: fail when calling sync_wait: %s(%d).", __func__, strerror(errno),
- errno);
- }
- return false;
-}
-
-void HostComposer::CompositionResultBuffer::setFence(base::unique_fd fence) {
- mFencedBuffer->setFence(std::move(fence));
-}
-
-void HostComposer::CompositionResultBuffer::waitForFence() {
- base::unique_fd fence = mFencedBuffer->getFence();
- if (!fence.ok()) {
- return;
- }
- constexpr int kWaitInterval = 3000;
- while (true) {
- int ret = sync_wait(fence, kWaitInterval);
- if (ret == 0) {
- return;
- }
- if (errno == ETIME) {
- ALOGI(
- "%s: timeout when calling sync_wait with fence = %d, timeout = %d, "
- "retry.",
- __func__, static_cast<int>(fence), kWaitInterval);
- continue;
- }
- ALOGE(
- "%s: error when calling sync_wait with fence = %d, timeout = %d: "
- "%s(%d). Quit.",
- __func__, static_cast<int>(fence), kWaitInterval, strerror(errno),
- errno);
- return;
- }
-}
-
-void HostComposer::HostComposerDisplayInfo::resetCompositionResultBuffers(
- std::vector<std::unique_ptr<CompositionResultBuffer>>
- newCompositionResultBuffers) {
- compositionResultBuffers = std::move(newCompositionResultBuffers);
-}
-
-HostComposer::CompositionResultBuffer&
-HostComposer::HostComposerDisplayInfo::getNextCompositionResultBuffer() {
- auto i = compositionResultBuffers.begin();
- // Find the buffer that is already ready for the next composition.
- for (; i != compositionResultBuffers.end(); i++) {
- if ((*i)->isReady()) {
- break;
- }
- }
- // If no buffers are ready, choose the first buffer which should be the
- // earliest buffer sent for composition.
- if (i == compositionResultBuffers.end()) {
- i = compositionResultBuffers.begin();
- }
- // Move the selected buffer to the end of compositionResultBuffers without
- // changing the existing order of other buffers.
- std::rotate(i, std::next(i), compositionResultBuffers.end());
- return *compositionResultBuffers.back();
-}
-
-HostComposer::HostComposer(DrmPresenter* drmPresenter, bool isMinigbm)
- : mDrmPresenter(drmPresenter), mIsMinigbm(isMinigbm) {}
-
-HWC2::Error HostComposer::init() {
- if (!mIsMinigbm) {
- mSyncDeviceFd = goldfish_sync_open();
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::createHostComposerDisplayInfo(
- Display* display, uint32_t hostDisplayId) {
- HWC2::Error error = HWC2::Error::None;
-
- hwc2_display_t displayId = display->getId();
- hwc2_config_t displayConfigId;
- int32_t displayWidth;
- int32_t displayHeight;
-
- error = display->getActiveConfig(&displayConfigId);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " has no active config", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(
- displayConfigId, HWC2::Attribute::Width, &displayWidth);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get width", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(
- displayConfigId, HWC2::Attribute::Height, &displayHeight);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
- displayId);
- return error;
- }
-
- HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
-
- displayInfo.hostDisplayId = hostDisplayId;
-
- std::vector<std::unique_ptr<CompositionResultBuffer>>
- compositionResultBuffers;
- constexpr uint32_t kCompositionInFlight = 3;
- for (uint32_t i = 0; i < kCompositionInFlight; i++) {
- std::unique_ptr<CompositionResultBuffer> buffer = nullptr;
- if (mIsMinigbm) {
- buffer = CompositionResultBuffer::createWithDrmBuffer(
- displayWidth, displayHeight, *mDrmPresenter);
- } else {
- buffer = CompositionResultBuffer::create(displayWidth, displayHeight);
- }
- if (!buffer) {
- ALOGE("%s: display:%" PRIu64
- " failed to create composition target buffer",
- __FUNCTION__, displayId);
- return HWC2::Error::NoResources;
- }
- compositionResultBuffers.emplace_back(std::move(buffer));
- }
- displayInfo.resetCompositionResultBuffers(
- std::move(compositionResultBuffers));
-
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::onDisplayCreate(Display* display) {
- HWC2::Error error = HWC2::Error::None;
-
- hwc2_display_t displayId = display->getId();
- hwc2_config_t displayConfigId;
- int32_t displayWidth;
- int32_t displayHeight;
- int32_t displayDpiX;
-
- error = display->getActiveConfig(&displayConfigId);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " has no active config", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(
- displayConfigId, HWC2::Attribute::Width, &displayWidth);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get width", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(
- displayConfigId, HWC2::Attribute::Height, &displayHeight);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
- displayId);
- return error;
- }
-
- error = display->getDisplayAttributeEnum(displayConfigId,
- HWC2::Attribute::DpiX, &displayDpiX);
- if (error != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to get height", __FUNCTION__,
- displayId);
- return error;
- }
-
- uint32_t hostDisplayId = 0;
-
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- if (displayId == 0) {
- // Primary display:
- hostCon->lock();
- if (rcEnc->rcCreateDisplayById(rcEnc, displayId)) {
- ALOGE("%s host failed to create display %" PRIu64, __func__, displayId);
- hostCon->unlock();
- return HWC2::Error::NoResources;
- }
- if (rcEnc->rcSetDisplayPoseDpi(rcEnc, displayId, -1, -1, displayWidth,
- displayHeight, displayDpiX / 1000)) {
- ALOGE("%s host failed to set display %" PRIu64, __func__, displayId);
- hostCon->unlock();
- return HWC2::Error::NoResources;
- }
- hostCon->unlock();
- } else {
- // Secondary display:
- static constexpr const uint32_t kHostDisplayIdStart = 6;
-
- uint32_t expectedHostDisplayId = kHostDisplayIdStart + displayId - 1;
- uint32_t actualHostDisplayId = 0;
-
- hostCon->lock();
- rcEnc->rcDestroyDisplay(rcEnc, expectedHostDisplayId);
- rcEnc->rcCreateDisplay(rcEnc, &actualHostDisplayId);
- rcEnc->rcSetDisplayPose(rcEnc, actualHostDisplayId, -1, -1, displayWidth,
- displayHeight);
- hostCon->unlock();
-
- if (actualHostDisplayId != expectedHostDisplayId) {
- ALOGE(
- "Something wrong with host displayId allocation, expected %d "
- "but received %d",
- expectedHostDisplayId, actualHostDisplayId);
- }
-
- hostDisplayId = actualHostDisplayId;
- }
-
- error = createHostComposerDisplayInfo(display, hostDisplayId);
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to initialize host info for display:%" PRIu64,
- __FUNCTION__, displayId);
- return error;
- }
-
- std::optional<std::vector<uint8_t>> edid;
- if (mIsMinigbm) {
- edid = mDrmPresenter->getEdid(displayId);
- if (edid) {
- display->setEdid(*edid);
- }
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::onDisplayDestroy(Display* display) {
- hwc2_display_t displayId = display->getId();
-
- auto it = mDisplayInfos.find(displayId);
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__,
- displayId);
- return HWC2::Error::BadDisplay;
- }
-
- HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
-
- if (displayId != 0) {
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- hostCon->lock();
- rcEnc->rcDestroyDisplay(rcEnc, displayInfo.hostDisplayId);
- hostCon->unlock();
- }
-
- mDisplayInfos.erase(it);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::onDisplayClientTargetSet(Display* display) {
- hwc2_display_t displayId = display->getId();
-
- auto it = mDisplayInfos.find(displayId);
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: display:%" PRIu64 " missing display buffers?", __FUNCTION__,
- displayId);
- return HWC2::Error::BadDisplay;
- }
-
- HostComposerDisplayInfo& displayInfo = mDisplayInfos[displayId];
-
- if (mIsMinigbm) {
- FencedBuffer& clientTargetFencedBuffer = display->getClientTarget();
-
- auto [drmBufferCreateError, drmBuffer] =
- mDrmPresenter->create(clientTargetFencedBuffer.getBuffer());
- if (drmBufferCreateError != HWC2::Error::None) {
- ALOGE("%s: display:%" PRIu64 " failed to create client target drm buffer",
- __FUNCTION__, displayId);
- return HWC2::Error::NoResources;
- }
- displayInfo.clientTargetDrmBuffer = std::move(drmBuffer);
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error HostComposer::validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- layerCompositionChanges) {
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- hostCon->lock();
- bool hostCompositionV1 = rcEnc->hasHostCompositionV1();
- bool hostCompositionV2 = rcEnc->hasHostCompositionV2();
- hostCon->unlock();
-
- const std::vector<Layer*> layers = display->getOrderedLayers();
- for (const auto& layer : layers) {
- if (layer->getCompositionType() == HWC2::Composition::Invalid) {
- // Log error for unused layers, layer leak?
- ALOGE("%s layer %" PRIu32 " CompositionType(%d) not set", __FUNCTION__,
- (uint32_t)layer->getId(), layer->getCompositionType());
- }
- }
-
- // If one layer requires a fall back to the client composition type, all
- // layers will fall back to the client composition type.
- bool fallBackToClient = (!hostCompositionV1 && !hostCompositionV2) ||
- display->hasColorTransform();
- std::unordered_map<Layer*, HWC2::Composition> changes;
-
- if (!fallBackToClient) {
- for (Layer* layer : layers) {
- HWC2::Composition layerCompositionType = layer->getCompositionType();
- std::optional<HWC2::Composition> layerFallBackTo = std::nullopt;
- switch (layerCompositionType) {
- case HWC2::Composition::Client:
- case HWC2::Composition::Sideband:
- layerFallBackTo = HWC2::Composition::Client;
- break;
- case HWC2::Composition::Cursor:
- layerFallBackTo = HWC2::Composition::Device;
- break;
- case HWC2::Composition::Invalid:
- case HWC2::Composition::Device:
- case HWC2::Composition::SolidColor:
- layerFallBackTo = std::nullopt;
- break;
- default:
- ALOGE("%s: layer %" PRIu32 " has an unknown composition type: %d",
- __FUNCTION__, static_cast<uint32_t>(layer->getId()),
- layerCompositionType);
- }
- if (layerFallBackTo == HWC2::Composition::Client) {
- fallBackToClient = true;
- }
- if (layerFallBackTo.has_value()) {
- changes.emplace(layer, layerFallBackTo.value());
- }
- }
- }
-
- if (fallBackToClient) {
- changes.clear();
- for (Layer* layer : layers) {
- if (layer->getCompositionType() == HWC2::Composition::Invalid) {
- continue;
- }
- if (layer->getCompositionType() != HWC2::Composition::Client) {
- changes.emplace(layer, HWC2::Composition::Client);
- }
- }
- }
-
- layerCompositionChanges->clear();
- for (auto& [layer, newCompositionType] : changes) {
- layer->logCompositionFallbackIfChanged(newCompositionType);
- layerCompositionChanges->emplace(layer->getId(), newCompositionType);
- }
-
- return HWC2::Error::None;
-}
-
-std::tuple<HWC2::Error, base::unique_fd> HostComposer::presentDisplay(
- Display* display) {
- auto it = mDisplayInfos.find(display->getId());
- base::unique_fd outRetireFence;
- if (it == mDisplayInfos.end()) {
- ALOGE("%s: failed to find display buffers for display:%" PRIu64,
- __FUNCTION__, display->getId());
- return std::make_tuple(HWC2::Error::BadDisplay, base::unique_fd());
- }
-
- HostComposerDisplayInfo& displayInfo = it->second;
-
- HostConnection* hostCon;
- ExtendedRCEncoderContext* rcEnc;
- HWC2::Error res = getAndValidateHostConnection(&hostCon, &rcEnc);
- if (res != HWC2::Error::None) {
- return std::make_tuple(res, base::unique_fd());
- }
- hostCon->lock();
- bool hostCompositionV1 = rcEnc->hasHostCompositionV1();
- bool hostCompositionV2 = rcEnc->hasHostCompositionV2();
- hostCon->unlock();
-
- // Ff we supports v2, then discard v1
- if (hostCompositionV2) {
- hostCompositionV1 = false;
- }
-
- const std::vector<Layer*> layers = display->getOrderedLayers();
- if (hostCompositionV2 || hostCompositionV1) {
- uint32_t numLayer = 0;
- for (auto layer : layers) {
- if (layer->getCompositionType() == HWC2::Composition::Device ||
- layer->getCompositionType() == HWC2::Composition::SolidColor) {
- numLayer++;
- }
- }
-
- DEBUG_LOG("%s: presenting display:%" PRIu64 " with %d layers", __FUNCTION__,
- display->getId(), static_cast<int>(layers.size()));
-
- display->clearReleaseFencesAndIdsLocked();
-
- if (numLayer == 0) {
- ALOGV(
- "%s display has no layers to compose, flushing client target buffer.",
- __FUNCTION__);
-
- FencedBuffer& displayClientTarget = display->getClientTarget();
- if (displayClientTarget.getBuffer() != nullptr) {
- base::unique_fd fence = displayClientTarget.getFence();
- if (mIsMinigbm) {
- auto [_, flushCompleteFence] = mDrmPresenter->flushToDisplay(
- display->getId(), *displayInfo.clientTargetDrmBuffer, fence);
- outRetireFence = std::move(flushCompleteFence);
- } else {
- post(hostCon, rcEnc, displayClientTarget.getBuffer());
- outRetireFence = std::move(fence);
- }
- }
- return std::make_tuple(HWC2::Error::None, std::move(outRetireFence));
- }
-
- std::unique_ptr<ComposeMsg> composeMsg;
- std::unique_ptr<ComposeMsg_v2> composeMsgV2;
-
- if (hostCompositionV1) {
- composeMsg.reset(new ComposeMsg(numLayer));
- } else {
- composeMsgV2.reset(new ComposeMsg_v2(numLayer));
- }
-
- // Handle the composition
- ComposeDevice* p;
- ComposeDevice_v2* p2;
- ComposeLayer* l;
-
- if (hostCompositionV1) {
- p = composeMsg->get();
- l = p->layer;
- } else {
- p2 = composeMsgV2->get();
- l = p2->layer;
- }
-
- std::vector<hwc2_layer_t> releaseLayerIds;
- for (auto layer : layers) {
- // TODO: use local var composisitonType to store getCompositionType()
- if (layer->getCompositionType() != HWC2::Composition::Device &&
- layer->getCompositionType() != HWC2::Composition::SolidColor) {
- ALOGE("%s: Unsupported composition types %d layer %u", __FUNCTION__,
- layer->getCompositionType(), (uint32_t)layer->getId());
- continue;
- }
- // send layer composition command to host
- if (layer->getCompositionType() == HWC2::Composition::Device) {
- releaseLayerIds.emplace_back(layer->getId());
-
- base::unique_fd fence = layer->getBuffer().getFence();
- if (fence.ok()) {
- int err = sync_wait(fence.get(), 3000);
- if (err < 0 && errno == ETIME) {
- ALOGE("%s waited on fence %d for 3000 ms", __FUNCTION__,
- fence.get());
- }
- } else {
- ALOGV("%s: acquire fence not set for layer %u", __FUNCTION__,
- (uint32_t)layer->getId());
- }
- const native_handle_t* cb = layer->getBuffer().getBuffer();
- if (cb != nullptr) {
- l->cbHandle = hostCon->grallocHelper()->getHostHandle(cb);
- } else {
- ALOGE("%s null buffer for layer %d", __FUNCTION__,
- (uint32_t)layer->getId());
- }
- } else {
- // solidcolor has no buffer
- l->cbHandle = 0;
- }
- l->composeMode = (hwc2_composition_t)layer->getCompositionType();
- l->displayFrame = layer->getDisplayFrame();
- l->crop = layer->getSourceCrop();
- l->blendMode = static_cast<int32_t>(layer->getBlendMode());
- l->alpha = layer->getPlaneAlpha();
- l->color = layer->getColor();
- l->transform = layer->getTransform();
- ALOGV(
- " cb %d blendmode %d alpha %f %d %d %d %d z %d"
- " composeMode %d, transform %d",
- l->cbHandle, l->blendMode, l->alpha, l->displayFrame.left,
- l->displayFrame.top, l->displayFrame.right, l->displayFrame.bottom,
- layer->getZ(), l->composeMode, l->transform);
- l++;
- }
-
- auto& compositionResultBuffer =
- displayInfo.getNextCompositionResultBuffer();
- if (hostCompositionV1) {
- p->version = 1;
- p->targetHandle = hostCon->grallocHelper()->getHostHandle(
- compositionResultBuffer.waitAndGetBufferHandle());
- p->numLayers = numLayer;
- } else {
- p2->version = 2;
- p2->displayId = displayInfo.hostDisplayId;
- p2->targetHandle = hostCon->grallocHelper()->getHostHandle(
- compositionResultBuffer.waitAndGetBufferHandle());
- p2->numLayers = numLayer;
- }
-
- void* buffer;
- uint32_t bufferSize;
- if (hostCompositionV1) {
- buffer = (void*)p;
- bufferSize = sizeof(ComposeDevice) + numLayer * sizeof(ComposeLayer);
- } else {
- bufferSize = sizeof(ComposeDevice_v2) + numLayer * sizeof(ComposeLayer);
- buffer = (void*)p2;
- }
-
- base::unique_fd retire_fd;
- hostCon->lock();
- if (rcEnc->hasAsyncFrameCommands()) {
- if (mIsMinigbm) {
- rcEnc->rcComposeAsyncWithoutPost(rcEnc, bufferSize, buffer);
- } else {
- rcEnc->rcComposeAsync(rcEnc, bufferSize, buffer);
- }
- } else {
- if (mIsMinigbm) {
- rcEnc->rcComposeWithoutPost(rcEnc, bufferSize, buffer);
- } else {
- rcEnc->rcCompose(rcEnc, bufferSize, buffer);
- }
- }
- hostCon->unlock();
-
- // Send a retire fence and use it as the release fence for all layers,
- // since media expects it
- EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_ANDROID,
- EGL_NO_NATIVE_FENCE_FD_ANDROID};
-
- uint64_t sync_handle, thread_handle;
-
- // We don't use rc command to sync if we are using virtio-gpu, which is
- // proxied by minigbm.
- bool useRcCommandToSync = !mIsMinigbm;
-
- if (useRcCommandToSync) {
- hostCon->lock();
- rcEnc->rcCreateSyncKHR(
- rcEnc, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs, 2 * sizeof(EGLint),
- true /* destroy when signaled */, &sync_handle, &thread_handle);
- hostCon->unlock();
- }
-
- if (mIsMinigbm) {
- auto [_, fence] = mDrmPresenter->flushToDisplay(
- display->getId(), compositionResultBuffer.waitAndGetDrmBuffer(), -1);
- retire_fd = std::move(fence);
- } else {
- int fd;
- goldfish_sync_queue_work(mSyncDeviceFd, sync_handle, thread_handle, &fd);
- retire_fd = base::unique_fd(fd);
- }
-
- for (hwc2_layer_t layerId : releaseLayerIds) {
- display->addReleaseFenceLocked(layerId,
- base::unique_fd(dup(retire_fd.get())));
- }
-
- outRetireFence = base::unique_fd(dup(retire_fd.get()));
- if (useRcCommandToSync) {
- hostCon->lock();
- if (rcEnc->hasAsyncFrameCommands()) {
- rcEnc->rcDestroySyncKHRAsync(rcEnc, sync_handle);
- } else {
- rcEnc->rcDestroySyncKHR(rcEnc, sync_handle);
- }
- hostCon->unlock();
- }
- compositionResultBuffer.setFence(base::unique_fd(dup(retire_fd.get())));
- } else {
- // we set all layers Composition::Client, so do nothing.
- FencedBuffer& displayClientTarget = display->getClientTarget();
- base::unique_fd fence = displayClientTarget.getFence();
- if (mIsMinigbm) {
- auto [_, outRetireFence] = mDrmPresenter->flushToDisplay(
- display->getId(), *displayInfo.clientTargetDrmBuffer, fence);
- outRetireFence = std::move(fence);
- } else {
- post(hostCon, rcEnc, displayClientTarget.getBuffer());
- outRetireFence = std::move(fence);
- }
- ALOGV("%s fallback to post, returns outRetireFence %d", __FUNCTION__,
- outRetireFence.get());
- }
-
- return std::make_tuple(HWC2::Error::None, std::move(outRetireFence));
-}
-
-void HostComposer::post(HostConnection* hostCon,
- ExtendedRCEncoderContext* rcEnc, buffer_handle_t h) {
- assert(cb && "native_handle_t::from(h) failed");
-
- hostCon->lock();
- rcEnc->rcFBPost(rcEnc, hostCon->grallocHelper()->getHostHandle(h));
- hostCon->flush();
- hostCon->unlock();
-}
-
-HWC2::Error HostComposer::onActiveConfigChange(Display* display) {
- DEBUG_LOG("%s: display:%" PRIu64, __FUNCTION__, display->getId());
- HWC2::Error error = createHostComposerDisplayInfo(display, display->getId());
- if (error != HWC2::Error::None) {
- ALOGE("%s failed to update host info for display:%" PRIu64, __FUNCTION__,
- display->getId());
- return error;
- }
- return HWC2::Error::None;
-}
-
-} // namespace android
diff --git a/system/hwc2/HostComposer.h b/system/hwc2/HostComposer.h
deleted file mode 100644
index e8a9927..0000000
--- a/system/hwc2/HostComposer.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2021 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_HWC_HOSTCOMPOSER_H
-#define ANDROID_HWC_HOSTCOMPOSER_H
-
-#include <android-base/unique_fd.h>
-
-#include <memory>
-#include <tuple>
-#include <vector>
-
-#include "Common.h"
-#include "Composer.h"
-#include "DrmPresenter.h"
-#include "FencedBuffer.h"
-#include "HostConnection.h"
-
-namespace android {
-
-class HostComposer : public Composer {
- public:
- HostComposer(DrmPresenter* drmPresenter, bool isMinigbm);
-
- HostComposer(const HostComposer&) = delete;
- HostComposer& operator=(const HostComposer&) = delete;
-
- HostComposer(HostComposer&&) = delete;
- HostComposer& operator=(HostComposer&&) = delete;
-
- HWC2::Error init() override;
-
- HWC2::Error onDisplayCreate(Display* display) override;
-
- HWC2::Error onDisplayDestroy(Display* display) override;
-
- HWC2::Error onDisplayClientTargetSet(Display* display) override;
-
- // Determines if this composer can compose the given layers on the given
- // display and requests changes for layers that can't not be composed.
- HWC2::Error validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- outLayerCompositionChanges) override;
-
- // Performs the actual composition of layers and presents the composed result
- // to the display.
- std::tuple<HWC2::Error, base::unique_fd> presentDisplay(
- Display* display) override;
-
- HWC2::Error onActiveConfigChange(Display* display) override;
-
- private:
- HWC2::Error createHostComposerDisplayInfo(Display* display,
- uint32_t hostDisplayId);
-
- void post(HostConnection* hostCon, ExtendedRCEncoderContext* rcEnc,
- buffer_handle_t h);
-
- int mSyncDeviceFd = -1;
-
- class CompositionResultBuffer {
- public:
- static std::unique_ptr<CompositionResultBuffer> create(int32_t width,
- int32_t height);
- static std::unique_ptr<CompositionResultBuffer> createWithDrmBuffer(
- int32_t width, int32_t height, DrmPresenter&);
- ~CompositionResultBuffer();
-
- DrmBuffer& waitAndGetDrmBuffer();
- buffer_handle_t waitAndGetBufferHandle();
- bool isReady() const;
- void setFence(base::unique_fd fence);
-
- private:
- CompositionResultBuffer() = default;
-
- void waitForFence();
-
- std::unique_ptr<FencedBuffer> mFencedBuffer;
- // Drm info for the additional composition result buffer.
- std::shared_ptr<DrmBuffer> mDrmBuffer;
- };
- class HostComposerDisplayInfo {
- public:
- HostComposerDisplayInfo() = default;
- void resetCompositionResultBuffers(
- std::vector<std::unique_ptr<CompositionResultBuffer>>);
- CompositionResultBuffer& getNextCompositionResultBuffer();
-
- uint32_t hostDisplayId = 0;
- // Drm info for the displays client target buffer.
- std::shared_ptr<DrmBuffer> clientTargetDrmBuffer;
-
- private:
- // Additional per display buffer for the composition result.
- std::vector<std::unique_ptr<CompositionResultBuffer>>
- compositionResultBuffers;
- };
-
- std::unordered_map<hwc2_display_t, HostComposerDisplayInfo> mDisplayInfos;
- DrmPresenter* mDrmPresenter;
- bool mIsMinigbm = false;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/HostUtils.cpp b/system/hwc2/HostUtils.cpp
deleted file mode 100644
index 11bb6ba..0000000
--- a/system/hwc2/HostUtils.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2021 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 "HostUtils.h"
-
-#include <memory>
-
-namespace android {
-
-HostConnection* createOrGetHostConnection() {
- static std::unique_ptr<HostConnection> sHostCon;
-
- if (!sHostCon) {
- sHostCon = HostConnection::createUnique();
- }
- return sHostCon.get();
-}
-
-} // namespace android
\ No newline at end of file
diff --git a/system/hwc2/HostUtils.h b/system/hwc2/HostUtils.h
deleted file mode 100644
index aa7039d..0000000
--- a/system/hwc2/HostUtils.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2021 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_HWC_HOSTUTILS_H
-#define ANDROID_HWC_HOSTUTILS_H
-
-#include "Common.h"
-#include "HostConnection.h"
-
-namespace android {
-
-HostConnection* createOrGetHostConnection();
-
-inline HWC2::Error getAndValidateHostConnection(
- HostConnection** ppHostCon, ExtendedRCEncoderContext** ppRcEnc) {
- *ppHostCon = nullptr;
- *ppRcEnc = nullptr;
-
- HostConnection* hostCon = createOrGetHostConnection();
- if (!hostCon) {
- ALOGE("%s: Failed to get host connection\n", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
- ExtendedRCEncoderContext* rcEnc = hostCon->rcEncoder();
- if (!rcEnc) {
- ALOGE("%s: Failed to get renderControl encoder context\n", __FUNCTION__);
- return HWC2::Error::NoResources;
- }
-
- *ppHostCon = hostCon;
- *ppRcEnc = rcEnc;
- return HWC2::Error::None;
-}
-
-#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
- HostConnection* hostCon; \
- ExtendedRCEncoderContext* rcEnc; \
- { \
- HWC2::Error res = getAndValidateHostConnection(&hostCon, &rcEnc); \
- if (res != HWC2::Error::None) { \
- return res; \
- } \
- }
-} // namespace android
-
-#endif
diff --git a/system/hwc2/Layer.cpp b/system/hwc2/Layer.cpp
deleted file mode 100644
index 7421ec8..0000000
--- a/system/hwc2/Layer.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright 2021 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 "Layer.h"
-
-#include <android-base/unique_fd.h>
-#include <sync/sync.h>
-
-#include <atomic>
-
-namespace android {
-namespace {
-
-std::atomic<hwc2_layer_t> sNextId{1};
-
-} // namespace
-
-Layer::Layer() : mId(sNextId++) {}
-
-HWC2::Error Layer::setBuffer(buffer_handle_t buffer, int32_t fence) {
- DEBUG_LOG("%s: layer:%" PRIu64 " buffer:%p fence:%" PRIu32, __FUNCTION__, mId,
- buffer, fence);
- mBuffer.setBuffer(buffer);
- mBuffer.setFence(base::unique_fd(fence));
- return HWC2::Error::None;
-}
-
-buffer_handle_t Layer::waitAndGetBuffer() {
- DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId);
-
- base::unique_fd fence = mBuffer.getFence();
- if (fence.ok()) {
- int err = sync_wait(fence.get(), 3000);
- if (err < 0 && errno == ETIME) {
- ALOGE("%s waited on fence %" PRId32 " for 3000 ms", __FUNCTION__,
- fence.get());
- }
- }
-
- return mBuffer.getBuffer();
-}
-
-HWC2::Error Layer::setCursorPosition(int32_t /*x*/, int32_t /*y*/) {
- DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId);
-
- if (mCompositionType != HWC2::Composition::Cursor) {
- ALOGE("%s: CompositionType not Cursor type", __FUNCTION__);
- return HWC2::Error::BadLayer;
- }
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Layer::setSurfaceDamage(hwc_region_t /*damage*/) {
- DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Layer::setBlendMode(int32_t m) {
- const auto blendMode = static_cast<HWC2::BlendMode>(m);
- const auto blendModeString = to_string(blendMode);
- DEBUG_LOG("%s layer:%" PRIu64 " blend mode:%s", __FUNCTION__, mId,
- blendModeString.c_str());
-
- mBlendMode = blendMode;
- return HWC2::Error::None;
-}
-
-HWC2::BlendMode Layer::getBlendMode() const {
- const auto blendMode = mBlendMode;
- const auto blendModeString = to_string(blendMode);
- DEBUG_LOG("%s layer:%" PRIu64 " blend mode:%s", __FUNCTION__, mId,
- blendModeString.c_str());
-
- return blendMode;
-}
-
-HWC2::Error Layer::setColor(hwc_color_t color) {
- DEBUG_LOG("%s layer:%" PRIu64 " color-r:%d color-g:%d color-b:%d color-a:%d)",
- __FUNCTION__, mId, color.r, color.g, color.b, color.a);
-
- mColor = color;
- return HWC2::Error::None;
-}
-
-hwc_color_t Layer::getColor() const {
- auto color = mColor;
- DEBUG_LOG("%s layer:%" PRIu64 " color-r:%d color-g:%d color-b:%d color-a:%d)",
- __FUNCTION__, mId, color.r, color.g, color.b, color.a);
-
- return color;
-}
-
-HWC2::Error Layer::setCompositionTypeEnum(HWC2::Composition compositionType) {
- const auto compositionTypeString = to_string(compositionType);
- DEBUG_LOG("%s layer:%" PRIu64 " composition type:%s", __FUNCTION__, mId,
- compositionTypeString.c_str());
-
- mCompositionType = compositionType;
- return HWC2::Error::None;
-}
-
-HWC2::Error Layer::setCompositionType(int32_t type) {
- const auto compositionType = static_cast<HWC2::Composition>(type);
- return setCompositionTypeEnum(compositionType);
-}
-
-HWC2::Composition Layer::getCompositionType() const {
- const auto compositionType = mCompositionType;
- const auto compositionTypeString = to_string(compositionType);
- DEBUG_LOG("%s layer:%" PRIu64 " composition type:%s", __FUNCTION__, mId,
- compositionTypeString.c_str());
-
- return compositionType;
-}
-
-HWC2::Error Layer::setDataspace(int32_t) {
- DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error Layer::setDisplayFrame(hwc_rect_t frame) {
- DEBUG_LOG("%s layer:%" PRIu64
- " display frame rect-left:%d rect-top:%d rect-right:%d rect-bot:%d",
- __FUNCTION__, mId, frame.left, frame.top, frame.right,
- frame.bottom);
-
- mDisplayFrame = frame;
- return HWC2::Error::None;
-}
-
-hwc_rect_t Layer::getDisplayFrame() const {
- auto frame = mDisplayFrame;
- DEBUG_LOG("%s layer:%" PRIu64
- " display frame rect-left:%d rect-top:%d rect-right:%d rect-bot:%d",
- __FUNCTION__, mId, frame.left, frame.top, frame.right,
- frame.bottom);
-
- return frame;
-}
-
-HWC2::Error Layer::setPlaneAlpha(float alpha) {
- DEBUG_LOG("%s layer:%" PRIu64 "alpha:%f", __FUNCTION__, mId, alpha);
-
- mPlaneAlpha = alpha;
- return HWC2::Error::None;
-}
-
-float Layer::getPlaneAlpha() const {
- auto alpha = mPlaneAlpha;
- DEBUG_LOG("%s layer:%" PRIu64 "alpha:%f", __FUNCTION__, mId, alpha);
-
- return alpha;
-}
-
-HWC2::Error Layer::setSidebandStream(const native_handle_t* stream) {
- DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId);
-
- mSidebandStream = stream;
- return HWC2::Error::None;
-}
-
-HWC2::Error Layer::setSourceCrop(hwc_frect_t crop) {
- DEBUG_LOG("%s layer:%" PRIu64
- "crop rect-left:%f rect-top:%f rect-right:%f rect-bot:%f",
- __FUNCTION__, mId, crop.left, crop.top, crop.right, crop.bottom);
-
- mSourceCrop = crop;
- return HWC2::Error::None;
-}
-
-hwc_frect_t Layer::getSourceCrop() const {
- hwc_frect_t crop = mSourceCrop;
- DEBUG_LOG("%s layer:%" PRIu64
- "crop rect-left:%f rect-top:%f rect-right:%f rect-bot:%f",
- __FUNCTION__, mId, crop.left, crop.top, crop.right, crop.bottom);
-
- return crop;
-}
-
-hwc_rect_t Layer::getSourceCropInt() const {
- hwc_rect_t crop = {};
- crop.left = static_cast<int>(mSourceCrop.left);
- crop.top = static_cast<int>(mSourceCrop.top);
- crop.right = static_cast<int>(mSourceCrop.right);
- crop.bottom = static_cast<int>(mSourceCrop.bottom);
- DEBUG_LOG("%s layer:%" PRIu64
- "crop rect-left:%d rect-top:%d rect-right:%d rect-bot:%d",
- __FUNCTION__, mId, crop.left, crop.top, crop.right, crop.bottom);
-
- return crop;
-}
-
-HWC2::Error Layer::setTransform(int32_t transform) {
- const auto transformType = static_cast<HWC2::Transform>(transform);
- const auto transformTypeString = to_string(transformType);
- DEBUG_LOG("%s layer:%" PRIu64 " transform:%s", __FUNCTION__, mId,
- transformTypeString.c_str());
-
- mTransform = transformType;
- return HWC2::Error::None;
-}
-
-hwc_transform_t Layer::getTransform() const {
- const auto transform = mTransform;
- const auto transformString = to_string(transform);
- DEBUG_LOG("%s layer:%" PRIu64 " transform:%s", __FUNCTION__, mId,
- transformString.c_str());
-
- return static_cast<hwc_transform_t>(transform);
-}
-
-HWC2::Error Layer::setVisibleRegion(hwc_region_t visible) {
- DEBUG_LOG("%s layer:%" PRIu64, __FUNCTION__, mId);
-
- mVisibleRegion.resize(visible.numRects);
- std::copy_n(visible.rects, visible.numRects, mVisibleRegion.data());
- return HWC2::Error::None;
-}
-
-std::size_t Layer::getNumVisibleRegions() const {
- std::size_t num = mVisibleRegion.size();
- DEBUG_LOG("%s layer:%" PRIu64 " number of visible regions: %zu", __FUNCTION__,
- mId, num);
-
- return num;
-}
-
-HWC2::Error Layer::setZ(uint32_t z) {
- DEBUG_LOG("%s layer:%" PRIu64 " z:%d", __FUNCTION__, mId, z);
-
- mZ = z;
- return HWC2::Error::None;
-}
-
-uint32_t Layer::getZ() const {
- uint32_t z = mZ;
- DEBUG_LOG("%s layer:%" PRIu64 " z:%d", __FUNCTION__, mId, z);
-
- return z;
-}
-
-void Layer::logCompositionFallbackIfChanged(HWC2::Composition to) {
- HWC2::Composition from = getCompositionType();
- if (mLastCompositionFallback && mLastCompositionFallback->from == from &&
- mLastCompositionFallback->to == to) {
- return;
- }
- ALOGI("%s: layer %" PRIu32 " CompositionType fallback from %d to %d", __FUNCTION__,
- static_cast<uint32_t>(getId()), static_cast<int>(from), static_cast<int>(to));
- mLastCompositionFallback = {
- .from = from,
- .to = to,
- };
-}
-
-} // namespace android
diff --git a/system/hwc2/Layer.h b/system/hwc2/Layer.h
deleted file mode 100644
index f1668e0..0000000
--- a/system/hwc2/Layer.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2021 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_HWC_LAYER_H
-#define ANDROID_HWC_LAYER_H
-
-#include <optional>
-#include <vector>
-
-#include "Common.h"
-#include "FencedBuffer.h"
-
-namespace android {
-
-class Layer {
- public:
- explicit Layer();
-
- Layer(const Layer&) = delete;
- Layer& operator=(const Layer&) = delete;
-
- Layer(Layer&&) = default;
- Layer& operator=(Layer&&) = default;
-
- HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
- FencedBuffer& getBuffer() { return mBuffer; }
-
- buffer_handle_t waitAndGetBuffer();
-
- hwc2_layer_t getId() const { return mId; }
-
- HWC2::Error setCursorPosition(int32_t x, int32_t y);
-
- HWC2::Error setSurfaceDamage(hwc_region_t damage);
-
- HWC2::Error setBlendMode(int32_t mode);
- HWC2::BlendMode getBlendMode() const;
-
- HWC2::Error setColor(hwc_color_t color);
- hwc_color_t getColor() const;
-
- HWC2::Error setCompositionTypeEnum(HWC2::Composition type);
- HWC2::Error setCompositionType(int32_t type);
- HWC2::Composition getCompositionType() const;
-
- HWC2::Error setDataspace(int32_t dataspace);
-
- HWC2::Error setDisplayFrame(hwc_rect_t frame);
- hwc_rect_t getDisplayFrame() const;
-
- HWC2::Error setPlaneAlpha(float alpha);
- float getPlaneAlpha() const;
-
- HWC2::Error setSidebandStream(const native_handle_t* stream);
-
- HWC2::Error setSourceCrop(hwc_frect_t crop);
- hwc_frect_t getSourceCrop() const;
- hwc_rect_t getSourceCropInt() const;
-
- HWC2::Error setTransform(int32_t transform);
- hwc_transform_t getTransform() const;
-
- HWC2::Error setVisibleRegion(hwc_region_t visible);
- std::size_t getNumVisibleRegions() const;
-
- HWC2::Error setZ(uint32_t z);
- uint32_t getZ() const;
-
- // For log use only.
- void logCompositionFallbackIfChanged(HWC2::Composition to);
-
- private:
- const hwc2_layer_t mId;
- FencedBuffer mBuffer;
- std::vector<hwc_rect_t> mSurfaceDamage;
- HWC2::BlendMode mBlendMode = HWC2::BlendMode::None;
- hwc_color_t mColor = {0, 0, 0, 0};
- HWC2::Composition mCompositionType = HWC2::Composition::Invalid;
- struct CompositionTypeFallback {
- HWC2::Composition from;
- HWC2::Composition to;
- };
- // For log use only.
- std::optional<CompositionTypeFallback> mLastCompositionFallback = std::nullopt;
- hwc_rect_t mDisplayFrame = {0, 0, -1, -1};
- float mPlaneAlpha = 0.0f;
- const native_handle_t* mSidebandStream = nullptr;
- hwc_frect_t mSourceCrop = {0.0f, 0.0f, -1.0f, -1.0f};
- HWC2::Transform mTransform = HWC2::Transform::None;
- std::vector<hwc_rect_t> mVisibleRegion;
- uint32_t mZ = 0;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/LruCache.h b/system/hwc2/LruCache.h
deleted file mode 100644
index 9ffca46..0000000
--- a/system/hwc2/LruCache.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#pragma once
-
-#include <list>
-#include <unordered_map>
-
-template <typename Key, typename Value>
-class LruCache {
- public:
- LruCache(std::size_t maxSize) : m_maxSize(maxSize) {
- m_table.reserve(maxSize);
- }
-
- Value* get(const Key& key) {
- auto tableIt = m_table.find(key);
- if (tableIt == m_table.end()) {
- return nullptr;
- }
-
- // Move to front.
- auto elementsIt = tableIt->second;
- m_elements.splice(elementsIt, m_elements, m_elements.begin());
- return &elementsIt->value;
- }
-
- void set(const Key& key, Value&& value) {
- auto tableIt = m_table.find(key);
- if (tableIt == m_table.end()) {
- if (m_table.size() >= m_maxSize) {
- auto& kv = m_elements.back();
- m_table.erase(kv.key);
- m_elements.pop_back();
- }
- } else {
- auto elementsIt = tableIt->second;
- m_elements.erase(elementsIt);
- }
- m_elements.emplace_front(KeyValue{
- key,
- std::forward<Value>(value),
- });
- m_table[key] = m_elements.begin();
- }
-
- void remove(const Key& key) {
- auto tableIt = m_table.find(key);
- if (tableIt == m_table.end()) {
- return;
- }
- auto elementsIt = tableIt->second;
- m_elements.erase(elementsIt);
- m_table.erase(tableIt);
- }
-
- void clear() {
- m_elements.clear();
- m_table.clear();
- }
-
- private:
- struct KeyValue {
- Key key;
- Value value;
- };
-
- const std::size_t m_maxSize;
- // Front is the most recently used and back is the least recently used.
- std::list<KeyValue> m_elements;
- std::unordered_map<Key, typename std::list<KeyValue>::iterator> m_table;
-};
diff --git a/system/hwc2/NoOpComposer.cpp b/system/hwc2/NoOpComposer.cpp
deleted file mode 100644
index f0bcfe2..0000000
--- a/system/hwc2/NoOpComposer.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2022 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 "NoOpComposer.h"
-
-#include "Device.h"
-#include "Display.h"
-#include "Drm.h"
-#include "Layer.h"
-
-namespace android {
-
-NoOpComposer::NoOpComposer() {}
-
-HWC2::Error NoOpComposer::init() {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error NoOpComposer::onDisplayCreate(Display*) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error NoOpComposer::onDisplayDestroy(Display*) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error NoOpComposer::onDisplayClientTargetSet(Display*) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error NoOpComposer::onActiveConfigChange(Display*) {
- DEBUG_LOG("%s", __FUNCTION__);
-
- return HWC2::Error::None;
-};
-
-HWC2::Error NoOpComposer::validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*) {
- const auto displayId = display->getId();
- DEBUG_LOG("%s display:%" PRIu64, __FUNCTION__, displayId);
-
- return HWC2::Error::None;
-}
-
-std::tuple<HWC2::Error, base::unique_fd> NoOpComposer::presentDisplay(
- Display*) {
- ATRACE_CALL();
- DEBUG_LOG("%s", __FUNCTION__);
-
- base::unique_fd emptyFence;
- return std::make_tuple(HWC2::Error::None, std::move(emptyFence));
-}
-
-} // namespace android
diff --git a/system/hwc2/NoOpComposer.h b/system/hwc2/NoOpComposer.h
deleted file mode 100644
index c3cbb4e..0000000
--- a/system/hwc2/NoOpComposer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2022 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_HWC_NOOPCOMPOSER_H
-#define ANDROID_HWC_NOOPCOMPOSER_H
-
-#include "Common.h"
-#include "Composer.h"
-#include "Display.h"
-#include "DrmPresenter.h"
-#include "Gralloc.h"
-#include "Layer.h"
-
-namespace android {
-
-class NoOpComposer : public Composer {
- public:
- NoOpComposer();
-
- NoOpComposer(const NoOpComposer&) = delete;
- NoOpComposer& operator=(const NoOpComposer&) = delete;
-
- NoOpComposer(NoOpComposer&&) = delete;
- NoOpComposer& operator=(NoOpComposer&&) = delete;
-
- HWC2::Error init() override;
-
- HWC2::Error onDisplayCreate(Display*) override;
-
- HWC2::Error onDisplayDestroy(Display*) override;
-
- HWC2::Error onDisplayClientTargetSet(Display*) override;
-
- HWC2::Error onActiveConfigChange(Display*) override;
-
- // Determines if this composer can compose the given layers on the given
- // display and requests changes for layers that can't not be composed.
- HWC2::Error validateDisplay(
- Display* display, std::unordered_map<hwc2_layer_t, HWC2::Composition>*
- outLayerCompositionChanges) override;
-
- // Performs the actual composition of layers and presents the composed result
- // to the display.
- std::tuple<HWC2::Error, base::unique_fd> presentDisplay(
- Display* display) override;
-};
-
-} // namespace android
-
-#endif
diff --git a/system/hwc2/VsyncThread.cpp b/system/hwc2/VsyncThread.cpp
deleted file mode 100644
index dbefcc6..0000000
--- a/system/hwc2/VsyncThread.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2021 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 "VsyncThread.h"
-
-#include <thread>
-
-namespace android {
-namespace {
-
-std::chrono::time_point<std::chrono::steady_clock> asTimePoint(int64_t nanos) {
- return std::chrono::time_point<std::chrono::steady_clock>(
- std::chrono::nanoseconds(nanos));
-}
-
-hwc2_vsync_period_t asNanos(std::chrono::nanoseconds duration) {
- return duration.count();
-}
-
-int64_t asNanos(std::chrono::time_point<std::chrono::steady_clock> time) {
- std::chrono::time_point<std::chrono::steady_clock> zero(
- std::chrono::nanoseconds(0));
- return std::chrono::duration_cast<std::chrono::nanoseconds>(time - zero)
- .count();
-}
-
-// Returns the timepoint of the next vsync after the 'now' timepoint that is
-// a multiple of 'vsyncPeriod' in-phase/offset-from 'previousSync'.
-//
-// Some examples:
-// * vsyncPeriod=50ns previousVsync=500ns now=510ns => 550ns
-// * vsyncPeriod=50ns previousVsync=300ns now=510ns => 550ns
-// * vsyncPeriod=50ns previousVsync=500ns now=550ns => 550ns
-std::chrono::time_point<std::chrono::steady_clock> GetNextVsyncInPhase(
- std::chrono::nanoseconds vsyncPeriod,
- std::chrono::time_point<std::chrono::steady_clock> previousVsync,
- std::chrono::time_point<std::chrono::steady_clock> now) {
- const auto elapsed = std::chrono::nanoseconds(now - previousVsync);
- const auto nextMultiple = (elapsed / vsyncPeriod) + 1;
- return previousVsync + (nextMultiple * vsyncPeriod);
-}
-
-} // namespace
-
-VsyncThread::VsyncThread(hwc2_display_t id) : mDisplayId(id) {
- mPreviousVsync = std::chrono::steady_clock::now() - mVsyncPeriod;
-}
-
-HWC2::Error VsyncThread::start(hwc2_vsync_period_t vsyncPeriod) {
- DEBUG_LOG("%s for display:%" PRIu64, __FUNCTION__, mDisplayId);
-
- mVsyncPeriod = std::chrono::nanoseconds(vsyncPeriod);
-
- const std::string threadName =
- "display_" + std::to_string(mDisplayId) + "_vsync_thread";
- this->run(threadName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
-
- return HWC2::Error::None;
-}
-
-HWC2::Error VsyncThread::setVsyncCallback(HWC2_PFN_VSYNC callback,
- hwc2_callback_data_t callbackData) {
- DEBUG_LOG("%s for display:%" PRIu64, __FUNCTION__, mDisplayId);
-
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- mVsyncCallback = callback;
- mVsyncCallbackData = callbackData;
-
- return HWC2::Error::None;
-}
-
-HWC2::Error VsyncThread::setVsync24Callback(HWC2_PFN_VSYNC_2_4 callback,
- hwc2_callback_data_t callbackData) {
- DEBUG_LOG("%s for display:%" PRIu64, __FUNCTION__, mDisplayId);
-
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- mVsync24Callback = callback;
- mVsync24CallbackData = callbackData;
-
- return HWC2::Error::None;
-}
-
-HWC2::Error VsyncThread::setVsyncEnabled(bool enabled) {
- DEBUG_LOG("%s for display:%" PRIu64 " enabled:%d", __FUNCTION__, mDisplayId,
- enabled);
-
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- mVsyncEnabled = enabled;
-
- return HWC2::Error::None;
-}
-
-HWC2::Error VsyncThread::scheduleVsyncUpdate(
- hwc2_vsync_period_t newVsyncPeriod,
- hwc_vsync_period_change_constraints_t* newVsyncPeriodConstraints,
- hwc_vsync_period_change_timeline_t* outTimeline) {
- DEBUG_LOG("%s for display:%" PRIu64, __FUNCTION__, mDisplayId);
-
- PendingUpdate update;
- update.period = std::chrono::nanoseconds(newVsyncPeriod);
- update.updateAfter = asTimePoint(newVsyncPeriodConstraints->desiredTimeNanos);
-
- std::unique_lock<std::mutex> lock(mStateMutex);
- mPendingUpdate.emplace(std::move(update));
-
- auto nextVsync =
- GetNextVsyncInPhase(mVsyncPeriod, mPreviousVsync, update.updateAfter);
-
- outTimeline->newVsyncAppliedTimeNanos = asNanos(nextVsync);
- outTimeline->refreshRequired = false;
- outTimeline->refreshTimeNanos = 0;
-
- return HWC2::Error::None;
-}
-
-std::chrono::nanoseconds VsyncThread::updateVsyncPeriodLocked(
- std::chrono::time_point<std::chrono::steady_clock> now) {
- if (mPendingUpdate && now > mPendingUpdate->updateAfter) {
- mVsyncPeriod = mPendingUpdate->period;
- mPendingUpdate.reset();
- }
-
- return mVsyncPeriod;
-}
-
-bool VsyncThread::threadLoop() {
- DEBUG_LOG("%s: for display:%" PRIu64 " started", __FUNCTION__, mDisplayId);
-
- std::chrono::nanoseconds vsyncPeriod = mVsyncPeriod;
-
- int vsyncs = 0;
- auto previousLog = std::chrono::steady_clock::now();
- while (true) {
- auto now = std::chrono::steady_clock::now();
-
- auto nextVsync = GetNextVsyncInPhase(vsyncPeriod, mPreviousVsync, now);
- std::this_thread::sleep_until(nextVsync);
-
- {
- std::unique_lock<std::mutex> lock(mStateMutex);
-
- mPreviousVsync = nextVsync;
-
- // Display has finished refreshing at previous vsync period. Update the
- // vsync period if there was a pending update.
- vsyncPeriod = updateVsyncPeriodLocked(mPreviousVsync);
- }
-
- if (mVsyncEnabled) {
- if (mVsync24Callback) {
- DEBUG_LOG("%s: for display:%" PRIu64 " calling vsync_2_4", __FUNCTION__,
- mDisplayId);
- mVsync24Callback(mVsync24CallbackData, mDisplayId, asNanos(nextVsync),
- asNanos(vsyncPeriod));
- } else if (mVsyncCallback) {
- DEBUG_LOG("%s: for display:%" PRIu64 " calling vsync", __FUNCTION__,
- mDisplayId);
- mVsyncCallback(mVsyncCallbackData, mDisplayId, asNanos(nextVsync));
- }
- }
-
- static constexpr const int kLogIntervalSeconds = 60;
- if (now > (previousLog + std::chrono::seconds(kLogIntervalSeconds))) {
- DEBUG_LOG("%s: for display:%" PRIu64 " send %" PRIu32
- " in last %d seconds",
- __FUNCTION__, mDisplayId, vsyncs, kLogIntervalSeconds);
- previousLog = now;
- vsyncs = 0;
- }
- ++vsyncs;
- }
-
- DEBUG_LOG("%s: for display:%" PRIu64 " started", __FUNCTION__, mDisplayId);
- return false;
-}
-
-} // namespace android
diff --git a/system/hwc2/VsyncThread.h b/system/hwc2/VsyncThread.h
deleted file mode 100644
index e7c237c..0000000
--- a/system/hwc2/VsyncThread.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2021 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_HWC_VSYNCTHREAD_H
-#define ANDROID_HWC_VSYNCTHREAD_H
-
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <utils/Thread.h>
-
-#include <chrono>
-#include <mutex>
-#include <optional>
-
-#include "Common.h"
-
-namespace android {
-
-// Generates Vsync signals in software.
-class VsyncThread : public Thread {
- public:
- VsyncThread(hwc2_display_t id);
- virtual ~VsyncThread() {}
-
- VsyncThread(const VsyncThread&) = default;
- VsyncThread& operator=(const VsyncThread&) = default;
-
- VsyncThread(VsyncThread&&) = default;
- VsyncThread& operator=(VsyncThread&&) = default;
-
- HWC2::Error start(hwc2_vsync_period_t period);
-
- HWC2::Error setVsyncCallback(HWC2_PFN_VSYNC callback,
- hwc2_callback_data_t callbackData);
- HWC2::Error setVsync24Callback(HWC2_PFN_VSYNC_2_4 callback,
- hwc2_callback_data_t callbackData);
-
- HWC2::Error setVsyncEnabled(bool enabled);
-
- HWC2::Error scheduleVsyncUpdate(
- hwc2_vsync_period_t newVsyncPeriod,
- hwc_vsync_period_change_constraints_t* newVsyncPeriodChangeConstraints,
- hwc_vsync_period_change_timeline_t* timeline);
-
- private:
- bool threadLoop() final;
-
- std::chrono::nanoseconds updateVsyncPeriodLocked(
- std::chrono::time_point<std::chrono::steady_clock> now);
-
- const hwc2_display_t mDisplayId;
-
- std::mutex mStateMutex;
-
- HWC2_PFN_VSYNC mVsyncCallback;
- hwc2_callback_data_t mVsyncCallbackData = nullptr;
-
- HWC2_PFN_VSYNC_2_4 mVsync24Callback;
- hwc2_callback_data_t mVsync24CallbackData = nullptr;
-
- bool mVsyncEnabled = false;
- std::chrono::nanoseconds mVsyncPeriod;
- std::chrono::time_point<std::chrono::steady_clock> mPreviousVsync;
-
- struct PendingUpdate {
- std::chrono::nanoseconds period;
- std::chrono::time_point<std::chrono::steady_clock> updateAfter;
- };
- std::optional<PendingUpdate> mPendingUpdate;
-};
-
-} // namespace android
-
-#endif
\ No newline at end of file
diff --git a/system/hwc2/android.hardware.graphics.composer@2.3.xml b/system/hwc2/android.hardware.graphics.composer@2.3.xml
deleted file mode 100644
index 07bb8d7..0000000
--- a/system/hwc2/android.hardware.graphics.composer@2.3.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.graphics.composer</name>
- <transport>hwbinder</transport>
- <version>2.3</version>
- <interface>
- <name>IComposer</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/system/hwc2/android.hardware.graphics.composer@2.4.xml b/system/hwc2/android.hardware.graphics.composer@2.4.xml
deleted file mode 100644
index 7f37bbd..0000000
--- a/system/hwc2/android.hardware.graphics.composer@2.4.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.graphics.composer</name>
- <transport>hwbinder</transport>
- <version>2.4</version>
- <interface>
- <name>IComposer</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/system/hwc2/drmTest.cpp b/system/hwc2/drmTest.cpp
deleted file mode 100644
index 254772c..0000000
--- a/system/hwc2/drmTest.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <time.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferAllocator.h>
-#include <unistd.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include "HostConnection.h"
-#include "cros_gralloc_handle.h"
-
-using namespace android;
-
-struct buffer_object {
- uint32_t width;
- uint32_t height;
- uint32_t pitch;
- uint32_t handle;
- uint32_t size;
- uint8_t *vaddr;
- uint32_t fb_id;
- const native_handle_t *fb;
-};
-
-struct buffer_object buf;
-
-static int modeset_create_fb(int fd, struct buffer_object *bo) {
- struct drm_mode_create_dumb create = {};
- struct drm_mode_map_dumb map = {};
-
- create.width = bo->width;
- create.height = bo->height;
- create.bpp = 32;
- drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
- printf("create dumb w %d h %d\n", bo->width, bo->height);
- getchar();
-
- bo->pitch = create.pitch;
- bo->size = create.size;
- bo->handle = create.handle;
- drmModeAddFB(fd, bo->width, bo->height, 24, 32, bo->pitch, bo->handle,
- &bo->fb_id);
- printf("drmModeAddFB\n");
- getchar();
-
- map.handle = create.handle;
- drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
- printf("map dumb\n");
- getchar();
- bo->vaddr = static_cast<unsigned char *>(mmap64(
- 0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, map.offset));
- memset(bo->vaddr, 0xff, bo->size);
- return 0;
-}
-
-static void modeset_destroy_fb(int fd, struct buffer_object *bo) {
- struct drm_mode_destroy_dumb destroy = {};
-
- drmModeRmFB(fd, bo->fb_id);
- munmap(bo->vaddr, bo->size);
- destroy.handle = bo->handle;
- drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
-}
-
-static uint32_t get_property_id(int fd, drmModeObjectProperties *props,
- const char *name) {
- drmModePropertyPtr property;
- uint32_t i, id = 0;
-
- /* find property according to the name */
- for (i = 0; i < props->count_props; i++) {
- property = drmModeGetProperty(fd, props->props[i]);
- if (!strcmp(property->name, name)) id = property->prop_id;
- drmModeFreeProperty(property);
- if (id) {
- break;
- }
- }
- return id;
-}
-
-static std::unique_ptr<HostConnection> sHostCon;
-
-static HostConnection *createOrGetHostConnection() {
- if (!sHostCon) {
- sHostCon = HostConnection::createUnique();
- }
- return sHostCon.get();
-}
-
-#define DEFINE_AND_VALIDATE_HOST_CONNECTION \
- HostConnection *hostCon = createOrGetHostConnection(); \
- if (!hostCon) { \
- ALOGE("drmTest: Failed to get host connection\n"); \
- return; \
- } \
- ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
- if (!rcEnc) { \
- ALOGE("drmTest: Failed to get renderControl encoder context\n"); \
- return; \
- }
-
-#include "drmhwcgralloc.h"
-void convertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
- cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle;
- if (!gr_handle) return;
-
- bo->width = gr_handle->width;
- bo->height = gr_handle->height;
- bo->hal_format = gr_handle->droid_format;
- bo->format = gr_handle->format;
- bo->usage = gr_handle->usage;
- bo->prime_fds[0] = gr_handle->fds[0];
- bo->pitches[0] = gr_handle->strides[0];
- bo->offsets[0] = gr_handle->offsets[0];
-}
-
-void grallocAllocBuffer(int fd, struct buffer_object *bo) {
- buffer_handle_t h;
- uint32_t stride;
-
- if (GraphicBufferAllocator::get().allocate(
- bo->width, bo->height, android::PIXEL_FORMAT_RGBA_8888, 1,
- (GraphicBuffer::USAGE_HW_COMPOSER | GraphicBuffer::USAGE_HW_RENDER),
- &h, &stride, 0, "emulatorDrmTest") == android::OK) {
- hwc_drm_bo tmp_bo{};
- convertBoInfo(h, &tmp_bo);
-
- int ret = drmPrimeFDToHandle(fd, tmp_bo.prime_fds[0], tmp_bo.gem_handles);
- for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) {
- tmp_bo.gem_handles[i] = tmp_bo.gem_handles[0];
- }
- if (ret) {
- printf("%s: DRM_IOCTL_PRIME_FD_TO_HANDLE failed: %s (errno %d)\n",
- __func__, strerror(errno), errno);
- return;
- }
- ret = drmModeAddFB2(fd, tmp_bo.width, tmp_bo.height, tmp_bo.format,
- tmp_bo.gem_handles, tmp_bo.pitches, tmp_bo.offsets,
- &bo->fb_id, 0);
-
- printf("allocate buffer\n");
- DEFINE_AND_VALIDATE_HOST_CONNECTION
- bo->fb = static_cast<const native_handle_t *>(h);
- getchar();
- printf("resource id is %d\n",
- hostCon->grallocHelper()->getHostHandle(bo->fb));
- } else {
- bo->fb = nullptr;
- }
-}
-
-int main(int argc, char **argv) {
- int fd;
- drmModeConnector *conn;
- drmModeRes *res;
- drmModePlaneRes *plane_res = nullptr;
- uint32_t conn_id;
- uint32_t crtc_id;
- uint32_t plane_id;
-
- fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
-
- int ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 0);
- if (ret) {
- printf("fail to set universal plane %d\n", ret);
- }
-
- res = drmModeGetResources(fd);
- crtc_id = res->crtcs[0];
- conn_id = res->connectors[0];
-
- plane_res = drmModeGetPlaneResources(fd);
- plane_id = plane_res->planes[0];
-
- conn = drmModeGetConnector(fd, conn_id);
- buf.width = conn->modes[0].hdisplay;
- buf.height = conn->modes[0].vdisplay;
- // modeset_create_fb(fd, &buf);
- grallocAllocBuffer(fd, &buf);
-
- drmModeSetCrtc(fd, crtc_id, buf.fb_id, 0, 0, &conn_id, 1, &conn->modes[0]);
- printf("drmModeSetCrtc\n");
- getchar();
-
- drmModePageFlip(fd, crtc_id, buf.fb_id, DRM_MODE_PAGE_FLIP_EVENT, &crtc_id);
- printf("drmModePageFlip\n");
- getchar();
-
- // drmModeSetPlane(fd, plane_id, crtc_id, buf.fb_id, 0, 50, 50, 320, 320,
- // 100 << 16, 150 << 16, 320 << 16, 320 << 16);
- // printf("drmModeSetPlane\n");
- // modeset_destroy_fb(fd, &buf);
-
- drmModeFreeConnector(conn);
- drmModeFreeResources(res);
- close(fd);
-
- return 0;
-}
-
-int main_atom(int argc, char **argv) {
- int fd;
- drmModeConnector *conn = nullptr;
- drmModeRes *res = nullptr;
- drmModePlaneRes *plane_res = nullptr;
- drmModeObjectProperties *props = nullptr;
- drmModeAtomicReq *req;
- uint32_t conn_id;
- uint32_t crtc_id;
- uint32_t plane_id;
- uint32_t blob_id;
- uint32_t property_crtc_id;
- uint32_t property_mode_id;
- uint32_t property_active;
-
- printf("drm available %d\n", drmAvailable());
- fd = open("/dev/dri/card0", O_RDWR);
- printf("openg drm fd %d\n", fd);
-
- int ret = drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
- if (ret) {
- printf("fail to set universal plane %d\n", ret);
- }
-
- ret = drmSetClientCap(fd, DRM_CLIENT_CAP_ATOMIC, 1);
- if (ret) {
- printf("fail to set atomic operation %d\n", ret);
- }
-
- res = drmModeGetResources(fd);
- if (!res) {
- printf("error to get drmModeGetResources: %d\n", errno);
- }
-
- crtc_id = res->crtcs[0];
- conn_id = res->connectors[0];
- plane_res = drmModeGetPlaneResources(fd);
- plane_id = plane_res->planes[0];
-
- conn = drmModeGetConnector(fd, conn_id);
- buf.width = conn->modes[0].hdisplay;
- buf.height = conn->modes[0].vdisplay;
- modeset_create_fb(fd, &buf);
-
- /* get connector properties */
- props = drmModeObjectGetProperties(fd, conn_id, DRM_MODE_OBJECT_CONNECTOR);
- property_crtc_id = get_property_id(fd, props, "CRTC_ID");
- drmModeFreeObjectProperties(props);
-
- /* get crtc properties */
- props = drmModeObjectGetProperties(fd, crtc_id, DRM_MODE_OBJECT_CRTC);
- property_active = get_property_id(fd, props, "ACTIVE");
- property_mode_id = get_property_id(fd, props, "MODE_ID");
- drmModeFreeObjectProperties(props);
-
- /* create blob to store current mode, and return the blob id */
- drmModeCreatePropertyBlob(fd, &conn->modes[0], sizeof(conn->modes[0]),
- &blob_id);
-
- /* start modeseting */
- req = drmModeAtomicAlloc();
- drmModeAtomicAddProperty(req, crtc_id, property_active, 1);
- drmModeAtomicAddProperty(req, crtc_id, property_mode_id, blob_id);
- drmModeAtomicAddProperty(req, conn_id, property_crtc_id, crtc_id);
- drmModeAtomicCommit(fd, req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
- drmModeAtomicFree(req);
- printf("drmModeAtomicCommit SetCrtc\n");
- getchar();
-
- drmModeSetPlane(fd, plane_id, crtc_id, buf.fb_id, 0, 50, 50, 320, 320, 0, 0,
- 320 << 16, 320 << 16);
- printf("drmModeSetPlane\n");
- getchar();
-
- modeset_destroy_fb(fd, &buf);
- drmModeFreeConnector(conn);
- drmModeFreePlaneResources(plane_res);
- drmModeFreeResources(res);
- close(fd);
-
- return 0;
-}
diff --git a/system/hwc2/drmhwcgralloc.h b/system/hwc2/drmhwcgralloc.h
deleted file mode 100644
index 05b2cf0..0000000
--- a/system/hwc2/drmhwcgralloc.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 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_DRMHWCGRALLOC_H_
-#define ANDROID_DRMHWCGRALLOC_H_
-
-#include <stdint.h>
-
-#define HWC_DRM_BO_MAX_PLANES 4
-typedef struct hwc_drm_bo {
- uint32_t width;
- uint32_t height;
- uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */
- uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */
- uint32_t usage;
- uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
- uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
- uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES];
- uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES];
- uint64_t modifiers[HWC_DRM_BO_MAX_PLANES];
- uint32_t fb_id;
- int acquire_fence_fd;
- void *priv;
-} hwc_drm_bo_t;
-
-#endif // ANDROID_DRMHWCGRALLOC_H_
diff --git a/system/hwc3/ComposerClient.cpp b/system/hwc3/ComposerClient.cpp
index f7ba42e..6bd8f0c 100644
--- a/system/hwc3/ComposerClient.cpp
+++ b/system/hwc3/ComposerClient.cpp
@@ -1347,36 +1347,36 @@
uint32_t width, uint32_t height,
uint32_t dpiX, uint32_t dpiY,
uint32_t refreshRate) {
- std::unique_lock<std::mutex> lock(mStateMutex);
-
if (!mCallbacks) {
return HWC3::Error::None;
}
const int64_t displayId = static_cast<int64_t>(id);
- Display* display = getDisplay(displayId);
- if (display != nullptr) {
- ALOGI("Disconnecting display:%" PRIu64, displayId);
- mCallbacks->onHotplug(displayId, /*connected=*/false);
-
- destroyDisplayLocked(displayId);
- }
-
if (connected) {
const int32_t configId = static_cast<int32_t>(id);
const std::vector<DisplayConfig> configs = {
DisplayConfig(configId, static_cast<int>(width),
static_cast<int>(height), static_cast<int>(dpiX),
static_cast<int>(dpiY), static_cast<int>(refreshRate))};
-
- createDisplayLocked(displayId, configId, configs);
+ {
+ std::unique_lock<std::mutex> lock(mStateMutex);
+ createDisplayLocked(displayId, configId, configs);
+ }
ALOGI("Connecting display:%" PRIu32 " w:%" PRIu32 " h:%" PRIu32
" dpiX:%" PRIu32 " dpiY %" PRIu32 "fps %" PRIu32,
id, width, height, dpiX, dpiY, refreshRate);
-
mCallbacks->onHotplug(displayId, /*connected=*/true);
+ } else {
+ ALOGI("Disconnecting display:%" PRIu64, displayId);
+ mCallbacks->onHotplug(displayId, /*connected=*/false);
+
+ Display* display = getDisplay(displayId);
+ if (display != nullptr) {
+ std::unique_lock<std::mutex> lock(mStateMutex);
+ destroyDisplayLocked(displayId);
+ }
}
return HWC3::Error::None;
diff --git a/system/hwc3/DrmClient.cpp b/system/hwc3/DrmClient.cpp
index 2f0ffaa..b25acc3 100644
--- a/system/hwc3/DrmClient.cpp
+++ b/system/hwc3/DrmClient.cpp
@@ -263,23 +263,48 @@
bool DrmClient::handleHotplug() {
DEBUG_LOG("%s", __FUNCTION__);
- AutoWriteLock lock(mDisplaysMutex);
+ struct HotplugToReport {
+ uint32_t id;
+ uint32_t width;
+ uint32_t height;
+ uint32_t dpiX;
+ uint32_t dpiY;
+ uint32_t rr;
+ bool connected;
+ };
- for (auto& display : mDisplays) {
- auto change = display->checkAndHandleHotplug(mFd);
- if (change == DrmHotplugChange::kNoChange) {
- continue;
+ std::vector<HotplugToReport> hotplugs;
+
+ {
+ AutoWriteLock lock(mDisplaysMutex);
+
+ for (auto& display : mDisplays) {
+ auto change = display->checkAndHandleHotplug(mFd);
+ if (change == DrmHotplugChange::kNoChange) {
+ continue;
+ }
+
+ hotplugs.push_back(HotplugToReport{
+ .id = display->getId(),
+ .width = display->getWidth(),
+ .height = display->getHeight(),
+ .dpiX = display->getDpiX(),
+ .dpiY = display->getDpiY(),
+ .rr = display->getRefreshRateUint(),
+ .connected = change == DrmHotplugChange::kConnected,
+ });
}
+ }
+ for (const auto& hotplug : hotplugs) {
if (mHotplugCallback) {
- const bool connected = (change == DrmHotplugChange::kConnected);
- (*mHotplugCallback)(connected, //
- display->getId(), //
- display->getWidth(), //
- display->getHeight(), //
- display->getDpiX(), //
- display->getDpiY(), //
- display->getRefreshRateUint());
+ (*mHotplugCallback)(hotplug.connected, //
+ hotplug.id, //
+ hotplug.width, //
+ hotplug.height, //
+ hotplug.dpiX, //
+ hotplug.dpiY, //
+ hotplug.rr);
}
}
diff --git a/system/hwc3/Layer.h b/system/hwc3/Layer.h
index 7d6a9ed..4d100a1 100644
--- a/system/hwc3/Layer.h
+++ b/system/hwc3/Layer.h
@@ -31,8 +31,8 @@
Layer(const Layer&) = delete;
Layer& operator=(const Layer&) = delete;
- Layer(Layer&&) = default;
- Layer& operator=(Layer&&) = default;
+ Layer(Layer&&) = delete;
+ Layer& operator=(Layer&&) = delete;
int64_t getId() const { return mId; }
@@ -113,4 +113,4 @@
} // namespace aidl::android::hardware::graphics::composer3::impl
-#endif
\ No newline at end of file
+#endif
diff --git a/system/hwc3/VsyncThread.h b/system/hwc3/VsyncThread.h
index 5738b5d..ffa859f 100644
--- a/system/hwc3/VsyncThread.h
+++ b/system/hwc3/VsyncThread.h
@@ -36,11 +36,11 @@
VsyncThread(int64_t id);
virtual ~VsyncThread();
- VsyncThread(const VsyncThread&) = default;
- VsyncThread& operator=(const VsyncThread&) = default;
+ VsyncThread(const VsyncThread&) = delete;
+ VsyncThread& operator=(const VsyncThread&) = delete;
- VsyncThread(VsyncThread&&) = default;
- VsyncThread& operator=(VsyncThread&&) = default;
+ VsyncThread(VsyncThread&&) = delete;
+ VsyncThread& operator=(VsyncThread&&) = delete;
HWC3::Error start(int32_t periodNanos);
@@ -84,4 +84,4 @@
} // namespace aidl::android::hardware::graphics::composer3::impl
-#endif
\ No newline at end of file
+#endif
diff --git a/system/vulkan_enc/CommandBufferStagingStream.cpp b/system/vulkan_enc/CommandBufferStagingStream.cpp
index 0890185..8487bcd 100644
--- a/system/vulkan_enc/CommandBufferStagingStream.cpp
+++ b/system/vulkan_enc/CommandBufferStagingStream.cpp
@@ -33,127 +33,130 @@
static const size_t kReadSize = 512 * 1024;
static const size_t kWriteOffset = kReadSize;
-CommandBufferStagingStream::CommandBufferStagingStream(Alloc&& allocFn, Free&& freeFn)
- : IOStream(1048576),
- m_buf(nullptr),
- m_size(0),
- m_writePos(0),
- m_customAlloc(allocFn),
- m_customFree(freeFn) {
- // custom allocator/free
- if (allocFn && freeFn) {
- m_usingCustomAlloc = true;
- // for custom allocation, allocate metadata memory at the beginning.
- // m_alloc, m_free and m_realloc wraps sync data logic
-
- // \param size to allocate
- // \return ptr starting at data
- m_alloc = [this](size_t size) -> void* {
- // allocation requested size + sync data size
-
- // <---sync bytes--><----Data--->
- // |———————————————|————————————|
- // |0|1|2|3|4|5|6|7|............|
- // |———————————————|————————————|
- // ꜛ ꜛ
- // allocated ptr ptr to data [dataPtr]
- const size_t totalSize = size + kSyncDataSize;
-
- unsigned char* dataPtr = static_cast<unsigned char*>(m_customAlloc(totalSize));
- if (!dataPtr) {
- ALOGE("Custom allocation (%zu bytes) failed\n", size);
- return nullptr;
- }
-
- // set DWORD sync data to 0
- *(reinterpret_cast<uint32_t*>(dataPtr)) = kSyncDataReadComplete;
-
- // pointer for data starts after sync data
- dataPtr += kSyncDataSize;
-
- return dataPtr;
+CommandBufferStagingStream::CommandBufferStagingStream()
+ : IOStream(1048576), m_size(0), m_writePos(0) {
+ // use default allocators
+ m_alloc = [](size_t size) -> Memory {
+ return {
+ .deviceMemory = VK_NULL_HANDLE, // no device memory for malloc
+ .ptr = malloc(size),
};
+ };
+ m_free = [](const Memory& mem) { free(mem.ptr); };
+ m_realloc = [](const Memory& mem, size_t size) -> Memory {
+ return {.deviceMemory = VK_NULL_HANDLE, .ptr = realloc(mem.ptr, size)};
+ };
+}
- // Free freeMemory(freeFn);
- // \param dataPtr to free
- m_free = [this](void* dataPtr) {
- // for custom allocation/free, memory holding metadata must be freed
- // <---sync byte---><----Data--->
- // |———————————————|————————————|
- // |0|1|2|3|4|5|6|7|............|
- // |———————————————|————————————|
- // ꜛ ꜛ
- // ptr to free ptr to data [dataPtr]
- unsigned char* toFreePtr = static_cast<unsigned char*>(dataPtr);
- toFreePtr -= kSyncDataSize;
- m_customFree(toFreePtr);
- };
+CommandBufferStagingStream::CommandBufferStagingStream(const Alloc& allocFn, const Free& freeFn)
+ : CommandBufferStagingStream() {
+ m_usingCustomAlloc = true;
+ // for custom allocation, allocate metadata memory at the beginning.
+ // m_alloc, m_free and m_realloc wraps sync data logic
- // \param ptr is the data pointer currently allocated
- // \return dataPtr starting at data
- m_realloc = [this](void* ptr, size_t size) -> void* {
- // realloc requires freeing previously allocated memory
- // read sync DWORD to ensure host is done reading this memory
- // before releasing it.
+ // \param size to allocate
+ // \return ptr starting at data
+ m_alloc = [&allocFn, this](size_t size) -> Memory {
+ // allocation requested size + sync data size
- size_t hostWaits = 0;
- unsigned char* syncDataStart = static_cast<unsigned char*>(ptr) - kSyncDataSize;
- uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(syncDataStart);
+ // <---sync bytes--><----Data--->
+ // |———————————————|————————————|
+ // |0|1|2|3|4|5|6|7|............|
+ // |———————————————|————————————|
+ // ꜛ ꜛ
+ // allocated ptr ptr to data [dataPtr]
- while (__atomic_load_n(syncDWordPtr, __ATOMIC_ACQUIRE) != kSyncDataReadComplete) {
- hostWaits++;
- usleep(10);
- if (hostWaits > 1000) {
- ALOGD("%s: warning, stalled on host decoding on this command buffer stream\n",
- __func__);
- }
+ Memory memory;
+ if (!allocFn) {
+ ALOGE("Custom allocation (%zu bytes) failed\n", size);
+ return memory;
+ }
+
+ // custom allocation/free requires metadata for sync between host/guest
+ const size_t totalSize = size + kSyncDataSize;
+ memory = allocFn(totalSize);
+ if (!memory.ptr) {
+ ALOGE("Custom allocation (%zu bytes) failed\n", size);
+ return memory;
+ }
+
+ // set sync data to read complete
+ uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(memory.ptr);
+ __atomic_store_n(syncDWordPtr, kSyncDataReadComplete, __ATOMIC_RELEASE);
+ return memory;
+ };
+
+ m_free = [&freeFn](const Memory& mem) {
+ if (!freeFn) {
+ ALOGE("Custom free for memory(%p) failed\n", mem.ptr);
+ return;
+ }
+ freeFn(mem);
+ };
+
+ // \param ptr is the data pointer currently allocated
+ // \return dataPtr starting at data
+ m_realloc = [this](const Memory& mem, size_t size) -> Memory {
+ // realloc requires freeing previously allocated memory
+ // read sync DWORD to ensure host is done reading this memory
+ // before releasing it.
+
+ size_t hostWaits = 0;
+
+ uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(mem.ptr);
+ while (__atomic_load_n(syncDWordPtr, __ATOMIC_ACQUIRE) != kSyncDataReadComplete) {
+ hostWaits++;
+ usleep(10);
+ if (hostWaits > 1000) {
+ ALOGD("%s: warning, stalled on host decoding on this command buffer stream\n",
+ __func__);
}
+ }
- // for custom allocation/free, memory holding metadata must be copied
- // along with stream data
- // <---sync byte---><----Data--->
- // |———————————————|————————————|
- // |0|1|2|3|4|5|6|7|............|
- // |———————————————|————————————|
- // ꜛ ꜛ
- // [copyLocation] ptr to data [ptr]
+ // for custom allocation/free, memory holding metadata must be copied
+ // along with stream data
+ // <---sync bytes--><----Data--->
+ // |———————————————|————————————|
+ // |0|1|2|3|4|5|6|7|............|
+ // |———————————————|————————————|
+ // ꜛ ꜛ
+ // [copyLocation] ptr to data [ptr]
- const size_t toCopySize = m_writePos + kSyncDataSize;
- unsigned char* copyLocation = static_cast<unsigned char*>(ptr) - kSyncDataSize;
- std::vector<uint8_t> tmp(copyLocation, copyLocation + toCopySize);
- m_free(ptr);
+ const size_t toCopySize = m_writePos + kSyncDataSize;
+ unsigned char* copyLocation = static_cast<unsigned char*>(mem.ptr);
+ std::vector<uint8_t> tmp(copyLocation, copyLocation + toCopySize);
+ m_free(mem);
- // get new buffer and copy previous stream data to it
- unsigned char* newBuf = static_cast<unsigned char*>(m_alloc(size));
- if (!newBuf) {
- ALOGE("Custom allocation (%zu bytes) failed\n", size);
- return nullptr;
- }
- // custom allocator will allocate space for metadata too
- // copy previous metadata too
- memcpy(newBuf - kSyncDataSize, tmp.data(), toCopySize);
+ // get new buffer and copy previous stream data to it
+ Memory newMemory = m_alloc(size);
+ unsigned char* newBuf = static_cast<unsigned char*>(newMemory.ptr);
+ if (!newBuf) {
+ ALOGE("Custom allocation (%zu bytes) failed\n", size);
+ return newMemory;
+ }
+ // copy previous data
+ memcpy(newBuf, tmp.data(), toCopySize);
- return newBuf;
- };
- } else {
- // use default allocators
- m_alloc = [](size_t size) { return malloc(size); };
- m_free = [](void* ptr) { free(ptr); };
- m_realloc = [](void* ptr, size_t size) { return realloc(ptr, size); };
- }
+ return newMemory;
+ };
}
CommandBufferStagingStream::~CommandBufferStagingStream() {
flush();
- if (m_buf) m_free(m_buf);
+ if (m_mem.ptr) m_free(m_mem);
+}
+
+unsigned char* CommandBufferStagingStream::getDataPtr() {
+ if (!m_mem.ptr) return nullptr;
+ const size_t metadataSize = m_usingCustomAlloc ? kSyncDataSize : 0;
+ return static_cast<unsigned char*>(m_mem.ptr) + metadataSize;
}
void CommandBufferStagingStream::markFlushing() {
if (!m_usingCustomAlloc) {
return;
}
- // mark read of stream buffer as pending
- uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(m_buf - kSyncDataSize);
+ uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(m_mem.ptr);
__atomic_store_n(syncDWordPtr, kSyncDataReadPending, __ATOMIC_RELEASE);
}
@@ -165,10 +168,10 @@
void* CommandBufferStagingStream::allocBuffer(size_t minSize) {
size_t allocSize = (1048576 < minSize ? minSize : 1048576);
// Initial case: blank
- if (!m_buf) {
- m_buf = (unsigned char*)m_alloc(allocSize);
+ if (!m_mem.ptr) {
+ m_mem = m_alloc(allocSize);
m_size = allocSize;
- return (void*)m_buf;
+ return getDataPtr();
}
// Calculate remaining
@@ -177,13 +180,25 @@
// if not, reallocate a buffer of big enough size
if (remaining < minSize) {
size_t newAllocSize = m_size * 2 + allocSize;
- m_buf = (unsigned char*)m_realloc(m_buf, newAllocSize);
+ m_mem = m_realloc(m_mem, newAllocSize);
m_size = newAllocSize;
- return (void*)(m_buf + m_writePos);
+ return (void*)(getDataPtr() + m_writePos);
}
- return (void*)(m_buf + m_writePos);
+ // for custom allocations, host should have finished reading
+ // data from command buffer since command buffers are flushed
+ // on queue submit.
+ // allocBuffer should not be called on command buffers that are currently
+ // being read by the host
+ if (m_usingCustomAlloc) {
+ uint32_t* syncDWordPtr = reinterpret_cast<uint32_t*>(m_mem.ptr);
+ LOG_ALWAYS_FATAL_IF(
+ __atomic_load_n(syncDWordPtr, __ATOMIC_ACQUIRE) != kSyncDataReadComplete,
+ "FATAL: allocBuffer() called but previous read not complete");
+ }
+
+ return (void*)(getDataPtr() + m_writePos);
}
int CommandBufferStagingStream::commitBuffer(size_t size)
@@ -224,7 +239,7 @@
}
void CommandBufferStagingStream::getWritten(unsigned char** bufOut, size_t* sizeOut) {
- *bufOut = m_buf;
+ *bufOut = getDataPtr();
*sizeOut = m_writePos;
}
@@ -232,3 +247,5 @@
m_writePos = 0;
IOStream::rewind();
}
+
+VkDeviceMemory CommandBufferStagingStream::getDeviceMemory() { return m_mem.deviceMemory; }
\ No newline at end of file
diff --git a/system/vulkan_enc/CommandBufferStagingStream.h b/system/vulkan_enc/CommandBufferStagingStream.h
index 9513b45..2742e20 100644
--- a/system/vulkan_enc/CommandBufferStagingStream.h
+++ b/system/vulkan_enc/CommandBufferStagingStream.h
@@ -16,9 +16,12 @@
#ifndef __COMMAND_BUFFER_STAGING_STREAM_H
#define __COMMAND_BUFFER_STAGING_STREAM_H
-#include "IOStream.h"
+#include <vulkan/vulkan_core.h>
+
#include <functional>
+#include "IOStream.h"
+
class CommandBufferStagingStream : public IOStream {
public:
// host will write kSyncDataReadComplete to the sync bytes to indicate memory is no longer being
@@ -31,18 +34,29 @@
// indicates read is pending
static constexpr uint32_t kSyncDataReadPending = 0X1;
+ // \struct backing memory structure
+ struct Memory {
+ VkDeviceMemory deviceMemory =
+ VK_NULL_HANDLE; // device memory associated with allocated memory
+ void* ptr = nullptr; // pointer to allocated memory
+ bool operator==(const Memory& rhs) const {
+ return (deviceMemory == rhs.deviceMemory) && (ptr == rhs.ptr);
+ }
+ };
+
// allocator
// param size to allocate
- // return pointer to allocated memory
- using Alloc = std::function<void*(size_t)>;
+ // return allocated memory
+ using Alloc = std::function<Memory(size_t)>;
// free function
- // param pointer to free
- using Free = std::function<void(void*)>;
+ // param memory to free
+ using Free = std::function<void(const Memory&)>;
// constructor
- // \param allocFn is the allocation function provided. Default allocation function used if nullptr
- // \param freeFn is the free function provided. Default free function used if nullptr
- // freeFn must be provided if allocFn is provided and vice versa
- explicit CommandBufferStagingStream(Alloc&& allocFn = nullptr, Free&& freeFn = nullptr);
+ // \param allocFn is the allocation function provided.
+ // \param freeFn is the free function provided
+ explicit CommandBufferStagingStream(const Alloc& allocFn, const Free& freeFn);
+ // constructor
+ explicit CommandBufferStagingStream();
~CommandBufferStagingStream();
virtual size_t idealAllocSize(size_t len);
@@ -63,38 +77,37 @@
// when not using custom allocators
void markFlushing();
+ // gets the device memory associated with the stream. This is VK_NULL_HANDLE for default allocation
+ // \return device memory
+ VkDeviceMemory getDeviceMemory();
+
private:
- // underlying buffer for data
- unsigned char* m_buf;
- // size of portion of m_buf available for data.
+ // underlying memory for data
+ Memory m_mem;
+ // size of portion of memory available for data.
// for custom allocation, this size excludes size of sync data.
size_t m_size;
- // current write position in m_buf
+ // current write position in data buffer
uint32_t m_writePos;
+ // alloc function
Alloc m_alloc;
+ // free function
Free m_free;
- // underlying custom alloc. default is null
- Alloc m_customAlloc = nullptr;
- // underlying free alloc. default is null
- Free m_customFree = nullptr;
-
// realloc function
// \param size of memory to be allocated
// \ param reference size to update with actual size allocated. This size can be < requested size
// for custom allocation to account for sync data
- using Realloc = std::function<void*(void*, size_t)>;
+ using Realloc = std::function<Memory(const Memory&, size_t)>;
Realloc m_realloc;
// flag tracking use of custom allocation/free
bool m_usingCustomAlloc = false;
- // calculates actual allocation size for data
- // \param requestedSize is the size requested for allocation
- // \return actual data size allocated for requested size. For
- // custom allocation the data size < requested size to account for sync data word
- size_t getDataAllocationSize(const size_t requestedSize);
+ // adjusted memory location to point to start of data after accounting for metadata
+ // \return pointer to data start
+ unsigned char* getDataPtr();
};
#endif
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index aebcdc0..5c1bd72 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -15,18 +15,15 @@
#include "ResourceTracker.h"
-#include "Resources.h"
-#include "CommandBufferStagingStream.h"
-#include "DescriptorSetVirtualization.h"
-
-#include "aemu/base/Optional.h"
-#include "aemu/base/threads/AndroidWorkPool.h"
-#include "aemu/base/Tracing.h"
-
-#include "goldfish_vk_private_defs.h"
-
#include "../OpenglSystemCommon/EmulatorFeatureInfo.h"
#include "../OpenglSystemCommon/HostConnection.h"
+#include "CommandBufferStagingStream.h"
+#include "DescriptorSetVirtualization.h"
+#include "Resources.h"
+#include "aemu/base/Optional.h"
+#include "aemu/base/Tracing.h"
+#include "aemu/base/threads/AndroidWorkPool.h"
+#include "goldfish_vk_private_defs.h"
#include "vulkan/vulkan_core.h"
/// Use installed headers or locally defined Fuchsia-specific bits
@@ -205,6 +202,14 @@
Lock mLock;
std::vector<CommandBufferStagingStream*> streams;
std::vector<VkEncoder*> encoders;
+ /// \brief sets alloc and free callbacks for memory allocation for CommandBufferStagingStream(s)
+ /// \param allocFn is the callback to allocate memory
+ /// \param freeFn is the callback to free memory
+ void setAllocFree(CommandBufferStagingStream::Alloc&& allocFn,
+ CommandBufferStagingStream::Free&& freeFn) {
+ mAlloc = allocFn;
+ mFree = freeFn;
+ }
~StagingInfo() {
for (auto stream : streams) {
@@ -228,7 +233,12 @@
CommandBufferStagingStream* stream;
VkEncoder* encoder;
if (streams.empty()) {
- stream = new CommandBufferStagingStream;
+ if (mAlloc && mFree) {
+ // if custom allocators are provided, forward them to CommandBufferStagingStream
+ stream = new CommandBufferStagingStream(mAlloc, mFree);
+ } else {
+ stream = new CommandBufferStagingStream;
+ }
encoder = new VkEncoder(stream);
} else {
stream = streams.back();
@@ -239,6 +249,10 @@
*streamOut = stream;
*encoderOut = encoder;
}
+
+ private:
+ CommandBufferStagingStream::Alloc mAlloc = nullptr;
+ CommandBufferStagingStream::Free mFree = nullptr;
};
static StagingInfo sStaging;
@@ -2933,8 +2947,8 @@
return coherentMemory;
}
- VkResult allocateCoherentMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
- VkEncoder *enc, VkDeviceMemory* pMemory) {
+ VkResult allocateCoherentMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
+ VkEncoder* enc, VkDeviceMemory* pMemory) {
uint64_t offset = 0;
uint8_t *ptr = nullptr;
VkMemoryAllocateFlagsInfo allocFlagsInfo;
@@ -3019,7 +3033,6 @@
VkResult getCoherentMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkEncoder* enc,
VkDevice device, VkDeviceMemory* pMemory) {
-
VkMemoryAllocateFlagsInfo allocFlagsInfo;
VkMemoryOpaqueCaptureAddressAllocateInfo opaqueCaptureAddressAllocInfo;
@@ -3061,6 +3074,9 @@
info.coherentMemory = coherentMemory;
info.device = device;
+ // for suballocated memory, create an alias VkDeviceMemory handle for application
+ // memory used for suballocations will still be VkDeviceMemory associated with
+ // CoherentMemory
auto mem = new_from_host_VkDeviceMemory(VK_NULL_HANDLE);
info_VkDeviceMemory[mem] = info;
*pMemory = mem;
@@ -3188,8 +3204,20 @@
const VkMemoryDedicatedAllocateInfo* dedicatedAllocInfoPtr =
vk_find_struct<VkMemoryDedicatedAllocateInfo>(pAllocateInfo);
+ // Note for AHardwareBuffers, the Vulkan spec states:
+ //
+ // Android hardware buffers have intrinsic width, height, format, and usage
+ // properties, so Vulkan images bound to memory imported from an Android
+ // hardware buffer must use dedicated allocations
+ //
+ // so any allocation requests with a VkImportAndroidHardwareBufferInfoANDROID
+ // will necessarily have a VkMemoryDedicatedAllocateInfo. However, the host
+ // may or may not actually use a dedicated allocation to emulate
+ // AHardwareBuffers. As such, the VkMemoryDedicatedAllocateInfo is passed to the
+ // host and the host will decide whether or not to use it.
+
bool shouldPassThroughDedicatedAllocInfo =
- !exportAllocateInfoPtr && !importAhbInfoPtr &&
+ !exportAllocateInfoPtr &&
!importBufferCollectionInfoPtr &&
!importVmoInfoPtr;
@@ -3731,6 +3759,23 @@
_RETURN_SCUCCESS_WITH_DEVICE_MEMORY_REPORT;
}
+ CoherentMemoryPtr freeCoherentMemoryLocked(VkDeviceMemory memory, VkDeviceMemory_Info& info) {
+ if (info.coherentMemory && info.ptr) {
+ if (info.coherentMemory->getDeviceMemory() != memory) {
+ delete_goldfish_VkDeviceMemory(memory);
+ }
+
+ if (info.ptr) {
+ info.coherentMemory->release(info.ptr);
+ info.ptr = nullptr;
+ }
+
+ return std::move(info.coherentMemory);
+ }
+
+ return nullptr;
+ }
+
void on_vkFreeMemory(
void* context,
VkDevice device,
@@ -3748,15 +3793,12 @@
memoryObjectId = getAHardwareBufferId(info.ahw);
}
#endif
- emitDeviceMemoryReport(
- info_VkDevice[device],
- info.imported ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT
- : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT,
- memoryObjectId,
- 0 /* size */,
- VK_OBJECT_TYPE_DEVICE_MEMORY,
- (uint64_t)(void*)memory
- );
+
+ emitDeviceMemoryReport(info_VkDevice[device],
+ info.imported ? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT
+ : VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT,
+ memoryObjectId, 0 /* size */, VK_OBJECT_TYPE_DEVICE_MEMORY,
+ (uint64_t)(void*)memory);
#ifdef VK_USE_PLATFORM_FUCHSIA
if (info.vmoHandle && info.ptr) {
@@ -3776,23 +3818,13 @@
return;
}
- if (info.coherentMemory && info.ptr) {
- if (info.coherentMemory->getDeviceMemory() != memory) {
- delete_goldfish_VkDeviceMemory(memory);
- }
+ auto coherentMemory = freeCoherentMemoryLocked(memory, info);
- if (info.ptr) {
- info.coherentMemory->release(info.ptr);
- info.ptr = nullptr;
- }
-
- auto coherentMemory = std::move(info.coherentMemory);
- // We have to release the lock before we could possibly free a
- // CoherentMemory, because that will call into VkEncoder, which
- // shouldn't be called when the lock is held.
- lock.unlock();
- coherentMemory = nullptr;
- }
+ // We have to release the lock before we could possibly free a
+ // CoherentMemory, because that will call into VkEncoder, which
+ // shouldn't be called when the lock is held.
+ lock.unlock();
+ coherentMemory = nullptr;
}
VkResult on_vkMapMemory(
@@ -5716,17 +5748,42 @@
unsigned char* writtenPtr = 0;
size_t written = 0;
- ((CommandBufferStagingStream*)cb->privateStream)->getWritten(&writtenPtr, &written);
+ CommandBufferStagingStream* cmdBufStream =
+ static_cast<CommandBufferStagingStream*>(cb->privateStream);
+ cmdBufStream->getWritten(&writtenPtr, &written);
// There's no pending commands here, skip. (case 2, stream created but no new recordings)
if (!written) continue;
// There are pending commands to flush.
VkEncoder* enc = (VkEncoder*)context;
- enc->vkQueueFlushCommandsGOOGLE(queue, cmdbuf, written, (const void*)writtenPtr, true /* do lock */);
+ VkDeviceMemory deviceMemory = cmdBufStream->getDeviceMemory();
+ VkDeviceSize dataOffset = 0;
+ if (mFeatureInfo->hasVulkanAuxCommandMemory) {
+ // for suballocations, deviceMemory is an alias VkDeviceMemory
+ // get underling VkDeviceMemory for given alias
+ deviceMemoryTransform_tohost(&deviceMemory, 1 /*memoryCount*/, &dataOffset,
+ 1 /*offsetCount*/, nullptr /*size*/, 0 /*sizeCount*/,
+ nullptr /*typeIndex*/, 0 /*typeIndexCount*/,
+ nullptr /*typeBits*/, 0 /*typeBitCounts*/);
+ // mark stream as flushing before flushing commands
+ cmdBufStream->markFlushing();
+ enc->vkQueueFlushCommandsFromAuxMemoryGOOGLE(queue, cmdbuf, deviceMemory,
+ dataOffset, written, true /*do lock*/);
+ } else {
+ enc->vkQueueFlushCommandsGOOGLE(queue, cmdbuf, written, (const void*)writtenPtr,
+ true /* do lock */);
+ }
// Reset this stream.
- ((CommandBufferStagingStream*)cb->privateStream)->reset();
+ // flushing happens on vkQueueSubmit
+ // vulkan api states that on queue submit,
+ // applications MUST not attempt to modify the command buffer in any way
+ // -as the device may be processing the commands recorded to it.
+ // It is safe to call reset() here for this reason.
+ // Command Buffer associated with this stream will only leave pending state
+ // after queue submit is complete and host has read the data
+ cmdBufStream->reset();
}
}
@@ -6603,6 +6660,69 @@
return 0;
}
+ CommandBufferStagingStream::Alloc getAlloc() {
+ if (mFeatureInfo->hasVulkanAuxCommandMemory) {
+ return [this](size_t size) -> CommandBufferStagingStream::Memory {
+ VkMemoryAllocateInfo info{
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = nullptr,
+ .allocationSize = size,
+ .memoryTypeIndex = VK_MAX_MEMORY_TYPES // indicates auxiliary memory
+ };
+
+ auto enc = ResourceTracker::getThreadLocalEncoder();
+ VkDevice device = VK_NULL_HANDLE;
+ VkDeviceMemory vkDeviceMem = VK_NULL_HANDLE;
+ VkResult result = getCoherentMemory(&info, enc, device, &vkDeviceMem);
+ if (result != VK_SUCCESS) {
+ ALOGE("Failed to get coherent memory %u", result);
+ return {.deviceMemory = VK_NULL_HANDLE, .ptr = nullptr};
+ }
+
+ // getCoherentMemory() uses suballocations.
+ // To retrieve the suballocated memory address, look up
+ // VkDeviceMemory filled in by getCoherentMemory()
+ // scope of mLock
+ {
+ AutoLock<RecursiveLock> lock(mLock);
+ const auto it = info_VkDeviceMemory.find(vkDeviceMem);
+ if (it == info_VkDeviceMemory.end()) {
+ ALOGE("Coherent memory allocated %u not found", result);
+ return {.deviceMemory = VK_NULL_HANDLE, .ptr = nullptr};
+ };
+
+ const auto& info = it->second;
+ return {.deviceMemory = vkDeviceMem, .ptr = info.ptr};
+ }
+ };
+ }
+ return nullptr;
+ }
+
+ CommandBufferStagingStream::Free getFree() {
+ if (mFeatureInfo->hasVulkanAuxCommandMemory) {
+ return [this](const CommandBufferStagingStream::Memory& memory) {
+ // deviceMemory may not be the actual backing auxiliary VkDeviceMemory
+ // for suballocations, deviceMemory is a alias VkDeviceMemory hand;
+ // freeCoherentMemoryLocked maps the alias to the backing VkDeviceMemory
+ VkDeviceMemory deviceMemory = memory.deviceMemory;
+ AutoLock<RecursiveLock> lock(mLock);
+ auto it = info_VkDeviceMemory.find(deviceMemory);
+ if (it == info_VkDeviceMemory.end()) {
+ ALOGE("Device memory to free not found");
+ return;
+ }
+ auto coherentMemory = freeCoherentMemoryLocked(deviceMemory, it->second);
+ // We have to release the lock before we could possibly free a
+ // CoherentMemory, because that will call into VkEncoder, which
+ // shouldn't be called when the lock is held.
+ lock.unlock();
+ coherentMemory = nullptr;
+ };
+ }
+ return nullptr;
+ }
+
VkResult on_vkBeginCommandBuffer(
void* context, VkResult input_result,
VkCommandBuffer commandBuffer,
@@ -7103,7 +7223,8 @@
// Resets staging stream for this command buffer and primary command buffers
// where this command buffer has been recorded. If requested, also clears the pending
// descriptor sets.
- void resetCommandBufferStagingInfo(VkCommandBuffer commandBuffer, bool alsoResetPrimaries, bool alsoClearPendingDescriptorSets) {
+ void resetCommandBufferStagingInfo(VkCommandBuffer commandBuffer, bool alsoResetPrimaries,
+ bool alsoClearPendingDescriptorSets) {
struct goldfish_VkCommandBuffer* cb = as_goldfish_VkCommandBuffer(commandBuffer);
if (!cb) {
return;
@@ -7299,6 +7420,8 @@
struct goldfish_VkCommandBuffer* cb = as_goldfish_VkCommandBuffer(commandBuffer);
if (!cb->privateEncoder) {
+ sStaging.setAllocFree(ResourceTracker::get()->getAlloc(),
+ ResourceTracker::get()->getFree());
sStaging.popStaging((CommandBufferStagingStream**)&cb->privateStream, &cb->privateEncoder);
}
uint8_t* writtenPtr; size_t written;
@@ -8114,6 +8237,9 @@
return mImpl->syncEncodersForQueue(queue, current);
}
+CommandBufferStagingStream::Alloc ResourceTracker::getAlloc() { return mImpl->getAlloc(); }
+
+CommandBufferStagingStream::Free ResourceTracker::getFree() { return mImpl->getFree(); }
VkResult ResourceTracker::on_vkBeginCommandBuffer(
void* context, VkResult input_result,
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index 391eac5..2cb5b2a 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -14,15 +14,15 @@
// limitations under the License.
#pragma once
-#include "aemu/base/Tracing.h"
-
#include <vulkan/vulkan.h>
-#include "VulkanHandleMapping.h"
-#include "VulkanHandles.h"
#include <functional>
#include <memory>
+#include "CommandBufferStagingStream.h"
+#include "VulkanHandleMapping.h"
+#include "VulkanHandles.h"
+#include "aemu/base/Tracing.h"
#include "goldfish_vk_transform_guest.h"
struct EmulatorFeatureInfo;
@@ -528,6 +528,9 @@
uint32_t syncEncodersForCommandBuffer(VkCommandBuffer commandBuffer, VkEncoder* current);
uint32_t syncEncodersForQueue(VkQueue queue, VkEncoder* current);
+ CommandBufferStagingStream::Alloc getAlloc();
+ CommandBufferStagingStream::Free getFree();
+
VkResult on_vkBeginCommandBuffer(
void* context, VkResult input_result,
VkCommandBuffer commandBuffer,
diff --git a/system/vulkan_enc_unit_tests/Android.mk b/system/vulkan_enc_unit_tests/Android.mk
index 162c95d..e506bc9 100644
--- a/system/vulkan_enc_unit_tests/Android.mk
+++ b/system/vulkan_enc_unit_tests/Android.mk
@@ -6,7 +6,7 @@
LOCAL_C_INCLUDES += \
device/generic/goldfish-opengl/host/include/libOpenglRender \
-
+ external/gfxstream-protocols/include/vulkan/include/
LOCAL_SRC_FILES:= \
CommandBufferStagingStream_test.cpp \
diff --git a/system/vulkan_enc_unit_tests/CommandBufferStagingStream_test.cpp b/system/vulkan_enc_unit_tests/CommandBufferStagingStream_test.cpp
index b1df082..375bc6e 100644
--- a/system/vulkan_enc_unit_tests/CommandBufferStagingStream_test.cpp
+++ b/system/vulkan_enc_unit_tests/CommandBufferStagingStream_test.cpp
@@ -201,30 +201,38 @@
<< "commitBufferAndReadFully should not be supported";
}
-// CommandBufferStagingStreamCustomAllocationTest tests tests behavior of CommandBufferStagingStream
+using MockAlloc = MockFunction<CommandBufferStagingStream::Memory(size_t)>;
+using MockFree = MockFunction<void(const CommandBufferStagingStream::Memory&)>;
+// default empty implementation of free
+static std::function<void(const CommandBufferStagingStream::Memory&)> EmptyFree =
+ [](const CommandBufferStagingStream::Memory&) {};
+// CommandBufferStagingStreamCustomAllocationTest tests behavior of CommandBufferStagingStream
// when initialized with custom allocator/free function.
// These tests test the same outcome as CommandBufferStagingStreamTest tests
// tests allocBuffer can successfully allocate a buffer of given size
-
TEST(CommandBufferStagingStreamCustomAllocationTest, AllocateBufferTest) {
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
- MockFunction<void*(size_t)> allocFn;
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+
+ MockAlloc allocFn;
// alloc function should be called once
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
// free function should be called once
- MockFunction<void(void*)> freeFn;
- EXPECT_CALL(freeFn, Call(Eq(static_cast<void*>(memorySrc.data())))).Times(1);
+ MockFree freeFn;
+ EXPECT_CALL(freeFn, Call(Eq(memory))).Times(1);
// scope: CommandBufferStagingStream_Creation
{
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), freeFn.AsStdFunction());
+ auto allocStdFn = allocFn.AsStdFunction();
+ auto freeStdFn = freeFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, freeStdFn);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
EXPECT_THAT(buffer, NotNull());
}
@@ -235,24 +243,84 @@
// memory source for initial allocation
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
- MockFunction<void*(size_t)> allocFn;
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = nullptr, // to test alloc call failing
+ };
+
+ MockAlloc allocFn;
// alloc function should be called once
- // return nullptr to test alloc call failing
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(nullptr));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
// free function should not be called if allocation fails
- MockFunction<void(void*)> freeFn;
+ MockFree freeFn;
EXPECT_CALL(freeFn, Call).Times(0);
// scope: CommandBufferStagingStream_Creation
{
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), freeFn.AsStdFunction());
+ auto allocStdFn = allocFn.AsStdFunction();
+ auto freeStdFn = freeFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, freeStdFn);
void* buffer = stream.allocBuffer(kTestBufferSize);
EXPECT_THAT(buffer, IsNull());
}
}
+TEST(CommandBufferStagingStreamCustomAllocationTest, DeviceMemoryPointerIsPassedDuringFree) {
+ // memory source
+ std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
+
+ // device memory for test purposes. The test just needs a pointer
+ uint64_t deviceMem = 0;
+ VkDeviceMemory deviceMemPtr = (VkDeviceMemory)(&deviceMem);
+
+ CommandBufferStagingStream::Memory memory{.deviceMemory = deviceMemPtr,
+ .ptr = memorySrc.data()};
+
+ MockAlloc allocFn;
+
+ // alloc function should be called once
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
+
+ // free function should be called once
+ MockFree freeFn;
+ EXPECT_CALL(freeFn, Call(Eq(memory))).Times(1);
+
+ // scope: CommandBufferStagingStream_Creation
+ {
+ auto allocStdFn = allocFn.AsStdFunction();
+ auto freeStdFn = freeFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, freeStdFn);
+ uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
+ EXPECT_THAT(buffer, NotNull());
+ }
+}
+
+// test verifies that there are no crashes if alloc/free function reference becomes null
+TEST(CommandBufferStagingStreamCustomAllocationTest, AllocFreeInvalidReference) {
+ MockAlloc allocFn;
+ // alloc shouldn't be called if reference is invalidated
+ EXPECT_CALL(allocFn, Call).Times(0);
+
+ MockFree freeFn;
+ // free shouldn't be called if reference is invalidated
+ EXPECT_CALL(freeFn, Call).Times(0);
+
+ auto allocStdFn = allocFn.AsStdFunction();
+ auto freeStdFn = freeFn.AsStdFunction();
+ // scope: CommandBufferStagingStream_Creation
+ {
+ CommandBufferStagingStream stream(allocStdFn, freeStdFn);
+ // invalidate alloc/free functions
+ allocStdFn = nullptr;
+ freeStdFn = nullptr;
+ stream.allocBuffer(kTestBufferSize);
+ uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
+ EXPECT_THAT(buffer, IsNull());
+ }
+}
+
// test reallocate buffer remembers previously committed buffers
TEST(CommandBufferStagingStreamCustomAllocationTest, ReallocateBuffer) {
// memory source for initial allocation
@@ -260,35 +328,43 @@
// memory source after reallocation
std::vector<uint8_t> reallocatedMemorySrc(kTestBufferSize * 3);
- MockFunction<void*(size_t)> allocFn;
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+
+ CommandBufferStagingStream::Memory reallocatedMemory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = reallocatedMemorySrc.data()};
+
+ MockAlloc allocFn;
// alloc function should be called twice
{
InSequence seq;
// expect initial allocation call with allocation size == kTestBufferSize;
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
// expect reallocation call with allocation size > kTestBufferSize.
EXPECT_CALL(allocFn, Call(testing::Ge(kTestBufferSize)))
.Times(1)
- .WillRepeatedly(Return(reallocatedMemorySrc.data()));
+ .WillRepeatedly(Return(reallocatedMemory));
}
- MockFunction<void(void*)> freeFn;
+ MockFree freeFn;
{
InSequence seq;
// free function should be called when reallocation happens
- EXPECT_CALL(freeFn, Call(Eq(memorySrc.data()))).Times(1);
+ EXPECT_CALL(freeFn, Call(Eq(memory))).Times(1);
// free function should be called when stream goes out of scope
- EXPECT_CALL(freeFn, Call(Eq(reallocatedMemorySrc.data()))).Times(1);
+ EXPECT_CALL(freeFn, Call(Eq(reallocatedMemory))).Times(1);
}
// scope: CommandBufferStagingStream_Creation
{
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), freeFn.AsStdFunction());
+ auto allocStdFn = allocFn.AsStdFunction();
+ auto freeStdFn = freeFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, freeStdFn);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
EXPECT_THAT(buffer, NotNull());
@@ -318,14 +394,17 @@
TEST(CommandBufferStagingStreamCustomAllocationTest, CommitBuffer) {
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
- MockFunction<void*(size_t)> allocFn;
+
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+
+ MockAlloc allocFn;
// alloc function should be called once
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
-
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), [](void*) {});
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
EXPECT_THAT(buffer, NotNull());
@@ -351,17 +430,16 @@
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
- MockFunction<void*(size_t)> allocFn;
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+
+ MockAlloc allocFn;
// alloc function should be called once
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
-
- // free function expectation not needed in this test
- MockFunction<void(void*)> freeFn;
-
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), freeFn.AsStdFunction());
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
// write some arbitrary data
@@ -389,18 +467,17 @@
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
- MockFunction<void*(size_t)> allocFn;
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+
+ MockAlloc allocFn;
// alloc function should be called once, no reallocation
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
- // free function expectation not needed in this test
- MockFunction<void(void*)> freeFn;
-
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), freeFn.AsStdFunction());
-
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
EXPECT_THAT(buffer, NotNull());
@@ -413,31 +490,33 @@
TEST(CommandBufferStagingStreamCustomAllocationTest, ReallocationBoundary) {
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 3);
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
- MockFunction<void*(size_t)> allocFn;
+ MockAlloc allocFn;
// alloc function should be called twice
{
InSequence seq;
// expect initial allocation call with allocation size >= kTestBufferSize;
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
// expect reallocation call with allocation size > kTestBufferSize.
EXPECT_CALL(allocFn, Call(testing::Ge(kTestBufferSize)))
.Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ .WillRepeatedly(Return(memory));
}
// free function should be called once during reallocation,
// once when stream goes out of scope
- MockFunction<void(void*)> freeFn;
+ MockFree freeFn;
- EXPECT_CALL(freeFn, Call(Eq(memorySrc.data()))).Times(2);
-
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), freeFn.AsStdFunction());
+ EXPECT_CALL(freeFn, Call(Eq(memory))).Times(2);
+ auto allocStdFn = allocFn.AsStdFunction();
+ auto freeStdFn = freeFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, freeStdFn);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
EXPECT_THAT(buffer, NotNull());
@@ -473,12 +552,15 @@
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 3);
- MockFunction<void*(size_t)> allocFn;
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), [](void*) {});
+ MockAlloc allocFn;
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
+
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
EXPECT_THAT(buffer, NotNull());
@@ -495,30 +577,38 @@
TEST(CommandBufferStagingStreamCustomAllocationTest, MetadataCheck) {
// memory source
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+
// CommandBufferStagingStream allocates metadata when using custom allocators
static const size_t expectedMetadataSize = 8;
- MockFunction<void*(size_t)> allocFn;
+ MockAlloc allocFn;
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), [](void*) {});
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
- EXPECT_THAT(buffer, NotNull());
+ // data should start after metadata
+ EXPECT_THAT(buffer, memorySrc.data() + expectedMetadataSize);
+ // metadata should be initialized to read complete
+ uint32_t* metadataPtr = reinterpret_cast<uint32_t*>(memorySrc.data());
+ EXPECT_THAT(*metadataPtr, CommandBufferStagingStream::kSyncDataReadComplete);
}
-TEST(CommandBufferStagingStreamCustomAllocationTest, MarkFlushingTest) {
+TEST(CommandBufferStagingStreamCustomAllocationTest, MarkFlushing) {
// memory source for allocation
std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+ MockAlloc allocFn;
- MockFunction<void*(size_t)> allocFn;
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
-
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), [](void*) {});
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
// write some data
@@ -536,47 +626,19 @@
EXPECT_EQ(*readPtr, CommandBufferStagingStream::kSyncDataReadPending);
}
-TEST(CommandBufferStagingStreamCustomAllocationTest, MarkFlushing) {
- // memory source for allocation
- std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
-
- MockFunction<void*(size_t)> allocFn;
-
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
-
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), [](void*) {});
- uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
-
- // write some data
- const std::string_view commandData{"some command"};
- const size_t dataSize = commandData.size();
- memcpy(buffer, commandData.data(), dataSize);
-
- // commit data
- stream.commitBuffer(dataSize);
-
- // will set metadata of the stream buffer to pending read
- stream.markFlushing();
-
- uint32_t* readPtr = reinterpret_cast<uint32_t*>(memorySrc.data());
- EXPECT_EQ(*readPtr, 0x01);
-}
-
// this test verifies that realloc waits till consumer of memory has completed read
TEST(CommandBufferStagingStreamCustomAllocationTest, ReallocNotCalledTillBufferIsRead) {
// memory source for allocation
// allocate a big enough buffer to avoid resizes in test
std::vector<uint8_t> memorySrc(kTestBufferSize * 3);
- auto ptr = memorySrc.data();
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
std::condition_variable memoryFlushedCondition;
std::mutex mutex;
- // track the number of times allocFn is called
-
- MockFunction<void*(size_t)> allocFn;
+ MockAlloc allocFn;
// mock function to notify read is complete
// this will be used to set up the expectation that realloc should
@@ -589,7 +651,8 @@
std::unique_lock readLock(mutex);
memoryFlushedCondition.wait(readLock, [&]() {
// wait till memorySrc is ready for read
- return *ptr == CommandBufferStagingStream::kSyncDataReadPending;
+ uint32_t* syncData = static_cast<uint32_t*>(memory.ptr);
+ return *syncData = CommandBufferStagingStream::kSyncDataReadPending;
});
readLock.unlock();
@@ -601,14 +664,12 @@
fn();
});
- CommandBufferStagingStream stream(allocFn.AsStdFunction(), [](void*) {});
- // scope for writeLock
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree); // scope for writeLock
{
std::lock_guard writeLock(mutex);
- EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize)))
- .Times(1)
- .WillRepeatedly(Return(memorySrc.data()));
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
uint8_t* buffer = static_cast<uint8_t*>(stream.allocBuffer(kTestBufferSize));
@@ -630,11 +691,34 @@
EXPECT_CALL(allocFn, Call(testing::Ge(kTestBufferSize)))
.Times(1)
.After(readCompleteExpectation)
- .WillRepeatedly(Return(memorySrc.data()));
+ .WillRepeatedly(Return(memory));
// realloc will be blocked till buffer read is complete by reader
(void)stream.allocBuffer(kTestBufferSize);
// wait for read thread to finish
consumer.join();
+}
+
+// this test verifies that allocBuffer() cannot be called on a stream
+// that is currently being read by the host
+TEST(CommandBufferStagingStreamCustomAllocationTest, AllocBufferFailsIfReadPending) {
+ // memory source for allocation
+ std::vector<uint8_t> memorySrc(kTestBufferSize * 2);
+ CommandBufferStagingStream::Memory memory{
+ .deviceMemory = VK_NULL_HANDLE, // not needed for this test
+ .ptr = memorySrc.data()};
+ MockAlloc allocFn;
+
+ EXPECT_CALL(allocFn, Call(Ge(kTestBufferSize))).Times(1).WillRepeatedly(Return(memory));
+
+ auto allocStdFn = allocFn.AsStdFunction();
+ CommandBufferStagingStream stream(allocStdFn, EmptyFree);
+ (void)stream.allocBuffer(kTestBufferSize);
+
+ // will set metadata of the stream buffer to pending read
+ stream.markFlushing();
+
+ EXPECT_DEATH({ (void)stream.allocBuffer(kTestBufferSize); }, "")
+ << "allocBuffer() should not be called while previous data is being flushed";
}
\ No newline at end of file