summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 04:48:11 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 04:48:11 +0000
commit4ed265b9b37c13d1cd340a5a840e45192132480d (patch)
tree972235c555b82d23bd826a02d64e821352248e4d
parent4dd56658620004986d78f6ba0fabff517f956c6e (diff)
parent48b1ff4a7f7c1b3fade987ac1c303c9724adf0f7 (diff)
downloadcommon-4ed265b9b37c13d1cd340a5a840e45192132480d.tar.gz
Snap for 10453563 from 48b1ff4a7f7c1b3fade987ac1c303c9724adf0f7 to mainline-adservices-releaseaml_ads_340915050
Change-Id: I4c6538776aec2b730cacd4018c03d70e45d0d5ff
-rw-r--r--BoardConfigCFlags.mk8
-rw-r--r--hwc3/Android.mk7
-rw-r--r--hwc3/ComposerClient.cpp154
-rw-r--r--hwc3/ComposerClient.h9
-rw-r--r--hwc3/ComposerCommandEngine.cpp21
-rw-r--r--hwc3/ComposerCommandEngine.h2
-rw-r--r--hwc3/Util.h39
-rw-r--r--hwc3/hwc3-default.xml2
-rw-r--r--hwc3/impl/HalImpl.cpp46
-rw-r--r--hwc3/impl/HalImpl.h6
-rw-r--r--hwc3/include/IComposerHal.h14
-rw-r--r--include/displaycolor/displaycolor.h57
-rw-r--r--libacryl/Android.mk3
-rw-r--r--libacryl/acrylic_factory.cpp173
-rw-r--r--libacryl/acrylic_formats.cpp2
-rw-r--r--libacryl/acrylic_g2d.cpp1
-rw-r--r--libacryl/acrylic_g2d.h7
-rw-r--r--libacryl/acrylic_layer.cpp7
-rw-r--r--libacryl/hdrplugin_headers/hardware/exynos/g2d_hdr_plugin.h1
-rw-r--r--libhwc2.1/Android.mk33
-rw-r--r--libhwc2.1/ExynosHWC.cpp31
-rw-r--r--libhwc2.1/ExynosHWC.h3
-rw-r--r--libhwc2.1/ExynosHWCDebug.cpp77
-rw-r--r--libhwc2.1/ExynosHWCDebug.h45
-rw-r--r--libhwc2.1/histogram_mediator.cpp134
-rw-r--r--libhwc2.1/histogram_mediator.h118
-rw-r--r--libhwc2.1/libdevice/BrightnessController.cpp292
-rw-r--r--libhwc2.1/libdevice/BrightnessController.h106
-rw-r--r--libhwc2.1/libdevice/DisplayColorLoader.h100
-rw-r--r--libhwc2.1/libdevice/ExynosDevice.cpp380
-rw-r--r--libhwc2.1/libdevice/ExynosDevice.h45
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.cpp664
-rw-r--r--libhwc2.1/libdevice/ExynosDisplay.h211
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.cpp94
-rw-r--r--libhwc2.1/libdevice/ExynosLayer.h37
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp30
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h6
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp4
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h16
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp472
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h91
-rw-r--r--libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h2
-rw-r--r--libhwc2.1/libdrmresource/drm/drmconnector.cpp10
-rw-r--r--libhwc2.1/libdrmresource/drm/drmcrtc.cpp15
-rw-r--r--libhwc2.1/libdrmresource/drm/drmeventlistener.cpp73
-rw-r--r--libhwc2.1/libdrmresource/drm/vsyncworker.cpp14
-rw-r--r--libhwc2.1/libdrmresource/include/drmconnector.h2
-rw-r--r--libhwc2.1/libdrmresource/include/drmcrtc.h6
-rw-r--r--libhwc2.1/libdrmresource/include/drmeventlistener.h32
-rw-r--r--libhwc2.1/libdrmresource/include/vsyncworker.h16
-rw-r--r--libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp22
-rw-r--r--libhwc2.1/libexternaldisplay/ExynosExternalDisplay.h2
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.cpp80
-rw-r--r--libhwc2.1/libhwcService/ExynosHWCService.h14
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.cpp128
-rw-r--r--libhwc2.1/libhwcService/IExynosHWC.h9
-rw-r--r--libhwc2.1/libhwchelper/ExynosHWCHelper.cpp58
-rw-r--r--libhwc2.1/libhwchelper/ExynosHWCHelper.h60
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp536
-rw-r--r--libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h47
-rw-r--r--libhwc2.1/libresource/ExynosMPP.cpp119
-rw-r--r--libhwc2.1/libresource/ExynosMPP.h59
-rw-r--r--libhwc2.1/libresource/ExynosMPPType.h53
-rw-r--r--libhwc2.1/libresource/ExynosResourceManager.cpp483
-rw-r--r--libhwc2.1/libresource/ExynosResourceManager.h51
-rw-r--r--libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp11
-rw-r--r--libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h2
-rw-r--r--libhwc2.1/pixel-display-default.xml2
-rw-r--r--libhwc2.1/pixel-display-secondary.xml7
-rw-r--r--libhwc2.1/pixel-display.cpp195
-rw-r--r--libhwc2.1/pixel-display.h23
-rw-r--r--libhwjpeg/Android.bp4
-rw-r--r--libhwjpeg/AppMarkerWriter.cpp201
-rw-r--r--libhwjpeg/AppMarkerWriter.h28
-rw-r--r--libhwjpeg/ExynosJpegEncoder.cpp119
-rw-r--r--libhwjpeg/ExynosJpegEncoderForCamera.cpp353
-rw-r--r--libhwjpeg/FileLock.cpp13
-rw-r--r--libhwjpeg/IFDWriter.h35
-rw-r--r--libhwjpeg/LibScalerForJpeg.cpp177
-rw-r--r--libhwjpeg/LibScalerForJpeg.h40
-rw-r--r--libhwjpeg/ThumbnailScaler.cpp6
-rw-r--r--libhwjpeg/ThumbnailScaler.h10
-rw-r--r--libhwjpeg/hwjpeg-base.cpp70
-rw-r--r--libhwjpeg/hwjpeg-internal.h30
-rw-r--r--libhwjpeg/hwjpeg-v4l2.cpp316
-rw-r--r--libhwjpeg/include/ExynosJpegApi.h40
-rw-r--r--libhwjpeg/include/ExynosJpegEncoderForCamera.h36
-rw-r--r--libhwjpeg/include/FileLock.h16
-rw-r--r--libhwjpeg/include/exynos-hwjpeg.h184
-rw-r--r--libhwjpeg/include/hwjpeglib-exynos.h34
-rw-r--r--libhwjpeg/libhwjpeg-exynos.cpp146
-rw-r--r--libion/ion.cpp9
-rw-r--r--libion/test/Android.bp9
93 files changed, 5036 insertions, 2519 deletions
diff --git a/BoardConfigCFlags.mk b/BoardConfigCFlags.mk
index 7c2f423..679f44f 100644
--- a/BoardConfigCFlags.mk
+++ b/BoardConfigCFlags.mk
@@ -9,8 +9,8 @@ endif
LOCAL_CFLAGS += -DUSES_GSCALER
-ifeq ($(HWC_SKIP_VALIDATE),true)
- LOCAL_CFLAGS += -DHWC_SKIP_VALIDATE
+ifeq ($(HWC_NO_SUPPORT_SKIP_VALIDATE),true)
+ LOCAL_CFLAGS += -DHWC_NO_SUPPORT_SKIP_VALIDATE
endif
ifeq ($(HWC_SUPPORT_COLOR_TRANSFORM), true)
@@ -40,3 +40,7 @@ endif
ifeq ($(BOARD_USES_HDRUI_GLES_CONVERSION), true)
LOCAL_CFLAGS += -DUSES_HDR_GLES_CONVERSION
endif
+
+ifeq ($(USES_IDISPLAY_INTF_SEC),true)
+ LOCAL_CFLAGS += -DUSES_IDISPLAY_INTF_SEC
+endif
diff --git a/hwc3/Android.mk b/hwc3/Android.mk
index f233aab..28ed88d 100644
--- a/hwc3/Android.mk
+++ b/hwc3/Android.mk
@@ -28,14 +28,14 @@ LOCAL_PROPRIETARY_MODULE := true
LOCAL_CFLAGS += \
-DSOC_VERSION=$(soc_ver) \
- -DLOG_TAG=\"hwc3\"
+ -DLOG_TAG=\"hwc-3\"
# hwc3 re-uses hwc2.2 ComposerResource and libexynosdisplay
-LOCAL_SHARED_LIBRARIES := android.hardware.graphics.composer3-V1-ndk \
+LOCAL_SHARED_LIBRARIES := android.hardware.graphics.composer3-V2-ndk \
android.hardware.graphics.composer@2.1-resources \
android.hardware.graphics.composer@2.2-resources \
android.hardware.graphics.composer@2.4 \
- com.google.hardware.pixel.display-V6-ndk \
+ com.google.hardware.pixel.display-V8-ndk \
libbase \
libbinder \
libbinder_ndk \
@@ -66,6 +66,7 @@ LOCAL_C_INCLUDES := \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libresource \
$(TOP)/hardware/google/graphics/$(soc_ver)/include \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1 \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libcolormanager \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libmaindisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp
index b576b68..c34b13a 100644
--- a/hwc3/ComposerClient.cpp
+++ b/hwc3/ComposerClient.cpp
@@ -33,25 +33,11 @@ bool ComposerClient::init() {
return false;
}
- mCommandEngine = std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
- if (mCommandEngine == nullptr) {
- return false;
- }
- if (!mCommandEngine->init()) {
- mCommandEngine = nullptr;
- return false;
- }
-
return true;
}
ComposerClient::~ComposerClient() {
DEBUG_FUNC();
- // not initialized
- if (!mCommandEngine) {
- return;
- }
-
LOG(DEBUG) << "destroying composer client";
mHal->unregisterEventCallback();
@@ -67,7 +53,7 @@ ComposerClient::~ComposerClient() {
// no need to check nullptr for output parameter, the aidl stub code won't pass nullptr
ndk::ScopedAStatus ComposerClient::createLayer(int64_t display, int32_t bufferSlotCount,
int64_t* layer) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->createLayer(display, layer);
if (!err) {
err = mResources->addLayer(display, *layer, bufferSlotCount);
@@ -91,7 +77,7 @@ ndk::ScopedAStatus ComposerClient::createVirtualDisplay(int32_t width, int32_t h
}
ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display, int64_t layer) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->destroyLayer(display, layer);
if (!err) {
err = mResources->removeLayer(display, layer);
@@ -100,7 +86,7 @@ ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display, int64_t layer)
}
ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->destroyVirtualDisplay(display);
if (!err) {
err = mResources->removeDisplay(display);
@@ -110,20 +96,33 @@ ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display) {
ndk::ScopedAStatus ComposerClient::executeCommands(const std::vector<DisplayCommand>& commands,
std::vector<CommandResultPayload>* results) {
- DEBUG_FUNC();
- auto err = mCommandEngine->execute(commands, results);
+ int64_t display = commands.empty() ? -1 : commands[0].display;
+ DEBUG_DISPLAY_FUNC(display);
+ ComposerCommandEngine engine(mHal, mResources.get());
+
+ auto err = engine.init();
+ if (err != ::android::NO_ERROR) {
+ LOG(ERROR) << "executeCommands(): init ComposerCommandEngine failed " << err;
+ return TO_BINDER_STATUS(err);
+ }
+
+ err = engine.execute(commands, results);
+ if (err != ::android::NO_ERROR) {
+ LOG(ERROR) << "executeCommands(): execute failed " << err;
+ return TO_BINDER_STATUS(err);
+ }
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t display, int32_t* config) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getActiveConfig(display, config);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getColorModes(int64_t display,
std::vector<ColorMode>* colorModes) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getColorModes(display, colorModes);
return TO_BINDER_STATUS(err);
}
@@ -149,14 +148,14 @@ ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(common::Dataspac
ndk::ScopedAStatus ComposerClient::getDisplayAttribute(int64_t display, int32_t config,
DisplayAttribute attribute, int32_t* value) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayAttribute(display, config, attribute, value);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(int64_t display,
std::vector<DisplayCapability>* caps) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayCapabilities(display, caps);
if (err) {
return TO_BINDER_STATUS(err);
@@ -177,33 +176,33 @@ ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(int64_t display,
ndk::ScopedAStatus ComposerClient::getDisplayConfigs(int64_t display,
std::vector<int32_t>* configs) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayConfigs(display, configs);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(int64_t display,
DisplayConnectionType* type) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayConnectionType(display, type);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(int64_t display,
DisplayIdentification* id) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayIdentificationData(display, id);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t display, std::string* name) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayName(display, name);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(int64_t display, int32_t* vsyncPeriod) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayVsyncPeriod(display, vsyncPeriod);
return TO_BINDER_STATUS(err);
}
@@ -211,31 +210,37 @@ ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(int64_t display, int32_
ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(int64_t display, int64_t maxFrames,
int64_t timestamp,
DisplayContentSample* samples) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayedContentSample(display, maxFrames, timestamp, samples);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
int64_t display, DisplayContentSamplingAttributes* attrs) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayedContentSamplingAttributes(display, attrs);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(int64_t display,
common::Transform* orientation) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getDisplayPhysicalOrientation(display, orientation);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display, HdrCapabilities* caps) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getHdrCapabilities(display, caps);
return TO_BINDER_STATUS(err);
}
+ndk::ScopedAStatus ComposerClient::getOverlaySupport(OverlayProperties* caps) {
+ DEBUG_FUNC();
+ auto err = mHal->getOverlaySupport(caps);
+ return TO_BINDER_STATUS(err);
+}
+
ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) {
DEBUG_FUNC();
auto err = mHal->getMaxVirtualDisplayCount(count);
@@ -244,42 +249,42 @@ ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) {
ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(int64_t display,
std::vector<PerFrameMetadataKey>* keys) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getPerFrameMetadataKeys(display, keys);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(int64_t display,
ReadbackBufferAttributes* attrs) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getReadbackBufferAttributes(display, attrs);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(int64_t display,
ndk::ScopedFileDescriptor* acquireFence) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getReadbackBufferFence(display, acquireFence);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getRenderIntents(int64_t display, ColorMode mode,
std::vector<RenderIntent>* intents) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getRenderIntents(display, mode, intents);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(int64_t display,
std::vector<ContentType>* types) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getSupportedContentTypes(display, types);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
int64_t display, std::optional<common::DisplayDecorationSupport>* supportStruct) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
bool support = false;
auto err = mHal->getRCDLayerSupport(display, support);
if (err != ::android::OK) {
@@ -306,7 +311,7 @@ ndk::ScopedAStatus ComposerClient::registerCallback(
}
ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display, int32_t config) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setActiveConfig(display, config);
return TO_BINDER_STATUS(err);
}
@@ -314,63 +319,78 @@ ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display, int32_t conf
ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
int64_t display, int32_t config, const VsyncPeriodChangeConstraints& constraints,
VsyncPeriodChangeTimeline* timeline) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setActiveConfigWithConstraints(display, config, constraints, timeline);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t display, int32_t config) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setBootDisplayConfig(display, config);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(int64_t display) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->clearBootDisplayConfig(display);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(int64_t display, int32_t* config) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->getPreferredBootDisplayConfig(display, config);
return TO_BINDER_STATUS(err);
}
-ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display, bool on) {
+ndk::ScopedAStatus ComposerClient::getHdrConversionCapabilities(
+ std::vector<common::HdrConversionCapability>* hdrConversionCapabilities) {
DEBUG_FUNC();
+ auto err = mHal->getHdrConversionCapabilities(hdrConversionCapabilities);
+ return TO_BINDER_STATUS(err);
+}
+
+ndk::ScopedAStatus ComposerClient::setHdrConversionStrategy(
+ const common::HdrConversionStrategy& hdrConversionStrategy,
+ common::Hdr* preferredHdrOutputType) {
+ DEBUG_FUNC();
+ auto err = mHal->setHdrConversionStrategy(hdrConversionStrategy, preferredHdrOutputType);
+ return TO_BINDER_STATUS(err);
+}
+
+ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display, bool on) {
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setAutoLowLatencyMode(display, on);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t display, int32_t count) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mResources->setDisplayClientTargetCacheSize(display, count);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setColorMode(int64_t display, ColorMode mode,
RenderIntent intent) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setColorMode(display, mode, intent);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setContentType(int64_t display, ContentType type) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setContentType(display, type);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
int64_t display, bool enable, FormatColorComponent componentMask, int64_t maxFrames) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setDisplayedContentSamplingEnabled(display, enable, componentMask, maxFrames);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display, PowerMode mode) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setPowerMode(display, mode);
return TO_BINDER_STATUS(err);
}
@@ -378,7 +398,7 @@ ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display, PowerMode mode)
ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
int64_t display, const AidlNativeHandle& aidlBuffer,
const ndk::ScopedFileDescriptor& releaseFence) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
buffer_handle_t readbackBuffer;
// Note ownership of the buffer is not passed to resource manager.
buffer_handle_t buffer = ::android::makeFromAidl(aidlBuffer);
@@ -392,19 +412,35 @@ ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
}
ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t display, bool enabled) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setVsyncEnabled(display, enabled);
return TO_BINDER_STATUS(err);
}
ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t display, int32_t timeout) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto err = mHal->setIdleTimerEnabled(display, timeout);
return TO_BINDER_STATUS(err);
}
+ndk::ScopedAStatus ComposerClient::setRefreshRateChangedCallbackDebugEnabled(int64_t display,
+ bool enabled) {
+ DEBUG_DISPLAY_FUNC(display);
+ auto err = mHal->setRefreshRateChangedCallbackDebugEnabled(display, enabled);
+ return TO_BINDER_STATUS(err);
+}
+
+void ComposerClient::HalEventCallback::onRefreshRateChangedDebug(
+ const RefreshRateChangedDebugData& data) {
+ DEBUG_DISPLAY_FUNC(data.display);
+ auto ret = mCallback->onRefreshRateChangedDebug(data);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "failed to send onRefreshRateChangedDebug:" << ret.getDescription();
+ }
+}
+
void ComposerClient::HalEventCallback::onHotplug(int64_t display, bool connected) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
if (connected) {
if (mResources->hasDisplay(display)) {
// This is a subsequent hotplug "connected" for a display. This signals a
@@ -426,7 +462,7 @@ void ComposerClient::HalEventCallback::onHotplug(int64_t display, bool connected
}
void ComposerClient::HalEventCallback::onRefresh(int64_t display) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
mResources->setDisplayMustValidateState(display, true);
auto ret = mCallback->onRefresh(display);
if (!ret.isOk()) {
@@ -436,7 +472,7 @@ void ComposerClient::HalEventCallback::onRefresh(int64_t display) {
void ComposerClient::HalEventCallback::onVsync(int64_t display, int64_t timestamp,
int32_t vsyncPeriodNanos) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto ret = mCallback->onVsync(display, timestamp, vsyncPeriodNanos);
if (!ret.isOk()) {
LOG(ERROR) << "failed to send onVsync:" << ret.getDescription();
@@ -445,7 +481,7 @@ void ComposerClient::HalEventCallback::onVsync(int64_t display, int64_t timestam
void ComposerClient::HalEventCallback::onVsyncPeriodTimingChanged(
int64_t display, const VsyncPeriodChangeTimeline& timeline) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto ret = mCallback->onVsyncPeriodTimingChanged(display, timeline);
if (!ret.isOk()) {
LOG(ERROR) << "failed to send onVsyncPeriodTimingChanged:" << ret.getDescription();
@@ -453,7 +489,7 @@ void ComposerClient::HalEventCallback::onVsyncPeriodTimingChanged(
}
void ComposerClient::HalEventCallback::onVsyncIdle(int64_t display) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto ret = mCallback->onVsyncIdle(display);
if (!ret.isOk()) {
LOG(ERROR) << "failed to send onVsyncIdle:" << ret.getDescription();
@@ -461,7 +497,7 @@ void ComposerClient::HalEventCallback::onVsyncIdle(int64_t display) {
}
void ComposerClient::HalEventCallback::onSeamlessPossible(int64_t display) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
auto ret = mCallback->onSeamlessPossible(display);
if (!ret.isOk()) {
LOG(ERROR) << "failed to send onSealmessPossible:" << ret.getDescription();
@@ -469,7 +505,7 @@ void ComposerClient::HalEventCallback::onSeamlessPossible(int64_t display) {
}
void ComposerClient::HalEventCallback::cleanDisplayResources(int64_t display) {
- DEBUG_FUNC();
+ DEBUG_DISPLAY_FUNC(display);
size_t cacheSize;
auto err = mResources->getDisplayClientTargetCacheSize(display, &cacheSize);
if (!err) {
diff --git a/hwc3/ComposerClient.h b/hwc3/ComposerClient.h
index 855fb8b..7a76fa4 100644
--- a/hwc3/ComposerClient.h
+++ b/hwc3/ComposerClient.h
@@ -49,6 +49,7 @@ public:
const VsyncPeriodChangeTimeline& timeline) override;
void onVsyncIdle(int64_t display) override;
void onSeamlessPossible(int64_t display) override;
+ void onRefreshRateChangedDebug(const RefreshRateChangedDebugData& data) override;
private:
void cleanDisplayResources(int64_t display);
@@ -92,6 +93,7 @@ public:
ndk::ScopedAStatus getDisplayPhysicalOrientation(int64_t display,
common::Transform* orientation) override;
ndk::ScopedAStatus getHdrCapabilities(int64_t display, HdrCapabilities* caps) override;
+ ndk::ScopedAStatus getOverlaySupport(OverlayProperties* caps) override;
ndk::ScopedAStatus getMaxVirtualDisplayCount(int32_t* count) override;
ndk::ScopedAStatus getPerFrameMetadataKeys(int64_t display,
std::vector<PerFrameMetadataKey>* keys) override;
@@ -114,6 +116,10 @@ public:
ndk::ScopedAStatus setBootDisplayConfig(int64_t display, int32_t config) override;
ndk::ScopedAStatus clearBootDisplayConfig(int64_t display) override;
ndk::ScopedAStatus getPreferredBootDisplayConfig(int64_t display, int32_t* config) override;
+ ndk::ScopedAStatus getHdrConversionCapabilities(
+ std::vector<common::HdrConversionCapability>*) override;
+ ndk::ScopedAStatus setHdrConversionStrategy(const common::HdrConversionStrategy&,
+ common::Hdr* preferredHdrOutputType) override;
ndk::ScopedAStatus setAutoLowLatencyMode(int64_t display, bool on) override;
ndk::ScopedAStatus setClientTargetSlotCount(int64_t display, int32_t count) override;
ndk::ScopedAStatus setColorMode(int64_t display, ColorMode mode, RenderIntent intent) override;
@@ -126,6 +132,8 @@ public:
const ndk::ScopedFileDescriptor& releaseFence) override;
ndk::ScopedAStatus setVsyncEnabled(int64_t display, bool enabled) override;
ndk::ScopedAStatus setIdleTimerEnabled(int64_t display, int32_t timeout) override;
+ ndk::ScopedAStatus setRefreshRateChangedCallbackDebugEnabled(int64_t /* display */,
+ bool /* enabled */) override;
protected:
::ndk::SpAIBinder createBinder() override;
@@ -135,7 +143,6 @@ private:
IComposerHal* mHal;
std::unique_ptr<IResourceManager> mResources;
- std::unique_ptr<ComposerCommandEngine> mCommandEngine;
std::function<void()> mOnClientDestroyed;
std::unique_ptr<HalEventCallback> mHalEventCallback;
};
diff --git a/hwc3/ComposerCommandEngine.cpp b/hwc3/ComposerCommandEngine.cpp
index ff66f9d..8b0f005 100644
--- a/hwc3/ComposerCommandEngine.cpp
+++ b/hwc3/ComposerCommandEngine.cpp
@@ -55,9 +55,9 @@ namespace aidl::android::hardware::graphics::composer3::impl {
} \
} while (0)
-bool ComposerCommandEngine::init() {
+int32_t ComposerCommandEngine::init() {
mWriter = std::make_unique<ComposerServiceWriter>();
- return (mWriter != nullptr);
+ return (mWriter != nullptr) ? ::android::NO_ERROR : ::android::NO_MEMORY;
}
int32_t ComposerCommandEngine::execute(const std::vector<DisplayCommand>& commands,
@@ -232,15 +232,12 @@ void ComposerCommandEngine::executeSetDisplayBrightness(uint64_t display,
void ComposerCommandEngine::executePresentOrValidateDisplay(
int64_t display, const std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
executeSetExpectedPresentTimeInternal(display, expectedPresentTime);
-
- int err;
// First try to Present as is.
- if (mHal->hasCapability(Capability::SKIP_VALIDATE)) {
- err = executePresentDisplay(display);
- if (!err) {
- mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
- return;
- }
+ auto err = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED
+ : executePresentDisplay(display);
+ if (!err) {
+ mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented);
+ return;
}
// Fallback to validate
@@ -262,9 +259,7 @@ int ComposerCommandEngine::executePresentDisplay(int64_t display) {
ndk::ScopedFileDescriptor presentFence;
std::vector<int64_t> layers;
std::vector<ndk::ScopedFileDescriptor> fences;
- auto err = mResources->mustValidateDisplay(display)
- ? IComposerClient::EX_NOT_VALIDATED
- : mHal->presentDisplay(display, presentFence, &layers, &fences);
+ auto err = mHal->presentDisplay(display, presentFence, &layers, &fences);
if (!err) {
mWriter->setPresentFence(display, std::move(presentFence));
mWriter->setReleaseFences(display, layers, std::move(fences));
diff --git a/hwc3/ComposerCommandEngine.h b/hwc3/ComposerCommandEngine.h
index ae68285..872c7e5 100644
--- a/hwc3/ComposerCommandEngine.h
+++ b/hwc3/ComposerCommandEngine.h
@@ -30,7 +30,7 @@ class ComposerCommandEngine {
public:
ComposerCommandEngine(IComposerHal* hal, IResourceManager* resources)
: mHal(hal), mResources(resources) {}
- bool init();
+ int32_t init();
int32_t execute(const std::vector<DisplayCommand>& commands,
std::vector<CommandResultPayload>* result);
diff --git a/hwc3/Util.h b/hwc3/Util.h
index 5305787..92a8a71 100644
--- a/hwc3/Util.h
+++ b/hwc3/Util.h
@@ -28,14 +28,26 @@
FullMethodName{ __PRETTY_FUNCTION__ }; \
constexpr static const char *__kFullName__ = __kFullNameObj__.get(); \
ATRACE_NAME(__kFullName__)
+
+#define DEBUG_DISPLAY_FUNC(display) \
+ constexpr static FullMethodName __kFullNameObj__{__PRETTY_FUNCTION__}; \
+ constexpr static const char *__kFullName__ = __kFullNameObj__.get(); \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) { \
+ ::android::String8 _traceName_; \
+ _traceName_.appendFormat("%s(display=%" PRId64 ",..)", __kFullName__, display); \
+ ATRACE_BEGIN(_traceName_.string()); \
+ } \
+ ScopedTraceEnder _traceEnder_
#else
#ifdef LOG_FUNC
-#define DEBUG_FUNC() DebugFunction _dbgFnObj_(__func__)
+#define DEBUG_DISPLAY_FUNC(display) DebugFunction _dbgFnObj_(__func__, display)
#else
-#define DEBUG_FUNC()
+#define DEBUG_DISPLAY_FUNC(display)
#endif
+#define DEBUG_FUNC() DEBUG_DISPLAY_FUNC(std::nullopt)
+
#endif
#define RET_IF_ERR(expr) \
@@ -51,14 +63,33 @@
namespace aidl::android::hardware::graphics::composer3::impl {
+class ScopedTraceEnder {
+public:
+ ~ScopedTraceEnder() { ATRACE_END(); }
+};
+
class DebugFunction {
public:
- DebugFunction(const char* name) : mName(name) { LOG(INFO) << mName << " Enter"; }
+ DebugFunction(const char *name, std::optional<int64_t> display)
+ : mName(name), mDisplay(display) {
+ if (mDisplay) {
+ LOG(INFO) << mName << "(display=" << *mDisplay << ",..) Enter";
+ } else {
+ LOG(INFO) << mName << " Enter";
+ }
+ }
- ~DebugFunction() { LOG(INFO) << mName << " Exit"; }
+ ~DebugFunction() {
+ if (mDisplay) {
+ LOG(INFO) << mName << "(display=" << *mDisplay << ",..) Exit";
+ } else {
+ LOG(INFO) << mName << " Exit";
+ }
+ }
private:
const char* mName;
+ std::optional<int64_t> mDisplay;
};
class FullMethodName {
diff --git a/hwc3/hwc3-default.xml b/hwc3/hwc3-default.xml
index 05a7c09..fd9e638 100644
--- a/hwc3/hwc3-default.xml
+++ b/hwc3/hwc3-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.graphics.composer3</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IComposer</name>
<instance>default</instance>
diff --git a/hwc3/impl/HalImpl.cpp b/hwc3/impl/HalImpl.cpp
index c3011f9..e48d390 100644
--- a/hwc3/impl/HalImpl.cpp
+++ b/hwc3/impl/HalImpl.cpp
@@ -99,6 +99,20 @@ void seamlessPossible(hwc2_callback_data_t callbackData, hwc2_display_t hwcDispl
hal->getEventCallback()->onSeamlessPossible(display);
}
+void refreshRateChangedDebug(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
+ hwc2_vsync_period_t hwcVsyncPeriodNanos) {
+ auto hal = static_cast<HalImpl*>(callbackData);
+ int64_t display;
+ int32_t vsyncPeriodNanos;
+
+ h2a::translate(hwcDisplay, display);
+ h2a::translate(hwcVsyncPeriodNanos, vsyncPeriodNanos);
+ hal->getEventCallback()->onRefreshRateChangedDebug(RefreshRateChangedDebugData{
+ .display = display,
+ .vsyncPeriodNanos = vsyncPeriodNanos,
+ });
+}
+
} // nampesapce hook
HalImpl::HalImpl(std::unique_ptr<ExynosDevice> device) : mDevice(std::move(device)) {
@@ -130,6 +144,7 @@ void HalImpl::initCaps() {
}
mCaps.insert(Capability::BOOT_DISPLAY_CONFIG);
+ mCaps.insert(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG);
}
int32_t HalImpl::getHalDisplay(int64_t display, ExynosDisplay*& halDisplay) {
@@ -193,6 +208,9 @@ void HalImpl::registerEventCallback(EventCallback* callback) {
// register HWC3 Callback
mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onVsyncIdle, this,
reinterpret_cast<hwc2_function_pointer_t>(hook::vsyncIdle));
+ mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug, this,
+ reinterpret_cast<hwc2_function_pointer_t>(
+ hook::refreshRateChangedDebug));
}
void HalImpl::unregisterEventCallback() {
@@ -204,6 +222,8 @@ void HalImpl::unregisterEventCallback() {
// unregister HWC3 Callback
mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onVsyncIdle, this, nullptr);
+ mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug, this,
+ nullptr);
mEventCallback = nullptr;
}
@@ -457,6 +477,10 @@ int32_t HalImpl::getHdrCapabilities(int64_t display, HdrCapabilities* caps) {
return HWC2_ERROR_NONE;
}
+int32_t HalImpl::getOverlaySupport(OverlayProperties* caps) {
+ return mDevice->getOverlaySupport(caps);
+}
+
int32_t HalImpl::getMaxVirtualDisplayCount(int32_t* count) {
uint32_t hwcCount = mDevice->getMaxVirtualDisplayCount();
h2a::translate(hwcCount, *count);
@@ -632,6 +656,14 @@ int32_t HalImpl::getPreferredBootDisplayConfig(int64_t display, int32_t* config)
return halDisplay->getPreferredBootDisplayConfig(config);
}
+int32_t HalImpl::getHdrConversionCapabilities(std::vector<common::HdrConversionCapability>*) {
+ return HWC2_ERROR_UNSUPPORTED;
+}
+
+int32_t HalImpl::setHdrConversionStrategy(const common::HdrConversionStrategy&, common::Hdr*) {
+ return HWC2_ERROR_UNSUPPORTED;
+}
+
int32_t HalImpl::setAutoLowLatencyMode(int64_t display, bool on) {
ExynosDisplay* halDisplay;
RET_IF_ERR(getHalDisplay(display, halDisplay));
@@ -1045,4 +1077,18 @@ int32_t HalImpl::getDisplayIdleTimerSupport(int64_t display, bool& outSupport) {
return halDisplay->getDisplayIdleTimerSupport(outSupport);
}
+int32_t HalImpl::getDisplayMultiThreadedPresentSupport(const int64_t& display, bool& outSupport) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ return halDisplay->getDisplayMultiThreadedPresentSupport(outSupport);
+}
+
+int32_t HalImpl::setRefreshRateChangedCallbackDebugEnabled(int64_t display, bool enabled) {
+ ExynosDisplay* halDisplay;
+ RET_IF_ERR(getHalDisplay(display, halDisplay));
+
+ return halDisplay->setRefreshRateChangedCallbackDebugEnabled(enabled);
+}
+
} // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/hwc3/impl/HalImpl.h b/hwc3/impl/HalImpl.h
index f772ca4..9cb8f1d 100644
--- a/hwc3/impl/HalImpl.h
+++ b/hwc3/impl/HalImpl.h
@@ -71,6 +71,7 @@ class HalImpl : public IComposerHal {
int32_t getDisplayPhysicalOrientation(int64_t display, common::Transform* orientation) override;
int32_t getDozeSupport(int64_t display, bool& outSupport) override;
int32_t getHdrCapabilities(int64_t display, HdrCapabilities* caps) override;
+ int32_t getOverlaySupport(OverlayProperties* caps) override;
int32_t getMaxVirtualDisplayCount(int32_t* count) override;
int32_t getPerFrameMetadataKeys(int64_t display,
std::vector<PerFrameMetadataKey>* keys) override;
@@ -92,6 +93,8 @@ class HalImpl : public IComposerHal {
int32_t setBootDisplayConfig(int64_t display, int32_t config) override;
int32_t clearBootDisplayConfig(int64_t display) override;
int32_t getPreferredBootDisplayConfig(int64_t display, int32_t* config) override;
+ int32_t getHdrConversionCapabilities(std::vector<common::HdrConversionCapability>*) override;
+ int32_t setHdrConversionStrategy(const common::HdrConversionStrategy&, common::Hdr*) override;
int32_t setAutoLowLatencyMode(int64_t display, bool on) override;
int32_t setClientTarget(int64_t display, buffer_handle_t target,
const ndk::ScopedFileDescriptor& fence, common::Dataspace dataspace,
@@ -136,6 +139,8 @@ class HalImpl : public IComposerHal {
const ndk::ScopedFileDescriptor& releaseFence) override;
int32_t setVsyncEnabled(int64_t display, bool enabled) override;
int32_t getDisplayIdleTimerSupport(int64_t display, bool& outSupport) override;
+ int32_t getDisplayMultiThreadedPresentSupport(const int64_t& display,
+ bool& outSupport) override;
int32_t setIdleTimerEnabled(int64_t display, int32_t timeout) override;
int32_t getRCDLayerSupport(int64_t display, bool& outSupport) override;
int32_t setLayerBlockingRegion(
@@ -153,6 +158,7 @@ class HalImpl : public IComposerHal {
const std::optional<ClockMonotonicTimestamp> expectedPresentTime) override;
EventCallback* getEventCallback() { return mEventCallback; }
+ int32_t setRefreshRateChangedCallbackDebugEnabled(int64_t display, bool enabled) override;
private:
void initCaps();
diff --git a/hwc3/include/IComposerHal.h b/hwc3/include/IComposerHal.h
index 6fe25c5..9a9108f 100644
--- a/hwc3/include/IComposerHal.h
+++ b/hwc3/include/IComposerHal.h
@@ -25,6 +25,9 @@
#include <aidl/android/hardware/graphics/common/ColorTransform.h>
#include <aidl/android/hardware/graphics/common/Dataspace.h>
#include <aidl/android/hardware/graphics/common/FRect.h>
+#include <aidl/android/hardware/graphics/common/Hdr.h>
+#include <aidl/android/hardware/graphics/common/HdrConversionCapability.h>
+#include <aidl/android/hardware/graphics/common/HdrConversionStrategy.h>
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <aidl/android/hardware/graphics/common/Point.h>
#include <aidl/android/hardware/graphics/common/Rect.h>
@@ -55,6 +58,7 @@
#include <aidl/android/hardware/graphics/composer3/HdrCapabilities.h>
#include <aidl/android/hardware/graphics/composer3/LayerBrightness.h>
#include <aidl/android/hardware/graphics/composer3/LayerCommand.h>
+#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
#include <aidl/android/hardware/graphics/composer3/ParcelableBlendMode.h>
#include <aidl/android/hardware/graphics/composer3/ParcelableComposition.h>
#include <aidl/android/hardware/graphics/composer3/ParcelableDataspace.h>
@@ -67,6 +71,7 @@
#include <aidl/android/hardware/graphics/composer3/PresentFence.h>
#include <aidl/android/hardware/graphics/composer3/PresentOrValidate.h>
#include <aidl/android/hardware/graphics/composer3/ReadbackBufferAttributes.h>
+#include <aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.h>
#include <aidl/android/hardware/graphics/composer3/ReleaseFences.h>
#include <aidl/android/hardware/graphics/composer3/RenderIntent.h>
#include <aidl/android/hardware/graphics/composer3/VirtualDisplay.h>
@@ -102,6 +107,7 @@ class IComposerHal {
const VsyncPeriodChangeTimeline& timeline) = 0;
virtual void onVsyncIdle(int64_t display) = 0;
virtual void onSeamlessPossible(int64_t display) = 0;
+ virtual void onRefreshRateChangedDebug(const RefreshRateChangedDebugData& data) = 0;
};
virtual void registerEventCallback(EventCallback* callback) = 0;
virtual void unregisterEventCallback() = 0;
@@ -121,7 +127,8 @@ class IComposerHal {
DisplayAttribute attribute, int32_t* outValue) = 0;
virtual int32_t getDisplayBrightnessSupport(int64_t display, bool& outSupport) = 0;
virtual int32_t getDisplayIdleTimerSupport(int64_t display, bool& outSupport) = 0;
-
+ virtual int32_t getDisplayMultiThreadedPresentSupport(const int64_t& display,
+ bool& outSupport) = 0;
virtual int32_t getDisplayCapabilities(int64_t display,
std::vector<DisplayCapability>* caps) = 0;
virtual int32_t getDisplayConfigs(int64_t display, std::vector<int32_t>* configs) = 0;
@@ -137,6 +144,7 @@ class IComposerHal {
common::Transform* orientation) = 0;
virtual int32_t getDozeSupport(int64_t display, bool& outSupport) = 0;
virtual int32_t getHdrCapabilities(int64_t display, HdrCapabilities* caps) = 0;
+ virtual int32_t getOverlaySupport(OverlayProperties* caps) = 0;
virtual int32_t getMaxVirtualDisplayCount(int32_t* count) = 0;
virtual int32_t getPerFrameMetadataKeys(int64_t display,
std::vector<PerFrameMetadataKey>* keys) = 0;
@@ -158,6 +166,9 @@ class IComposerHal {
virtual int32_t setBootDisplayConfig(int64_t display, int32_t config) = 0;
virtual int32_t clearBootDisplayConfig(int64_t display) = 0;
virtual int32_t getPreferredBootDisplayConfig(int64_t display, int32_t* config) = 0;
+ virtual int32_t getHdrConversionCapabilities(std::vector<common::HdrConversionCapability>*) = 0;
+ virtual int32_t setHdrConversionStrategy(const common::HdrConversionStrategy&,
+ common::Hdr*) = 0;
virtual int32_t setAutoLowLatencyMode(int64_t display, bool on) = 0;
virtual int32_t setClientTarget(int64_t display, buffer_handle_t target,
const ndk::ScopedFileDescriptor& fence,
@@ -220,6 +231,7 @@ class IComposerHal {
virtual int32_t setLayerBlockingRegion(
int64_t display, int64_t layer,
const std::vector<std::optional<common::Rect>>& blockingRegion) = 0;
+ virtual int32_t setRefreshRateChangedCallbackDebugEnabled(int64_t display, bool enabled) = 0;
};
} // namespace aidl::android::hardware::graphics::composer3::detail
diff --git a/include/displaycolor/displaycolor.h b/include/displaycolor/displaycolor.h
index d9141ff..f23d8a8 100644
--- a/include/displaycolor/displaycolor.h
+++ b/include/displaycolor/displaycolor.h
@@ -34,7 +34,9 @@ using android::hardware::graphics::common::V1_2::PixelFormat;
/**
* hwc/displaycolor interface history
*
- * 6.1.0.2022-05-18 Get calibrated serial number.
+ * 7.0.0.2022-03-22 Interface refactor
+ * 6.2.0.2022-05-18 Get calibrated serial number.
+ * 6.1.0.2022-04-29 dim solid color layer
* 6.0.0.2022-02-22 Get whether dimming in linear.
* 5.0.0.2022-02-17 Add layer dim ratio.
* 4.0.0.2021-12-20 Get pixel format and dataspace of blending stage.
@@ -60,8 +62,8 @@ constexpr struct DisplayColorIntfVer {
}
} kInterfaceVersion {
- 6,
- 1,
+ 7,
+ 0,
0,
};
@@ -115,12 +117,28 @@ struct DisplayInfo {
DisplayBrightnessTable brightness_table;
};
+struct Color {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+
+ bool operator==(const Color &rhs) const {
+ return r == rhs.r &&
+ g == rhs.g &&
+ b == rhs.b &&
+ a == rhs.a;
+ }
+};
+
struct LayerColorData {
bool operator==(const LayerColorData &rhs) const {
return dataspace == rhs.dataspace && matrix == rhs.matrix &&
static_metadata == rhs.static_metadata &&
dynamic_metadata == rhs.dynamic_metadata &&
- dim_ratio == rhs.dim_ratio;
+ dim_ratio == rhs.dim_ratio &&
+ is_solid_color_layer == rhs.is_solid_color_layer &&
+ (!is_solid_color_layer || solid_color == rhs.solid_color);
}
/**
@@ -230,6 +248,16 @@ struct LayerColorData {
* @brief the layer's luminance dim ratio
*/
float dim_ratio = 1.0f;
+
+ /**
+ * @brief is layer solid color
+ */
+ bool is_solid_color_layer;
+
+ /**
+ * @brief color for solid color layer
+ */
+ Color solid_color;
};
/**
@@ -318,6 +346,13 @@ class IDisplayColorGeneric {
const ConfigType *config = nullptr;
};
+ /// A collection of stages. For example, It could be pre-blending stages
+ //(per-channel) or post-blending stages.
+ template <typename ... IStageData>
+ struct IStageDataCollection : public IStageData ... {
+ virtual ~IStageDataCollection() {}
+ };
+
/// Interface for accessing data for panel
class IPanel {
public:
@@ -337,7 +372,7 @@ class IDisplayColorGeneric {
* @param scene Display scene data to use during the update.
* @return OK if successful, error otherwise.
*/
- virtual int Update(DisplayType display, const DisplayScene &scene) = 0;
+ virtual int Update(const DisplayType display, const DisplayScene &scene) = 0;
/**
* @brief Update display color data. This function is expected to be called
@@ -348,29 +383,27 @@ class IDisplayColorGeneric {
* @param scene Display scene data to use during the update.
* @return OK if successful, error otherwise.
*/
- virtual int UpdatePresent(DisplayType display, const DisplayScene &scene) = 0;
+ virtual int UpdatePresent(const DisplayType display, const DisplayScene &scene) = 0;
/**
* @brief Check if refresh rate regamma compensation is enabled.
*
* @return true for yes.
*/
- virtual bool IsRrCompensationEnabled(DisplayType display) = 0;
+ virtual bool IsRrCompensationEnabled(const DisplayType display) = 0;
/**
* @brief Get calibration information for each profiles.
* @param display The display to get the calibration information.
*/
- virtual const CalibrationInfo &GetCalibrationInfo(
- DisplayType display) const = 0;
+ virtual const CalibrationInfo &GetCalibrationInfo(const DisplayType display) const = 0;
/**
* @brief Get a map of supported ColorModes, and supported RenderIntents for
* each ColorMode.
* @param display The display to get the color modes and render intents.
*/
- virtual const ColorModesMap &ColorModesAndRenderIntents(
- DisplayType display) const = 0;
+ virtual const ColorModesMap &ColorModesAndRenderIntents(const DisplayType display) const = 0;
/**
* @brief Get pixel format and dataspace of blending stage.
@@ -379,7 +412,7 @@ class IDisplayColorGeneric {
* @param dataspace Dataspace of blending stage
* @return OK if successful, error otherwise.
*/
- virtual int GetBlendingProperty(DisplayType display,
+ virtual int GetBlendingProperty(const DisplayType display,
hwc::PixelFormat &pixel_format,
hwc::Dataspace &dataspace,
bool &dimming_linear) const = 0;
diff --git a/libacryl/Android.mk b/libacryl/Android.mk
index abbc2f2..2984d2d 100644
--- a/libacryl/Android.mk
+++ b/libacryl/Android.mk
@@ -16,7 +16,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_CFLAGS += -DLOG_TAG=\"libacryl\"
+LOCAL_CFLAGS += -DLOG_TAG=\"hwc-libacryl\"
#LOCAL_CFLAGS += -DLIBACRYL_DEBUG
ifdef BOARD_LIBACRYL_DEFAULT_COMPOSITOR
@@ -47,6 +47,7 @@ LOCAL_HEADER_LIBRARIES += libgralloc_headers
LOCAL_C_INCLUDES := $(LOCAL_PATH)/local_include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES += $(TOP)/hardware/google/graphics/$(TARGET_BOARD_PLATFORM)/libcap
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/libacryl/acrylic_factory.cpp b/libacryl/acrylic_factory.cpp
index 7242ecd..b59f409 100644
--- a/libacryl/acrylic_factory.cpp
+++ b/libacryl/acrylic_factory.cpp
@@ -23,181 +23,16 @@
#include "acrylic_g2d.h"
#include "acrylic_internal.h"
-
-static uint32_t all_fimg2d_gs101_formats[] = {
- HAL_PIXEL_FORMAT_RGBA_8888,
- HAL_PIXEL_FORMAT_BGRA_8888,
- HAL_PIXEL_FORMAT_RGBA_1010102,
- HAL_PIXEL_FORMAT_RGBX_8888,
- HAL_PIXEL_FORMAT_RGB_888,
- HAL_PIXEL_FORMAT_RGB_565,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P,
- HAL_PIXEL_FORMAT_YCrCb_420_SP, // NV21 (YVU420 semi-planar)
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, // NV21 on multi-buffer
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, // NV21 on multi-buffer
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP, // NV12 (YUV420 semi-planar)
- HAL_PIXEL_FORMAT_GOOGLE_NV12_SP, // NV12 (YUV420 semi-planar)
- MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I, // NV12 AFBC
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, // NV12 with MFC alignment constraints
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, // NV12M with MFC alignment constraints on multi-buffer
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV, // NV12M with MFC alignment constraints on multi-buffer
- HAL_PIXEL_FORMAT_YCbCr_422_SP, // YUV422 2P (YUV422 semi-planar)
- HAL_PIXEL_FORMAT_YCBCR_P010,
- HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B,
- MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC,
-};
-
-static uint32_t all_fimg2d_gs201_formats[] = {
- HAL_PIXEL_FORMAT_RGBA_8888,
- HAL_PIXEL_FORMAT_BGRA_8888,
- HAL_PIXEL_FORMAT_RGBA_1010102,
- HAL_PIXEL_FORMAT_RGBX_8888,
- HAL_PIXEL_FORMAT_RGB_888,
- HAL_PIXEL_FORMAT_RGB_565,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P,
- HAL_PIXEL_FORMAT_YCrCb_420_SP, // NV21 (YVU420 semi-planar)
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, // NV21 on multi-buffer
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, // NV21 on multi-buffer
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP, // NV12 (YUV420 semi-planar)
- HAL_PIXEL_FORMAT_GOOGLE_NV12_SP, // NV12 (YUV420 semi-planar)
- MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I, // NV12 AFBC
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, // NV12 with MFC alignment constraints
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, // NV12M with MFC alignment constraints on multi-buffer
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV, // NV12M with MFC alignment constraints on multi-buffer
- HAL_PIXEL_FORMAT_YCbCr_422_SP, // YUV422 2P (YUV422 semi-planar)
- HAL_PIXEL_FORMAT_YCBCR_P010,
- HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B,
- MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60,
- HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80,
-};
-
-// The presence of the dataspace definitions are in the order
-// of application's preference to reduce comparations.
-static int all_hwc_dataspaces[] = {
- HAL_DATASPACE_STANDARD_BT709,
- HAL_DATASPACE_STANDARD_BT709 | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_BT709 | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_BT2020,
- HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_BT2020 | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_BT601_625,
- HAL_DATASPACE_STANDARD_BT601_625 | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_BT601_625 | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_BT601_525,
- HAL_DATASPACE_STANDARD_BT601_525 | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_BT601_525 | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED,
- HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED,
- HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_DCI_P3,
- HAL_DATASPACE_STANDARD_DCI_P3 | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_DCI_P3 | HAL_DATASPACE_RANGE_LIMITED,
- HAL_DATASPACE_STANDARD_FILM,
- HAL_DATASPACE_STANDARD_FILM | HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_STANDARD_FILM | HAL_DATASPACE_RANGE_LIMITED,
- // 0 should be treated as BT709 Limited range
- 0,
- HAL_DATASPACE_RANGE_FULL,
- HAL_DATASPACE_RANGE_LIMITED,
- // Depricated legacy dataspace definitions
- HAL_DATASPACE_SRGB,
- HAL_DATASPACE_JFIF,
- HAL_DATASPACE_BT601_525,
- HAL_DATASPACE_BT601_625,
- HAL_DATASPACE_BT709,
-};
-
-const static stHW2DCapability __capability_fimg2d_gs101 = {
- .max_upsampling_num = {8, 8},
- .max_downsampling_factor = {4, 4},
- .max_upsizing_num = {8, 8},
- .max_downsizing_factor = {4, 4},
- .min_src_dimension = {1, 1},
- .max_src_dimension = {8192, 8192},
- .min_dst_dimension = {1, 1},
- .max_dst_dimension = {8192, 8192},
- .min_pix_align = {1, 1},
- .rescaling_count = 0,
- .compositing_mode = HW2DCapability::BLEND_NONE | HW2DCapability::BLEND_SRC_COPY | HW2DCapability::BLEND_SRC_OVER,
- .transform_type = HW2DCapability::TRANSFORM_ALL,
- .auxiliary_feature = HW2DCapability::FEATURE_PLANE_ALPHA | HW2DCapability::FEATURE_UORDER_WRITE
- | HW2DCapability::FEATURE_AFBC_ENCODE | HW2DCapability::FEATURE_AFBC_DECODE
- | HW2DCapability::FEATURE_SOLIDCOLOR,
- .num_formats = ARRSIZE(all_fimg2d_gs101_formats),
- .num_dataspaces = ARRSIZE(all_hwc_dataspaces),
- .max_layers = 4,
- .pixformats = all_fimg2d_gs101_formats,
- .dataspaces = all_hwc_dataspaces,
- .base_align = 1,
-};
-
-const static stHW2DCapability __capability_fimg2d_gs201 = {
- .max_upsampling_num = {8, 8},
- .max_downsampling_factor = {4, 4},
- .max_upsizing_num = {8, 8},
- .max_downsizing_factor = {4, 4},
- .min_src_dimension = {1, 1},
- .max_src_dimension = {8192, 8192},
- .min_dst_dimension = {1, 1},
- .max_dst_dimension = {8192, 8192},
- .min_pix_align = {1, 1},
- .rescaling_count = 0,
- .compositing_mode = HW2DCapability::BLEND_NONE | HW2DCapability::BLEND_SRC_COPY | HW2DCapability::BLEND_SRC_OVER,
- .transform_type = HW2DCapability::TRANSFORM_ALL,
- .auxiliary_feature = HW2DCapability::FEATURE_PLANE_ALPHA | HW2DCapability::FEATURE_UORDER_WRITE
- | HW2DCapability::FEATURE_AFBC_ENCODE | HW2DCapability::FEATURE_AFBC_DECODE
- | HW2DCapability::FEATURE_SOLIDCOLOR,
- .num_formats = ARRSIZE(all_fimg2d_gs201_formats),
- .num_dataspaces = ARRSIZE(all_hwc_dataspaces),
- .max_layers = 4,
- .pixformats = all_fimg2d_gs201_formats,
- .dataspaces = all_hwc_dataspaces,
- .base_align = 1,
-};
-
-static const HW2DCapability capability_fimg2d_gs101(__capability_fimg2d_gs101);
-
-static const HW2DCapability capability_fimg2d_gs201(__capability_fimg2d_gs201);
+#include "acrylic_capability.h"
Acrylic *Acrylic::createInstance(const char *spec)
{
Acrylic *compositor = nullptr;
ALOGD_TEST("Creating a new Acrylic instance of '%s'", spec);
-
- if (strcmp(spec, "fimg2d_gs101") == 0) {
- compositor = new AcrylicCompositorG2D(capability_fimg2d_gs101, true);
- } else if (strcmp(spec, "fimg2d_gs201") == 0) {
- compositor = new AcrylicCompositorG2D(capability_fimg2d_gs201, true);
- } else {
- ALOGE("Unknown HW2D compositor spec., %s", spec);
- return nullptr;
+ compositor = createAcrylicCompositorG2D(spec);
+ if (compositor) {
+ ALOGI("%s compositor added", spec);
}
ALOGE_IF(!compositor, "Failed to create HW2D compositor of '%s'", spec);
diff --git a/libacryl/acrylic_formats.cpp b/libacryl/acrylic_formats.cpp
index 9654de0..5bc37ae 100644
--- a/libacryl/acrylic_formats.cpp
+++ b/libacryl/acrylic_formats.cpp
@@ -91,6 +91,7 @@ static uint32_t __halfmt_to_v4l2_ycbcr[][2] = {
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, V4L2_PIX_FMT_NV12N_10B },
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, V4L2_PIX_FMT_NV12M_S10B },
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, V4L2_PIX_FMT_NV12M_P010 },
+ {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, V4L2_PIX_FMT_NV12_P010 },
{HAL_PIXEL_FORMAT_YCBCR_P010, V4L2_PIX_FMT_NV12_P010 },
{HAL_PIXEL_FORMAT_YCbCr_422_I, V4L2_PIX_FMT_YUYV },
{HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I, V4L2_PIX_FMT_YVYU },
@@ -172,6 +173,7 @@ static struct {
{HAL_PIXEL_FORMAT_YCBCR_P010, 1, 0x22, {24, 0, 0, 0}, HAL_PIXEL_FORMAT_YCBCR_P010, 2},
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, 2, 0x22, {16, 8, 0, 0}, HAL_PIXEL_FORMAT_YCBCR_P010, 2},
{HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B, 1, 0x22, {24, 0, 0, 0}, HAL_PIXEL_FORMAT_YCBCR_P010, 2},
+ {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, 1, 0x22, {24, 0, 0, 0}, HAL_PIXEL_FORMAT_YCBCR_P010, 2},
{MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I, 1, 0x22, {15, 0, 0, 0}, HAL_PIXEL_FORMAT_YCBCR_P010, 2},
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, 2, 0x22, { 8, 4, 0, 0}, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, 2},
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, 1, 0x22, {12, 0, 0, 0}, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, 2},
diff --git a/libacryl/acrylic_g2d.cpp b/libacryl/acrylic_g2d.cpp
index f3f4567..605e9f1 100644
--- a/libacryl/acrylic_g2d.cpp
+++ b/libacryl/acrylic_g2d.cpp
@@ -508,6 +508,7 @@ static g2d_fmt __halfmt_to_g2dfmt[] = {
{HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B, G2D_FMT_NV12_P010, 1, 0},
{MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I, G2D_FMT_NV12_P010, 1, 0},
{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, G2D_FMT_NV12_P010, 2, 0},
+ {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, G2D_FMT_NV12_P010, 1, 0},
{HAL_PIXEL_FORMAT_YCbCr_422_I, G2D_FMT_YUYV, 1, 0},
{HAL_PIXEL_FORMAT_EXYNOS_YCrCb_422_I, G2D_FMT_YVYU, 1, 0},
{HAL_PIXEL_FORMAT_YCbCr_422_SP, G2D_FMT_NV16, 1, 0},
diff --git a/libacryl/acrylic_g2d.h b/libacryl/acrylic_g2d.h
index e377017..6ed5942 100644
--- a/libacryl/acrylic_g2d.h
+++ b/libacryl/acrylic_g2d.h
@@ -70,7 +70,12 @@ public:
return;
for (unsigned int i = 0; i < mCmds->layer_count; i++) {
- unsigned int idx = (mCmds->layer_hdr_mode[i].offset >> 8) - 2;
+ unsigned int idx;
+
+ if (mWriter->hasColorFillLayer())
+ idx = (mCmds->layer_hdr_mode[i].offset >> 8) - 3;
+ else
+ idx = (mCmds->layer_hdr_mode[i].offset >> 8) - 2;
// If premultiplied alpha values are de-premultied before HDR conversion,
// it should be multiplied again after the conversion. But some of the HDR processors
diff --git a/libacryl/acrylic_layer.cpp b/libacryl/acrylic_layer.cpp
index b90d541..5c587fc 100644
--- a/libacryl/acrylic_layer.cpp
+++ b/libacryl/acrylic_layer.cpp
@@ -140,7 +140,8 @@ bool AcrylicCanvas::setImageBuffer(int fd[MAX_HW2D_PLANES], size_t len[MAX_HW2D_
for (int i = 0; i < num_buffers; i++) {
if ((offset[i] < 0) || (static_cast<size_t>(offset[i]) >= len[i])) {
- ALOGE("Too large offset %ld for length %zu of buffer[%d]", offset[i], len[i], i);
+ ALOGE("Too large offset %jd for length %zu of buffer[%d]",
+ static_cast<intmax_t>(offset[i]), len[i], i);
return false;
}
@@ -155,8 +156,8 @@ bool AcrylicCanvas::setImageBuffer(int fd[MAX_HW2D_PLANES], size_t len[MAX_HW2D_
m.mBufferFd[i] = fd[i];
mBufferLength[i] = len[i];
mBufferOffset[i] = offset[i];
- ALOGD_TEST("Configured buffer[%d]: fd %d, len %zu, offset %u (type: %s)",
- i, m.mBufferFd[i], mBufferLength[i], mBufferOffset[i],
+ ALOGD_TEST("Configured buffer[%d]: fd %d, len %zu, offset %jd (type: %s)", i,
+ m.mBufferFd[i], mBufferLength[i], static_cast<intmax_t>(mBufferOffset[i]),
canvasTypeName(mCanvasType));
}
diff --git a/libacryl/hdrplugin_headers/hardware/exynos/g2d_hdr_plugin.h b/libacryl/hdrplugin_headers/hardware/exynos/g2d_hdr_plugin.h
index 02b863a..aefed60 100644
--- a/libacryl/hdrplugin_headers/hardware/exynos/g2d_hdr_plugin.h
+++ b/libacryl/hdrplugin_headers/hardware/exynos/g2d_hdr_plugin.h
@@ -39,6 +39,7 @@ public:
virtual void setTargetDisplayLuminance(unsigned int __unused min, unsigned int __unused max) { };
virtual struct g2d_commandlist *getCommands() = 0;
virtual void putCommands(struct g2d_commandlist __unused *commands) { };
+ virtual bool hasColorFillLayer(void) { return false; }
};
#endif/* __LIBACRYL_PLUGIN_G2D_HDR_H__ */
diff --git a/libhwc2.1/Android.mk b/libhwc2.1/Android.mk
index 1918890..1e23ab7 100644
--- a/libhwc2.1/Android.mk
+++ b/libhwc2.1/Android.mk
@@ -67,8 +67,8 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware \
libvendorgraphicbuffer libbinder_ndk \
android.hardware.power-V2-ndk pixel-power-ext-V1-ndk
-LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \
- com.google.hardware.pixel.display-V6-ndk \
+LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V2-ndk \
+ com.google.hardware.pixel.display-V8-ndk \
libbinder_ndk \
libbase \
libpng \
@@ -97,13 +97,14 @@ LOCAL_C_INCLUDES += \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libexternaldisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libvirtualdisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libcolormanager \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdisplayinterface \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwcService \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libdisplayinterface \
- $(TOP)/hardware/google/graphics/common/libhwc2.1/libdrmresource/include
-
+ $(TOP)/hardware/google/graphics/common/libhwc2.1/libdrmresource/include \
+ $(TOP)/hardware/google/graphics/$(soc_ver)
LOCAL_SRC_FILES := \
libhwchelper/ExynosHWCHelper.cpp \
ExynosHWCDebug.cpp \
@@ -120,16 +121,21 @@ LOCAL_SRC_FILES := \
libdisplayinterface/ExynosDisplayInterface.cpp \
libdisplayinterface/ExynosDeviceDrmInterface.cpp \
libdisplayinterface/ExynosDisplayDrmInterface.cpp \
- pixel-display.cpp
+ pixel-display.cpp \
+ histogram_mediator.cpp
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS += libacryl libdrm libui libvendorgraphicbuffer
LOCAL_VINTF_FRAGMENTS += pixel-display-default.xml
+ifeq ($(USES_IDISPLAY_INTF_SEC),true)
+LOCAL_VINTF_FRAGMENTS += pixel-display-secondary.xml
+endif
+
include $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/Android.mk
LOCAL_CFLAGS += -DHLOG_CODE=0
-LOCAL_CFLAGS += -DLOG_TAG=\"display\"
+LOCAL_CFLAGS += -DLOG_TAG=\"hwc-display\"
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
@@ -153,9 +159,10 @@ LOCAL_HEADER_LIBRARIES += libgralloc_headers
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libbinder libexynosdisplay libacryl \
android.hardware.graphics.composer@2.4 \
android.hardware.graphics.allocator@2.0 \
- android.hardware.graphics.mapper@2.0
+ android.hardware.graphics.mapper@2.0 \
+ android.hardware.graphics.composer3-V2-ndk
-LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V6-ndk \
+LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V8-ndk \
libbinder_ndk \
libbase
@@ -175,6 +182,7 @@ LOCAL_C_INCLUDES += \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libexternaldisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libvirtualdisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libcolormanager \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
$(TOP)/hardware/google/graphics/common/libhwc2.1/libhwcService \
@@ -185,7 +193,7 @@ LOCAL_EXPORT_SHARED_LIBRARY_HEADERS += libdrm
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_C_INCLUDES)
LOCAL_CFLAGS := -DHLOG_CODE=0
-LOCAL_CFLAGS += -DLOG_TAG=\"hwcservice\"
+LOCAL_CFLAGS += -DLOG_TAG=\"hwc-service\"
LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
LOCAL_SRC_FILES := \
@@ -215,8 +223,8 @@ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libexynosdisplay libacryl \
android.hardware.graphics.mapper@2.0 \
libui
-LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \
- com.google.hardware.pixel.display-V6-ndk \
+LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V2-ndk \
+ com.google.hardware.pixel.display-V8-ndk \
libbinder_ndk \
libbase
@@ -225,7 +233,7 @@ LOCAL_HEADER_LIBRARIES := libhardware_legacy_headers libbinder_headers google_ha
LOCAL_HEADER_LIBRARIES += libgralloc_headers
LOCAL_CFLAGS := -DHLOG_CODE=0
-LOCAL_CFLAGS += -DLOG_TAG=\"hwcomposer\"
+LOCAL_CFLAGS += -DLOG_TAG=\"hwc-2\"
LOCAL_CFLAGS += -DSOC_VERSION=$(soc_ver)
ifeq ($(BOARD_USES_HWC_SERVICES),true)
@@ -246,6 +254,7 @@ LOCAL_C_INCLUDES += \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libmaindisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libexternaldisplay \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libvirtualdisplay \
+ $(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libcolormanager \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libdevice \
$(TOP)/hardware/google/graphics/$(soc_ver)/libhwc2.1/libresource \
diff --git a/libhwc2.1/ExynosHWC.cpp b/libhwc2.1/ExynosHWC.cpp
index 8b3d9a4..c21245f 100644
--- a/libhwc2.1/ExynosHWC.cpp
+++ b/libhwc2.1/ExynosHWC.cpp
@@ -192,7 +192,7 @@ void exynos_getCapabilities(struct hwc2_device *dev, uint32_t *outCount, int32_t
if (!exynosDevice)
*outCapabilities = 0;
else
- return exynosDevice->getCapabilities(outCount, outCapabilities);
+ return exynosDevice->getCapabilitiesLegacy(outCount, outCapabilities);
}
void exynos_dump(hwc2_device_t *dev, uint32_t *outSize, char *outBuffer)
@@ -1149,15 +1149,34 @@ int32_t exynos_SetActiveConfigWithConstraints(hwc2_device_t* dev, hwc2_display_t
{
HDEBUGLOGD(eDebugDisplayConfig, "%s, %d", __func__, config);
ExynosDevice *exynosDevice = checkDevice(dev);
+ if (!exynosDevice) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
- if (exynosDevice) {
- ExynosDisplay *exynosDisplay = checkDisplay(exynosDevice, display);
- if (exynosDisplay) {
- return exynosDisplay->setActiveConfigWithConstraints(config, vsyncPeriodChangeConstraints, outTimeline);
+ ExynosDisplay *exynosDisplay = checkDisplay(exynosDevice, display);
+ if (!exynosDisplay) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ const auto prevXres = exynosDisplay->mXres, prevYres = exynosDisplay->mYres;
+ auto ret = exynosDisplay->setActiveConfigWithConstraints(config,
+ vsyncPeriodChangeConstraints,
+ outTimeline);
+ if (ret != HWC2_ERROR_NONE) {
+ ALOGE("exynos_SetActiveConfigWithConstraints() failed config(%d)", config);
+ return ret;
+ }
+
+ // when resolution is changed, HWC2 updates the property
+ if (prevXres != exynosDisplay->mDisplayConfigs[config].width ||
+ prevYres != exynosDisplay->mDisplayConfigs[config].height) {
+ if ((ret = exynosDisplay->setBootDisplayConfig(config)) != HWC2_ERROR_NONE) {
+ ALOGE("setBootDisplayConfig() failed when setActiveConfigWithConstraints()");
+ return ret;
}
}
- return HWC2_ERROR_BAD_DISPLAY;
+ return HWC2_ERROR_NONE;
}
int32_t exynos_SetAutoLowLatencyMode(hwc2_device_t* dev, hwc2_display_t display, bool on)
diff --git a/libhwc2.1/ExynosHWC.h b/libhwc2.1/ExynosHWC.h
index 8d17a74..f1235d9 100644
--- a/libhwc2.1/ExynosHWC.h
+++ b/libhwc2.1/ExynosHWC.h
@@ -24,9 +24,6 @@
//#define DISABLE_FENCE
-#define HWC_FPS_TH 5 /* valid range 1 to 60 */
-#define VSYNC_INTERVAL (1000000000.0 / 60)
-
enum {
HWC_CTL_MAX_OVLY_CNT = 100,
HWC_CTL_VIDEO_OVLY_CNT = 101,
diff --git a/libhwc2.1/ExynosHWCDebug.cpp b/libhwc2.1/ExynosHWCDebug.cpp
index bbf676c..dc42369 100644
--- a/libhwc2.1/ExynosHWCDebug.cpp
+++ b/libhwc2.1/ExynosHWCDebug.cpp
@@ -18,33 +18,13 @@
#include <sync/sync.h>
#include "exynos_sync.h"
-uint32_t mErrLogSize = 0;
-uint32_t mFenceLogSize = 0;
-
-int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display)
-{
+int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display) {
+ if (display == nullptr) return -1;
int32_t ret = NO_ERROR;
- if (mErrLogSize >= ERR_LOG_SIZE)
- return -1;
- FILE *pFile = NULL;
- char filePath[128];
- sprintf(filePath, "%s/hwc_error_log.txt", ERROR_LOG_PATH0);
- pFile = fopen(filePath, "a");
- if (pFile == NULL) {
- ALOGE("Fail to open file %s/hwc_error_log.txt, error: %s", ERROR_LOG_PATH0, strerror(errno));
- sprintf(filePath, "%s/hwc_error_log.txt", ERROR_LOG_PATH1);
- pFile = fopen(filePath, "a");
- }
- if (pFile == NULL) {
- ALOGE("Fail to open file %s/hwc_error_log.txt, error: %s", ERROR_LOG_PATH1, strerror(errno));
- return -errno;
- }
+ auto &fileWriter = display->mErrLogFileWriter;
- mErrLogSize = ftell(pFile);
- if (mErrLogSize >= ERR_LOG_SIZE) {
- if (pFile != NULL)
- fclose(pFile);
+ if (!fileWriter.chooseOpenedFile()) {
return -1;
}
@@ -52,47 +32,19 @@ int32_t saveErrorLog(const String8 &errString, ExynosDisplay *display)
struct timeval tv;
gettimeofday(&tv, NULL);
- if (display != NULL) {
- saveString.appendFormat("%s %s %" PRIu64 ": %s\n", getLocalTimeStr(tv).string(),
- display->mDisplayName.string(), display->mErrorFrameCount,
- errString.string());
- } else {
- saveString.appendFormat("%s : %s\n", getLocalTimeStr(tv).string(), errString.string());
- }
+ saveString.appendFormat("%s errFrameNumber %" PRIu64 ": %s\n", getLocalTimeStr(tv).string(),
+ display->mErrorFrameCount, errString.string());
- if (pFile != NULL) {
- fwrite(saveString.string(), 1, saveString.size(), pFile);
- mErrLogSize = (uint32_t)ftell(pFile);
- ret = mErrLogSize;
- fclose(pFile);
- }
+ fileWriter.write(saveString);
+ fileWriter.flush();
return ret;
}
int32_t saveFenceTrace(ExynosDisplay *display) {
int32_t ret = NO_ERROR;
+ auto &fileWriter = display->mFenceFileWriter;
- if (mFenceLogSize >= FENCE_ERR_LOG_SIZE)
- return -1;
-
- FILE *pFile = NULL;
- char filePath[128];
- sprintf(filePath, "%s/hwc_fence_state.txt", ERROR_LOG_PATH0);
- pFile = fopen(filePath, "a");
- if (pFile == NULL) {
- ALOGE("Fail to open file %s/hwc_fence_state.txt, error: %s", ERROR_LOG_PATH0, strerror(errno));
- sprintf(filePath, "%s/hwc_fence_state.txt", ERROR_LOG_PATH1);
- pFile = fopen(filePath, "a");
- }
- if (pFile == NULL) {
- ALOGE("Fail to open file %s, error: %s", ERROR_LOG_PATH1, strerror(errno));
- return -errno;
- }
-
- mFenceLogSize = ftell(pFile);
- if (mFenceLogSize >= FENCE_ERR_LOG_SIZE) {
- if (pFile != NULL)
- fclose(pFile);
+ if (!fileWriter.chooseOpenedFile()) {
return -1;
}
@@ -117,12 +69,7 @@ int32_t saveFenceTrace(ExynosDisplay *display) {
}
}
- if (pFile != NULL) {
- fwrite(saveString.string(), 1, saveString.size(), pFile);
- mFenceLogSize = (uint32_t)ftell(pFile);
- ret = mFenceLogSize;
- fclose(pFile);
- }
-
+ fileWriter.write(saveString);
+ fileWriter.flush();
return ret;
}
diff --git a/libhwc2.1/ExynosHWCDebug.h b/libhwc2.1/ExynosHWCDebug.h
index 01a49cf..8bc6092 100644
--- a/libhwc2.1/ExynosHWCDebug.h
+++ b/libhwc2.1/ExynosHWCDebug.h
@@ -17,6 +17,8 @@
#define HWC_DEBUG_H
#include <utils/String8.h>
+#include <utils/Trace.h>
+
#include "ExynosHWC.h"
#include "ExynosHWCHelper.h"
@@ -43,6 +45,8 @@ enum {
eDebugColorManagement = 0x00080000,
eDebugAttrSetting = 0x00100000,
eDebugDisplayConfig = 0x00400000,
+ eDebugTDM = 0x00800000,
+ eDebugLoadBalancing = 0x01000000,
};
class ExynosDisplay;
@@ -110,6 +114,13 @@ int32_t saveFenceTrace(ExynosDisplay *display);
saveErrorLog(saveString, this); \
}
+#define DISPLAY_DRM_LOGI(msg, ...) \
+ ALOGI("[%s] " msg, mExynosDisplay->mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_DRM_LOGW(msg, ...) \
+ ALOGW("[%s] " msg, mExynosDisplay->mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_DRM_LOGE(msg, ...) \
+ ALOGE("[%s] " msg, mExynosDisplay->mDisplayName.string(), ##__VA_ARGS__)
+
#define MPP_LOGV(msg, ...) ALOGV("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__)
#define MPP_LOGI(msg, ...) ALOGI("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__)
#define MPP_LOGW(msg, ...) ALOGW("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__)
@@ -129,4 +140,38 @@ int32_t saveFenceTrace(ExynosDisplay *display);
saveErrorLog(saveString, display); \
}
+class ScopedTraceEnder {
+public:
+ ~ScopedTraceEnder() { ATRACE_END(); }
+};
+
+#define ATRACE_FORMAT(fmt, ...) \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) { \
+ String8 traceName; \
+ traceName.appendFormat(fmt, ##__VA_ARGS__); \
+ ATRACE_BEGIN(traceName.string()); \
+ } \
+ ScopedTraceEnder traceEnder
+
+#define DISPLAY_ATRACE_NAME(name) ATRACE_FORMAT("%s for %s", name, mDisplayTraceName.string())
+#define DISPLAY_ATRACE_CALL() DISPLAY_ATRACE_NAME(__func__)
+#define DISPLAY_ATRACE_INT(name, value) \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) { \
+ ATRACE_INT(String8::format("%s for %s", name, mDisplayTraceName.string()).string(), \
+ value); \
+ }
+#define DISPLAY_ATRACE_INT64(name, value) \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) { \
+ ATRACE_INT64(String8::format("%s for %s", name, mDisplayTraceName.string()).string(), \
+ value); \
+ }
+
+#define DISPLAY_LOGD_AND_ATRACE_NAME(debugFlag, fmt, ...) \
+ if (hwcCheckDebugMessages(debugFlag) || CC_UNLIKELY(ATRACE_ENABLED())) { \
+ String8 log; \
+ log.appendFormat((fmt), ##__VA_ARGS__); \
+ DISPLAY_LOGD(debugFlag, "%s", log.string()); \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) ATRACE_NAME(log.string()); \
+ }
+
#endif
diff --git a/libhwc2.1/histogram_mediator.cpp b/libhwc2.1/histogram_mediator.cpp
new file mode 100644
index 0000000..f23feec
--- /dev/null
+++ b/libhwc2.1/histogram_mediator.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 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 "histogram_mediator.h"
+
+histogram::HistogramMediator::HistogramMediator(ExynosDisplay *display) {
+ mDisplay = display;
+ ExynosDisplayDrmInterface *moduleDisplayInterface =
+ static_cast<ExynosDisplayDrmInterface *>(display->mDisplayInterface.get());
+ mIDLHistogram = std::make_shared<HistogramReceiver>();
+
+ moduleDisplayInterface->registerHistogramInfo(mIDLHistogram);
+ moduleDisplayInterface->getPanelResolution();
+}
+uint32_t histogram::HistogramMediator::getFrameCount() {
+ ExynosDisplayDrmInterface *moduleDisplayInterface =
+ static_cast<ExynosDisplayDrmInterface *>(mDisplay->mDisplayInterface.get());
+ return moduleDisplayInterface->getFrameCount();
+}
+
+bool histogram::HistogramMediator::isDisplayPowerOff() {
+ if (!mDisplay->mPowerModeState.has_value() ||
+ ((mDisplay->mPowerModeState.value() == HWC2_POWER_MODE_OFF) ||
+ (mDisplay->mPowerModeState.value() == HWC2_POWER_MODE_DOZE))) {
+ return true;
+ }
+ return false;
+}
+
+bool histogram::HistogramMediator::isSecureContentPresenting() {
+ Mutex::Autolock lock(mDisplay->mDRMutex);
+ for (uint32_t i = 0; i < mDisplay->mLayers.size(); i++) {
+ ExynosLayer *layer = mDisplay->mLayers[i];
+ if (layer != NULL && layer->isDrm()) { /* there is some DRM layer */
+ return true;
+ }
+ }
+ return false;
+}
+histogram::HistogramErrorCode histogram::HistogramMediator::requestHist() {
+ if (isSecureContentPresenting()) { /* there is some DRM layer */
+ return histogram::HistogramErrorCode::DRM_PLAYING;
+ }
+ ExynosDisplayDrmInterface *moduleDisplayInterface =
+ static_cast<ExynosDisplayDrmInterface *>(mDisplay->mDisplayInterface.get());
+
+ {
+ std::unique_lock<std::mutex> lk(mIDLHistogram->mDataCollectingMutex);
+ if (moduleDisplayInterface->setHistogramControl(
+ hidl_histogram_control_t::HISTOGRAM_CONTROL_REQUEST) != NO_ERROR) {
+ return histogram::HistogramErrorCode::ENABLE_HIST_ERROR;
+ }
+ mIDLHistogram->mHistReq_pending = true;
+ }
+ return histogram::HistogramErrorCode::NONE;
+}
+
+histogram::HistogramErrorCode histogram::HistogramMediator::cancelHistRequest() {
+ ExynosDisplayDrmInterface *moduleDisplayInterface =
+ static_cast<ExynosDisplayDrmInterface *>(mDisplay->mDisplayInterface.get());
+
+ if (moduleDisplayInterface->setHistogramControl(
+ hidl_histogram_control_t::HISTOGRAM_CONTROL_CANCEL) != NO_ERROR) {
+ return histogram::HistogramErrorCode::DISABLE_HIST_ERROR;
+ }
+ return histogram::HistogramErrorCode::NONE;
+}
+
+void histogram::HistogramMediator::HistogramReceiver::callbackHistogram(char16_t *bin) {
+ std::unique_lock<std::mutex> lk(mDataCollectingMutex);
+ if (mHistReq_pending == true) {
+ std::memcpy(mHistData, bin, HISTOGRAM_BINS_SIZE * sizeof(char16_t));
+ mHistReq_pending = false;
+ }
+ mHistData_cv.notify_all();
+}
+
+int histogram::HistogramMediator::calculateThreshold(const RoiRect &roi) {
+ int threshold = ((roi.bottom - roi.top) * (roi.right - roi.left)) >> 16;
+ return threshold + 1;
+}
+
+histogram::HistogramErrorCode histogram::HistogramMediator::setRoiWeightThreshold(
+ const RoiRect &roi, const Weight &weight, const HistogramPos &pos) {
+ int threshold = calculateThreshold(roi);
+ mIDLHistogram->setHistogramROI((uint16_t)roi.left, (uint16_t)roi.top,
+ (uint16_t)(roi.right - roi.left),
+ (uint16_t)(roi.bottom - roi.top));
+ mIDLHistogram->setHistogramWeights(weight.weightR, weight.weightG, weight.weightB);
+ mIDLHistogram->setHistogramThreshold(threshold);
+ mIDLHistogram->setHistogramPos(pos);
+
+ return histogram::HistogramErrorCode::NONE;
+}
+
+histogram::HistogramErrorCode histogram::HistogramMediator::collectRoiLuma(
+ std::vector<char16_t> *buf) {
+ std::unique_lock<std::mutex> lk(mIDLHistogram->mDataCollectingMutex);
+
+ mIDLHistogram->mHistData_cv.wait_for(lk, std::chrono::milliseconds(50), [this]() {
+ return (!isDisplayPowerOff() && !mIDLHistogram->mHistReq_pending);
+ });
+ if (mIDLHistogram->mHistReq_pending == false) setSampleFrameCounter(getFrameCount());
+ buf->assign(mIDLHistogram->mHistData, mIDLHistogram->mHistData + HISTOGRAM_BINS_SIZE);
+
+ return histogram::HistogramErrorCode::NONE;
+}
+
+histogram::RoiRect histogram::HistogramMediator::calRoi(const RoiRect &roi) {
+ RoiRect roi_return = {-1, -1, -1, -1};
+ ExynosDisplayDrmInterface *moduleDisplayInterface =
+ static_cast<ExynosDisplayDrmInterface *>(mDisplay->mDisplayInterface.get());
+ roi_return.left = roi.left * moduleDisplayInterface->getActiveModeHDisplay() /
+ moduleDisplayInterface->panelHsize();
+ roi_return.top = roi.top * moduleDisplayInterface->getActiveModeVDisplay() /
+ moduleDisplayInterface->panelVsize();
+ roi_return.right = roi.right * moduleDisplayInterface->getActiveModeHDisplay() /
+ moduleDisplayInterface->panelHsize();
+ roi_return.bottom = roi.bottom * moduleDisplayInterface->getActiveModeVDisplay() /
+ moduleDisplayInterface->panelVsize();
+ return roi_return;
+}
diff --git a/libhwc2.1/histogram_mediator.h b/libhwc2.1/histogram_mediator.h
new file mode 100644
index 0000000..54d28c9
--- /dev/null
+++ b/libhwc2.1/histogram_mediator.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 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 HISTOGRAM_MEDIATOR_H_
+#define HISTOGRAM_MEDIATOR_H_
+
+#include <aidl/android/hardware/graphics/common/Rect.h>
+#include <aidl/com/google/hardware/pixel/display/BnDisplay.h>
+#include <aidl/com/google/hardware/pixel/display/HistogramErrorCode.h>
+#include <aidl/com/google/hardware/pixel/display/HistogramPos.h>
+#include <aidl/com/google/hardware/pixel/display/Priority.h>
+#include <aidl/com/google/hardware/pixel/display/Weight.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <vector>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+#include "ExynosDevice.h"
+#include "ExynosDisplay.h"
+#include "ExynosDisplayDrmInterfaceModule.h"
+#include "ExynosDisplayInterface.h"
+#include "ExynosLayer.h"
+
+namespace histogram {
+using RoiRect = ::aidl::android::hardware::graphics::common::Rect;
+using Weight = ::aidl::com::google::hardware::pixel::display::Weight;
+using HistogramPos = ::aidl::com::google::hardware::pixel::display::HistogramPos;
+using Priority = ::aidl::com::google::hardware::pixel::display::Priority;
+using HistogramErrorCode = ::aidl::com::google::hardware::pixel::display::HistogramErrorCode;
+
+constexpr size_t HISTOGRAM_BINS_SIZE = 256;
+constexpr size_t WEIGHT_SUM = 1024;
+
+class HistogramMediator {
+public:
+ HistogramMediator() = default;
+ HistogramMediator(ExynosDisplay *display);
+ ~HistogramMediator() {}
+
+ bool isDisplayPowerOff();
+ bool isSecureContentPresenting();
+ HistogramErrorCode requestHist();
+ HistogramErrorCode cancelHistRequest();
+ HistogramErrorCode collectRoiLuma(std::vector<char16_t> *buf);
+ HistogramErrorCode setRoiWeightThreshold(const RoiRect &roi, const Weight &weight,
+ const HistogramPos &pos);
+ RoiRect calRoi(const RoiRect &roi);
+ struct HistogramReceiver : public IDLHistogram {
+ HistogramReceiver() : mHistData(){};
+ void callbackHistogram(char16_t *bin) override;
+ uint16_t mHistData[HISTOGRAM_BINS_SIZE]; // luma buffer
+ std::condition_variable mHistData_cv; // for pullback data sync ctrl
+ bool mHistReq_pending = false;
+ std::mutex mDataCollectingMutex; // for data collecting operations
+ };
+
+ struct HistogramConfig {
+ RoiRect mRoi;
+ Weight mWeights;
+ HistogramPos mPos;
+
+ HistogramConfig() {}
+
+ HistogramConfig(const RoiRect &roi, const Weight &weights, const HistogramPos &pos) {
+ mRoi = roi;
+ mWeights = weights;
+ mPos = pos;
+ }
+
+ bool operator!=(const HistogramConfig &rhs) {
+ return mRoi != rhs.mRoi || mWeights != rhs.mWeights || mPos != rhs.mPos;
+ }
+
+ HistogramConfig &operator=(const HistogramConfig &rhs) {
+ mRoi = rhs.mRoi;
+ mWeights = rhs.mWeights;
+ mPos = rhs.mPos;
+ return *this;
+ }
+ };
+
+ uint32_t getFrameCount();
+ void setSampleFrameCounter(int32_t id) { mSampledFrameCounter = id; }
+ uint32_t getSampleFrameCounter() { return mSampledFrameCounter; }
+ bool histRequested() { return mIDLHistogram->mHistReq_pending; }
+ std::mutex mConfigMutex;
+ HistogramConfig mConfig GUARDED_BY(mConfigMutex);
+
+private:
+ int calculateThreshold(const RoiRect &roi);
+ std::shared_ptr<HistogramReceiver> mIDLHistogram;
+ ExynosDisplay *mDisplay = nullptr;
+ uint32_t mSampledFrameCounter = 0;
+};
+
+} // namespace histogram
+
+#endif // HISTOGRAM_MEDIATOR_H_
diff --git a/libhwc2.1/libdevice/BrightnessController.cpp b/libhwc2.1/libdevice/BrightnessController.cpp
index 40fb813..5a226e0 100644
--- a/libhwc2.1/libdevice/BrightnessController.cpp
+++ b/libhwc2.1/libdevice/BrightnessController.cpp
@@ -34,10 +34,12 @@ BrightnessController::BrightnessController(int32_t panelIndex, std::function<voi
mLhbm(false),
mSdrDim(false),
mPrevSdrDim(false),
+ mDimBrightnessReq(false),
mFrameRefresh(refresh),
mHdrLayerState(HdrLayerState::kHdrNone),
mUpdateDcLhbm(updateDcLhbm) {
initBrightnessSysfs();
+ initCabcSysfs();
}
BrightnessController::~BrightnessController() {
@@ -58,14 +60,21 @@ int BrightnessController::initDrm(const DrmDevice& drmDevice,
mLhbmSupported = connector.lhbm_on().id() != 0;
mGhbmSupported = connector.hbm_mode().id() != 0;
+
+ /* allow the first brightness to apply */
+ mBrightnessFloatReq.set_dirty();
return NO_ERROR;
}
void BrightnessController::initDimmingUsage() {
- mBrightnessDimmingUsage = static_cast<BrightnessDimmingUsage>(
- property_get_int32("vendor.display.brightness.dimming.usage", 0));
- mHbmDimmingTimeUs =
- property_get_int32("vendor.display.brightness.dimming.hbm_time", kHbmDimmingTimeUs);
+ String8 propName;
+ propName.appendFormat(kDimmingUsagePropName, mPanelIndex);
+
+ mBrightnessDimmingUsage = static_cast<BrightnessDimmingUsage>(property_get_int32(propName, 0));
+
+ propName.clear();
+ propName.appendFormat(kDimmingHbmTimePropName, mPanelIndex);
+ mHbmDimmingTimeUs = property_get_int32(propName, kHbmDimmingTimeUs);
if (mBrightnessDimmingUsage == BrightnessDimmingUsage::NORMAL) {
mDimming.store(true);
@@ -100,6 +109,21 @@ void BrightnessController::initBrightnessSysfs() {
ifsMaxBrightness.close();
}
+void BrightnessController::initCabcSysfs() {
+ mCabcSupport = property_get_bool("vendor.display.cabc.supported", false);
+ if (!mCabcSupport) return;
+
+ String8 nodeName;
+ nodeName.appendFormat(kLocalCabcModeFileNode, mPanelIndex);
+
+ mCabcModeOfs.open(nodeName.string(), std::ofstream::out);
+ if (mCabcModeOfs.fail()) {
+ ALOGE("%s %s fail to open", __func__, nodeName.string());
+ mCabcModeOfs.close();
+ return;
+ }
+}
+
void BrightnessController::initBrightnessTable(const DrmDevice& drmDevice,
const DrmConnector& connector) {
if (connector.brightness_cap().id() == 0) {
@@ -133,9 +157,25 @@ void BrightnessController::initBrightnessTable(const DrmDevice& drmDevice,
// init to min before SF sets the brightness
mDisplayWhitePointNits = cap->normal.nits.min;
+ mPrevDisplayWhitePointNits = mDisplayWhitePointNits;
mBrightnessIntfSupported = true;
drmModeFreePropertyBlob(blob);
+
+ String8 nodeName;
+ nodeName.appendFormat(kDimBrightnessFileNode, mPanelIndex);
+
+ std::ifstream ifsDimBrightness(nodeName.string());
+ if (ifsDimBrightness.fail()) {
+ ALOGW("%s fail to open %s", __func__, nodeName.string());
+ } else {
+ ifsDimBrightness >> mDimBrightness;
+ ifsDimBrightness.close();
+ if (mDimBrightness >= mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBklStart)
+ mDimBrightness = 0;
+ }
+ mDbmSupported = !!mDimBrightness;
+ ALOGI("%s mDimBrightness=%d, mDbmSupported=%d", __func__, mDimBrightness, mDbmSupported);
}
int BrightnessController::processEnhancedHbm(bool on) {
@@ -177,6 +217,9 @@ int BrightnessController::processDisplayBrightness(float brightness, const nsecs
{
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
+ /* apply the first brightness */
+ if (mBrightnessFloatReq.is_dirty()) mBrightnessLevel.set_dirty();
+
mBrightnessFloatReq.store(brightness);
if (!mBrightnessFloatReq.is_dirty()) {
return NO_ERROR;
@@ -185,20 +228,14 @@ int BrightnessController::processDisplayBrightness(float brightness, const nsecs
// check if it will go drm path for below cases.
// case 1: hbm state will change
// case 2: for hwc3, brightness command could apply at next present if possible
- if (mGhbmSupported || waitPresent) {
+ if (queryBrightness(brightness, &ghbm, &level) == NO_ERROR) {
// ghbm on/off always go drm path
- if (mGhbmSupported) {
- if (queryBrightness(brightness, &ghbm, &level)) {
- ALOGE("%s failed to convert brightness %f", __func__, brightness);
- return -EINVAL;
- }
- // check if this will cause a hbm transition
- if ((mGhbm.get() != HbmMode::OFF) != ghbm) {
- // this brightness change will go drm path
- updateStates();
- mFrameRefresh(); // force next frame to update brightness
- return NO_ERROR;
- }
+ // check if this will cause a hbm transition
+ if (mGhbmSupported && (mGhbm.get() != HbmMode::OFF) != ghbm) {
+ // this brightness change will go drm path
+ updateStates();
+ mFrameRefresh(); // force next frame to update brightness
+ return NO_ERROR;
}
// there will be a Present to apply this brightness change
if (waitPresent) {
@@ -209,21 +246,23 @@ int BrightnessController::processDisplayBrightness(float brightness, const nsecs
} else {
level = brightness < 0 ? 0 : static_cast<uint32_t>(brightness * mMaxBrightness + 0.5f);
}
- // go sysfs path
+ // clear dirty before go sysfs path
+ mBrightnessFloatReq.clear_dirty();
}
// Sysfs path is faster than drm path. If there is an unchecked drm path change, the sysfs
// path should check the sysfs content.
if (mUncheckedGbhmRequest) {
ATRACE_NAME("check_ghbm_mode");
- checkSysfsStatus(kGlobalHbmModeFileNode,
- std::to_string(toUnderlying(mPendingGhbmStatus.load())), vsyncNs * 5);
+ checkSysfsStatus(GetPanelSysfileByIndex(kGlobalHbmModeFileNode),
+ {std::to_string(toUnderlying(mPendingGhbmStatus.load()))}, vsyncNs * 5);
mUncheckedGbhmRequest = false;
}
if (mUncheckedLhbmRequest) {
ATRACE_NAME("check_lhbm_mode");
- checkSysfsStatus(kLocalHbmModeFileNode, std::to_string(mPendingLhbmStatus), vsyncNs * 5);
+ checkSysfsStatus(GetPanelSysfileByIndex(kLocalHbmModeFileNode),
+ {std::to_string(mPendingLhbmStatus)}, vsyncNs * 5);
mUncheckedLhbmRequest = false;
}
@@ -262,7 +301,8 @@ int BrightnessController::applyPendingChangeViaSysfs(const nsecs_t vsyncNs) {
if (mUncheckedBlRequest) {
ATRACE_NAME("check_bl_value");
- checkSysfsStatus(BRIGHTNESS_SYSFS_NODE, std::to_string(mPendingBl), vsyncNs * 5);
+ checkSysfsStatus(GetPanelSysfileByIndex(BRIGHTNESS_SYSFS_NODE),
+ {std::to_string(mPendingBl)}, vsyncNs * 5);
mUncheckedBlRequest = false;
}
@@ -276,6 +316,13 @@ int BrightnessController::processLocalHbm(bool on) {
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
mLhbmReq.store(on);
+ // As kernel timeout timer might disable LHBM without letting HWC know, enforce mLhbmReq and
+ // mLhbm dirty to ensure the enabling request can be passed through kernel unconditionally.
+ // TODO-b/260915350: move LHBM timeout mechanism from kernel to HWC for easier control and sync.
+ if (on) {
+ mLhbmReq.set_dirty();
+ mLhbm.set_dirty();
+ }
if (mLhbmReq.is_dirty()) {
updateStates();
}
@@ -310,6 +357,16 @@ int BrightnessController::processInstantHbm(bool on) {
return NO_ERROR;
}
+int BrightnessController::processDimBrightness(bool on) {
+ std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
+ mDimBrightnessReq.store(on);
+ if (mDimBrightnessReq.is_dirty()) {
+ updateStates();
+ ALOGI("%s request = %d", __func__, mDimBrightnessReq.get());
+ }
+ return NO_ERROR;
+}
+
float BrightnessController::getSdrDimRatioForInstantHbm() {
if (!mBrightnessIntfSupported || !mGhbmSupported) {
return 1.0f;
@@ -340,28 +397,36 @@ float BrightnessController::getSdrDimRatioForInstantHbm() {
return ratio;
}
-void BrightnessController::onClearDisplay() {
+void BrightnessController::onClearDisplay(bool needModeClear) {
+ resetLhbmState();
+ mInstantHbmReq.reset(false);
+
+ if (mBrightnessLevel.is_dirty()) applyBrightnessViaSysfs(mBrightnessLevel.get());
+
+ if (!needModeClear) return;
+
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
mEnhanceHbmReq.reset(false);
- mLhbmReq.reset(false);
mBrightnessFloatReq.reset(-1);
- mInstantHbmReq.reset(false);
mBrightnessLevel.reset(0);
+ mDisplayWhitePointNits = 0;
+ mPrevDisplayWhitePointNits = 0;
mGhbm.reset(HbmMode::OFF);
mDimming.reset(false);
mHbmDimming = false;
if (mBrightnessDimmingUsage == BrightnessDimmingUsage::NORMAL) {
mDimming.store(true);
}
- mLhbm.reset(false);
- mLhbmBrightnessAdj = false;
+ std::lock_guard<std::recursive_mutex> lock1(mCabcModeMutex);
+ mCabcMode.reset(CabcMode::OFF);
}
int BrightnessController::prepareFrameCommit(ExynosDisplay& display,
const DrmConnector& connector,
ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
+ const bool mixedComposition,
bool& ghbmSync, bool& lhbmSync, bool& blSync) {
int ret;
@@ -372,6 +437,17 @@ int BrightnessController::prepareFrameCommit(ExynosDisplay& display,
ATRACE_CALL();
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
+ bool sync = false;
+ if (mixedComposition && mPrevDisplayWhitePointNits > 0 && mDisplayWhitePointNits > 0) {
+ float diff = std::abs(mPrevDisplayWhitePointNits - mDisplayWhitePointNits);
+ float min = std::min(mPrevDisplayWhitePointNits, mDisplayWhitePointNits);
+ if (diff / min > kBrightnessSyncThreshold) {
+ sync = true;
+ ALOGD("%s: enable brightness sync for change from %f to %f", __func__,
+ mPrevDisplayWhitePointNits, mDisplayWhitePointNits);
+ }
+ }
+
if (mDimming.is_dirty()) {
if ((ret = drmReq.atomicAddProperty(connector.id(), connector.dimming_on(),
mDimming.get())) < 0) {
@@ -437,9 +513,11 @@ int BrightnessController::prepareFrameCommit(ExynosDisplay& display,
} else {
mUncheckedBlRequest = true;
mPendingBl = mBrightnessLevel.get();
+ blSync = sync;
}
}
mBrightnessLevel.clear_dirty();
+ mPrevDisplayWhitePointNits = mDisplayWhitePointNits;
}
if (mGhbm.is_dirty() && mGhbmSupported) {
@@ -455,7 +533,7 @@ int BrightnessController::prepareFrameCommit(ExynosDisplay& display,
hbmEnum)) < 0) {
ALOGE("%s: Fail to set hbm_mode property", __func__);
} else {
- ghbmSync = true;
+ ghbmSync = sync;
}
mGhbm.clear_dirty();
}
@@ -558,11 +636,11 @@ int BrightnessController::updateStates() {
mInstantHbmReq.clear_dirty();
mSdrDim.clear_dirty();
mPrevSdrDim.clear_dirty();
+ mDimBrightnessReq.clear_dirty();
if (mBrightnessLevel.is_dirty() || mDimming.is_dirty() || mGhbm.is_dirty() ||
mLhbm.is_dirty()) {
- ALOGI("level=%d, DimmingOn=%d, Hbm=%d, LhbmOn=%d.", mBrightnessLevel.get(), mDimming.get(),
- mGhbm.get(), mLhbm.get());
+ printBrightnessStates("drm");
}
return NO_ERROR;
}
@@ -573,6 +651,15 @@ int BrightnessController::queryBrightness(float brightness, bool *ghbm, uint32_t
return HWC2_ERROR_UNSUPPORTED;
}
+ if (mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBklStart == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBklEnd == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBriStart == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mBriEnd == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mNitsStart == 0 &&
+ mBrightnessTable[toUnderlying(BrightnessRange::NORMAL)].mNitsEnd == 0) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
if (brightness < 0) {
// screen off
if (ghbm) {
@@ -608,7 +695,10 @@ int BrightnessController::queryBrightness(float brightness, bool *ghbm, uint32_t
*nits = norm * nSpan + mBrightnessTable[i].mNitsStart;
}
}
-
+ if ((i == toUnderlying(BrightnessRange::NORMAL)) && mDbmSupported &&
+ (mDimBrightnessReq.get() == true) && (*level == mBrightnessTable[i].mBklStart)) {
+ *level = mDimBrightness;
+ }
return NO_ERROR;
}
}
@@ -617,27 +707,39 @@ int BrightnessController::queryBrightness(float brightness, bool *ghbm, uint32_t
}
// Return immediately if it's already in the status. Otherwise poll the status
-int BrightnessController::checkSysfsStatus(const char* file, const std::string& expectedValue,
+int BrightnessController::checkSysfsStatus(const std::string& file,
+ const std::vector<std::string>& expectedValue,
const nsecs_t timeoutNs) {
ATRACE_CALL();
+
+ if (expectedValue.size() == 0) {
+ return -EINVAL;
+ }
+
char buf[16];
- String8 nodeName;
- nodeName.appendFormat(file, mPanelIndex);
- UniqueFd fd = open(nodeName.string(), O_RDONLY);
+ UniqueFd fd = open(file.c_str(), O_RDONLY);
+ if (fd.get() < 0) {
+ ALOGE("%s failed to open sysfs %s: %s", __func__, file.c_str(), strerror(errno));
+ return -ENOENT;
+ }
int size = read(fd.get(), buf, sizeof(buf));
if (size <= 0) {
- ALOGE("%s failed to read from %s", __func__, kLocalHbmModeFileNode);
- return false;
+ ALOGE("%s failed to read from %s: %s", __func__, file.c_str(), strerror(errno));
+ return -EIO;
}
// '- 1' to remove trailing '\n'
- if (std::string_view(buf, size - 1) == expectedValue) {
- return true;
+ std::string val = std::string(buf, size - 1);
+ if (std::find(expectedValue.begin(), expectedValue.end(), val) != expectedValue.end()) {
+ return OK;
+ } else if (timeoutNs == 0) {
+ // not get the expected value and no intention to wait
+ return -EINVAL;
}
struct pollfd pfd;
- int ret = EINVAL;
+ int ret = -EINVAL;
auto startTime = systemTime(SYSTEM_TIME_MONOTONIC);
pfd.fd = fd.get();
@@ -651,9 +753,9 @@ int BrightnessController::checkSysfsStatus(const char* file, const std::string&
}
int pollRet = poll(&pfd, 1, ns2ms(remainTimeNs));
if (pollRet == 0) {
- ALOGW("%s poll timeout", __func__);
+ ALOGW("%s poll %s timeout", __func__, file.c_str());
// time out
- ret = ETIMEDOUT;
+ ret = -ETIMEDOUT;
break;
} else if (pollRet > 0) {
if (!(pfd.revents & POLLPRI)) {
@@ -663,31 +765,72 @@ int BrightnessController::checkSysfsStatus(const char* file, const std::string&
lseek(fd.get(), 0, SEEK_SET);
size = read(fd.get(), buf, sizeof(buf));
if (size > 0) {
- if (std::string_view(buf, size - 1) == expectedValue) {
- ret = 0;
+ val = std::string(buf, size - 1);
+ if (std::find(expectedValue.begin(), expectedValue.end(), val) !=
+ expectedValue.end()) {
+ ret = OK;
+ break;
} else {
- buf[size - 1] = 0;
- ALOGE("%s read %s expected %s after notified", __func__, buf,
- expectedValue.c_str());
- ret = EINVAL;
+ std::string values;
+ for (auto& s : expectedValue) {
+ values += s + std::string(" ");
+ }
+ if (values.size() > 0) {
+ values.resize(values.size() - 1);
+ }
+ ALOGW("%s read %s expected %s after notified on file %s", __func__, val.c_str(),
+ values.c_str(), file.c_str());
}
} else {
- ret = EIO;
- ALOGE("%s failed to read after notified %d", __func__, errno);
+ ret = -EIO;
+ ALOGE("%s failed to read after notified %d on file %s", __func__, errno,
+ file.c_str());
+ break;
}
- break;
} else {
if (errno == EAGAIN || errno == EINTR) {
continue;
}
- ALOGE("%s poll failed %d", __func__, errno);
- ret = errno;
+ ALOGE("%s poll failed %d on file %s", __func__, errno, file.c_str());
+ ret = -errno;
break;
}
};
- return ret == NO_ERROR;
+ return ret;
+}
+
+void BrightnessController::resetLhbmState() {
+ std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
+ mLhbmReq.reset(false);
+ mLhbm.reset(false);
+ mLhbmBrightnessAdj = false;
+}
+
+void BrightnessController::setOutdoorVisibility(LbeState state) {
+ std::lock_guard<std::recursive_mutex> lock(mCabcModeMutex);
+ mOutdoorVisibility = (state != LbeState::OFF);
+}
+
+int BrightnessController::updateCabcMode() {
+ if (!mCabcSupport || mCabcModeOfs.fail()) return HWC2_ERROR_UNSUPPORTED;
+
+ std::lock_guard<std::recursive_mutex> lock(mCabcModeMutex);
+ CabcMode mode;
+ if (mOutdoorVisibility)
+ mode = CabcMode::OFF;
+ else
+ mode = isHdrLayerOn() ? CabcMode::CABC_MOVIE_MODE : CabcMode::CABC_UI_MODE;
+ mCabcMode.store(mode);
+
+ if (mCabcMode.is_dirty()) {
+ applyCabcModeViaSysfs(static_cast<uint8_t>(mode));
+ ALOGD("%s, isHdrLayerOn: %d, mOutdoorVisibility: %d.", __func__, isHdrLayerOn(),
+ mOutdoorVisibility);
+ mCabcMode.clear_dirty();
+ }
+ return NO_ERROR;
}
int BrightnessController::applyBrightnessViaSysfs(uint32_t level) {
@@ -705,8 +848,8 @@ int BrightnessController::applyBrightnessViaSysfs(uint32_t level) {
{
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
mBrightnessLevel.reset(level);
- ALOGI("level=%d, DimmingOn=%d, Hbm=%d, LhbmOn=%d", level,
- mDimming.get(), mGhbm.get(), mLhbm.get());
+ mPrevDisplayWhitePointNits = mDisplayWhitePointNits;
+ printBrightnessStates("sysfs");
}
return NO_ERROR;
@@ -715,6 +858,22 @@ int BrightnessController::applyBrightnessViaSysfs(uint32_t level) {
return HWC2_ERROR_UNSUPPORTED;
}
+int BrightnessController::applyCabcModeViaSysfs(uint8_t mode) {
+ if (!mCabcModeOfs.is_open()) return HWC2_ERROR_UNSUPPORTED;
+
+ ATRACE_NAME("write_cabc_mode_sysfs");
+ mCabcModeOfs.seekp(std::ios_base::beg);
+ mCabcModeOfs << std::to_string(mode);
+ mCabcModeOfs.flush();
+ if (mCabcModeOfs.fail()) {
+ ALOGE("%s fail to write CabcMode %d", __func__, mode);
+ mCabcModeOfs.clear();
+ return HWC2_ERROR_NO_RESOURCES;
+ }
+ ALOGI("%s Cabc_Mode=%d", __func__, mode);
+ return NO_ERROR;
+}
+
// brightness is normalized to current display brightness
bool BrightnessController::validateLayerBrightness(float brightness) {
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
@@ -745,6 +904,15 @@ void BrightnessController::parseHbmModeEnums(const DrmProperty& property) {
}
}
+/*
+ * WARNING: This print is parsed by Battery Historian. Consult with the Battery
+ * Historian team before modifying (b/239640926).
+ */
+void BrightnessController::printBrightnessStates(const char* path) {
+ ALOGI("path=%s, id=%d, level=%d, DimmingOn=%d, Hbm=%d, LhbmOn=%d", path ?: "unknown",
+ mPanelIndex, mBrightnessLevel.get(), mDimming.get(), mGhbm.get(), mLhbm.get());
+}
+
void BrightnessController::dump(String8& result) {
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
@@ -753,10 +921,10 @@ void BrightnessController::dump(String8& result) {
"lhbm supported %d, ghbm supported %d\n", mBrightnessOfs.is_open(),
mMaxBrightness, mBrightnessIntfSupported, mLhbmSupported, mGhbmSupported);
result.appendFormat("\trequests: enhance hbm %d, lhbm %d, "
- "brightness %f, instant hbm %d\n",
+ "brightness %f, instant hbm %d, DimBrightness %d\n",
mEnhanceHbmReq.get(), mLhbmReq.get(), mBrightnessFloatReq.get(),
- mInstantHbmReq.get());
- result.appendFormat("\tstates: brighntess level %d, ghbm %d, dimming %d, lhbm %d\n",
+ mInstantHbmReq.get(), mDimBrightnessReq.get());
+ result.appendFormat("\tstates: brighntess level %d, ghbm %d, dimming %d, lhbm %d",
mBrightnessLevel.get(), mGhbm.get(), mDimming.get(), mLhbm.get());
result.appendFormat("\thdr layer state %d, unchecked lhbm request %d(%d), "
"unchecked ghbm request %d(%d)\n",
@@ -765,6 +933,10 @@ void BrightnessController::dump(String8& result) {
mPendingGhbmStatus.load());
result.appendFormat("\tdimming usage %d, hbm dimming %d, time us %d\n", mBrightnessDimmingUsage,
mHbmDimming, mHbmDimmingTimeUs);
- result.appendFormat("\twhite point nits %f\n", mDisplayWhitePointNits);
+ result.appendFormat("\twhite point nits current %f, previous %f\n", mDisplayWhitePointNits,
+ mPrevDisplayWhitePointNits);
+ result.appendFormat("\tcabc supported %d, cabcMode %d\n", mCabcModeOfs.is_open(),
+ mCabcMode.get());
+
result.appendFormat("\n");
}
diff --git a/libhwc2.1/libdevice/BrightnessController.h b/libhwc2.1/libdevice/BrightnessController.h
index 2e4d304..66f4b23 100644
--- a/libhwc2.1/libdevice/BrightnessController.h
+++ b/libhwc2.1/libdevice/BrightnessController.h
@@ -65,6 +65,8 @@ public:
int processEnhancedHbm(bool on);
int processDisplayBrightness(float bl, const nsecs_t vsyncNs, bool waitPresent = false);
int processLocalHbm(bool on);
+ int processDimBrightness(bool on);
+ bool isDbmSupported() { return mDbmSupported; }
int applyPendingChangeViaSysfs(const nsecs_t vsyncNs);
bool validateLayerBrightness(float brightness);
@@ -88,7 +90,7 @@ public:
*/
float getSdrDimRatioForInstantHbm();
- void onClearDisplay();
+ void onClearDisplay(bool needModeClear);
/**
* apply brightness change on drm path.
@@ -97,6 +99,7 @@ public:
int prepareFrameCommit(ExynosDisplay& display,
const DrmConnector& connector,
ExynosDisplayDrmInterface::DrmModeAtomicReq& drmReq,
+ const bool mixedComposition,
bool& ghbmSync, bool& lhbmSync, bool& blSync);
bool isGhbmSupported() { return mGhbmSupported; }
@@ -111,8 +114,13 @@ public:
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
return mLhbm.get();
}
- int checkSysfsStatus(const char *file, const std::string &expectedValue,
+ int checkSysfsStatus(const std::string& file, const std::vector<std::string>& expectedValue,
const nsecs_t timeoutNs);
+ bool fileExists(const std::string& file) {
+ struct stat sb;
+ return stat(file.c_str(), &sb) == 0;
+ }
+ void resetLhbmState();
uint32_t getBrightnessLevel() {
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
@@ -135,6 +143,25 @@ public:
void dump(String8 &result);
+ void setOutdoorVisibility(LbeState state);
+
+ int updateCabcMode();
+
+ const std::string GetPanelSysfileByIndex(const char *file_pattern) {
+ String8 nodeName;
+ nodeName.appendFormat(file_pattern, mPanelIndex);
+ return nodeName.c_str();
+ }
+
+ const std::string GetPanelRefreshRateSysfile() {
+ String8 nodeName;
+ nodeName.appendFormat(kRefreshrateFileNode,
+ mPanelIndex == 0 ? "primary"
+ : mPanelIndex == 1 ? "secondary"
+ : "unknown");
+ return nodeName.c_str();
+ }
+
struct BrightnessTable {
float mBriStart;
float mBriEnd;
@@ -154,16 +181,39 @@ public:
const BrightnessTable *getBrightnessTable() { return mBrightnessTable; }
+ /*
+ * WARNING: This enum is parsed by Battery Historian. Add new values, but
+ * do not modify/remove existing ones. Alternatively, consult with the
+ * Battery Historian team (b/239640926).
+ */
enum class BrightnessRange : uint32_t {
NORMAL = 0,
- HBM,
+ HBM = 1,
MAX,
};
+ /*
+ * WARNING: This enum is parsed by Battery Historian. Add new values, but
+ * do not modify/remove existing ones. Alternatively, consult with the
+ * Battery Historian team (b/239640926).
+ */
enum class HbmMode {
OFF = 0,
- ON_IRC_ON,
- ON_IRC_OFF,
+ ON_IRC_ON = 1,
+ ON_IRC_OFF = 2,
+ };
+
+ /*
+ * LHBM command need take a couple of frames to become effective
+ * DISABLED - finish sending disabling command to panel
+ * ENABLED - panel finishes boosting brightness to the peak value
+ * ENABLING - finish sending enabling command to panel (panel begins boosting brightness)
+ * Note: the definition should be consistent with kernel driver
+ */
+ enum class LhbmMode {
+ DISABLED = 0,
+ ENABLED = 1,
+ ENABLING = 2,
};
/*
@@ -171,36 +221,60 @@ public:
* NORMAL- enable dimming
* HBM- enable dimming only for hbm transition
* NONE- disable dimming
+ *
+ * WARNING: This enum is parsed by Battery Historian. Add new values, but
+ * do not modify/remove existing ones. Alternatively, consult with the
+ * Battery Historian team (b/239640926).
*/
enum class BrightnessDimmingUsage {
NORMAL = 0,
- HBM,
+ HBM = 1,
NONE,
};
static constexpr const char *kLocalHbmModeFileNode =
"/sys/class/backlight/panel%d-backlight/local_hbm_mode";
+ static constexpr const char* kDimBrightnessFileNode =
+ "/sys/class/backlight/panel%d-backlight/dim_brightness";
+ static constexpr const char* kRefreshrateFileNode =
+ "/sys/devices/platform/exynos-drm/%s-panel/refresh_rate";
+
private:
+ // sync brightness change for mixed composition when there is more than 50% luminance change.
+ // The percentage is calculated as:
+ // (big_lumi - small_lumi) / small_lumi
+ // For mixed composition, if remove brightness animations, the minimum brightness jump is
+ // between nbm peak and hbm peak. 50% will cover known panels
+ static constexpr float kBrightnessSyncThreshold = 0.5f;
// Worst case for panel with brightness range 2 nits to 1000 nits.
static constexpr float kGhbmMinDimRatio = 0.002;
static constexpr int32_t kHbmDimmingTimeUs = 5000000;
static constexpr const char *kGlobalHbmModeFileNode =
"/sys/class/backlight/panel%d-backlight/hbm_mode";
+ static constexpr const char* kDimmingUsagePropName =
+ "vendor.display.%d.brightness.dimming.usage";
+ static constexpr const char* kDimmingHbmTimePropName =
+ "vendor.display.%d.brightness.dimming.hbm_time";
int queryBrightness(float brightness, bool* ghbm = nullptr, uint32_t* level = nullptr,
float *nits = nullptr);
void initBrightnessTable(const DrmDevice& device, const DrmConnector& connector);
void initBrightnessSysfs();
+ void initCabcSysfs();
void initDimmingUsage();
int applyBrightnessViaSysfs(uint32_t level);
+ int applyCabcModeViaSysfs(uint8_t mode);
int updateStates() REQUIRES(mBrightnessMutex);
void dimmingThread();
void processDimmingOff();
void parseHbmModeEnums(const DrmProperty& property);
+ void printBrightnessStates(const char* path) REQUIRES(mBrightnessMutex);
+
bool mLhbmSupported = false;
bool mGhbmSupported = false;
+ bool mDbmSupported = false;
bool mBrightnessIntfSupported = false;
BrightnessTable mBrightnessTable[toUnderlying(BrightnessRange::MAX)];
@@ -221,6 +295,7 @@ private:
CtrlValue<bool> mLhbm GUARDED_BY(mBrightnessMutex);
CtrlValue<bool> mSdrDim GUARDED_BY(mBrightnessMutex);
CtrlValue<bool> mPrevSdrDim GUARDED_BY(mBrightnessMutex);
+ CtrlValue<bool> mDimBrightnessReq GUARDED_BY(mBrightnessMutex);
// Indicating if the last LHBM on has changed the brightness level
bool mLhbmBrightnessAdj = false;
@@ -251,11 +326,30 @@ private:
// sysfs path
std::ofstream mBrightnessOfs;
uint32_t mMaxBrightness = 0; // read from sysfs
+ std::ofstream mCabcModeOfs;
+ bool mCabcSupport = false;
+ uint32_t mDimBrightness = 0;
// Note IRC or dimming is not in consideration for now.
float mDisplayWhitePointNits = 0;
+ float mPrevDisplayWhitePointNits = 0;
std::function<void(void)> mUpdateDcLhbm;
+
+ // state for control CABC state
+ enum class CabcMode {
+ OFF = 0,
+ CABC_UI_MODE,
+ CABC_STILL_MODE,
+ CABC_MOVIE_MODE,
+ };
+
+ static constexpr const char* kLocalCabcModeFileNode =
+ "/sys/class/backlight/panel%d-backlight/cabc_mode";
+ std::recursive_mutex mCabcModeMutex;
+ bool mOutdoorVisibility GUARDED_BY(mCabcModeMutex) = false;
+ bool isHdrLayerOn() { return mHdrLayerState.get() == HdrLayerState::kHdrLarge; }
+ CtrlValue<CabcMode> mCabcMode GUARDED_BY(mCabcModeMutex);
};
#endif // _BRIGHTNESS_CONTROLLER_H_
diff --git a/libhwc2.1/libdevice/DisplayColorLoader.h b/libhwc2.1/libdevice/DisplayColorLoader.h
new file mode 100644
index 0000000..02bbbf8
--- /dev/null
+++ b/libhwc2.1/libdevice/DisplayColorLoader.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 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 DISPLAY_COLOR_LOADER_H
+#define DISPLAY_COLOR_LOADER_H
+
+#include <dlfcn.h>
+#include <log/log.h>
+#include <string>
+#include <vector>
+
+template <typename GsInterfaceType, const char *entry>
+class DisplayColorLoader {
+ static_assert(entry != nullptr);
+ public:
+ DisplayColorLoader(const DisplayColorLoader &) = delete;
+ DisplayColorLoader& operator=(const DisplayColorLoader &) = delete;
+
+ DisplayColorLoader(const std::string &libName) {
+ libHandle = dlopen(libName.c_str(), RTLD_LAZY);
+
+ if (libHandle == nullptr) {
+ ALOGE("%s: failed to load library %s\n", __func__, libName.c_str());
+ getDisplayColor = nullptr;
+ return;
+ }
+
+ const displaycolor::DisplayColorIntfVer *(*getVersion)();
+ getVersion = reinterpret_cast<decltype(getVersion)>(dlsym(libHandle, "GetInterfaceVersion"));
+ if (getVersion == nullptr) {
+ ALOGE("%s: prebuilt lib is not versioned", __func__);
+ return;
+ }
+
+ auto intfVer = getVersion();
+
+ if (intfVer != nullptr &&
+ displaycolor::kInterfaceVersion.Compatible(*intfVer)) {
+ getDisplayColor = reinterpret_cast<decltype(getDisplayColor)>(dlsym(libHandle, entry));
+
+ if (getDisplayColor == nullptr) {
+ ALOGE("%s: failed to get %s\n", __func__, entry);
+ } else if (!(displaycolor::kInterfaceVersion == *intfVer)) {
+ ALOGW("%s: different hwc/displaycolor patch level %u.%u.%u vs .%u",
+ __func__,
+ intfVer->major,
+ intfVer->minor,
+ displaycolor::kInterfaceVersion.patch,
+ intfVer->patch);
+ }
+ } else {
+ if (intfVer != nullptr) {
+ ALOGE("%s: prebuilt lib version %u.%u.%u expected %u.%u.%u",
+ __func__,
+ intfVer->major,
+ intfVer->minor,
+ intfVer->patch,
+ displaycolor::kInterfaceVersion.major,
+ displaycolor::kInterfaceVersion.minor,
+ displaycolor::kInterfaceVersion.patch);
+ } else {
+ ALOGE("%s: prebult lib getVersion returns null", __func__);
+ }
+ }
+ }
+
+ GsInterfaceType *GetDisplayColor(
+ const std::vector<displaycolor::DisplayInfo> &display_info) {
+ if (getDisplayColor != nullptr) {
+ return getDisplayColor(display_info);
+ }
+
+ return nullptr;
+ }
+
+ ~DisplayColorLoader() {
+ if (libHandle != nullptr) {
+ dlclose(libHandle);
+ }
+ }
+
+ private:
+ void *libHandle;
+ GsInterfaceType *(*getDisplayColor)(const std::vector<displaycolor::DisplayInfo> &);
+};
+
+#endif //DISPLAY_COLOR_LOADER_H
diff --git a/libhwc2.1/libdevice/ExynosDevice.cpp b/libhwc2.1/libdevice/ExynosDevice.cpp
index 99f9438..99fbc1a 100644
--- a/libhwc2.1/libdevice/ExynosDevice.cpp
+++ b/libhwc2.1/libdevice/ExynosDevice.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
#include "ExynosDevice.h"
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
@@ -43,8 +45,14 @@ using aidl::android::hardware::graphics::composer3::IComposerCallback;
class ExynosDevice;
-extern uint32_t mFenceLogSize;
-extern void PixelDisplayInit(ExynosDevice *device);
+extern void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str);
+
+static const std::map<const uint32_t, const std::string_view> pixelDisplayIntfName =
+ {{getDisplayId(HWC_DISPLAY_PRIMARY, 0), "default"},
+#ifdef USES_IDISPLAY_INTF_SEC
+ {getDisplayId(HWC_DISPLAY_PRIMARY, 1), "secondary"}
+#endif
+};
int hwcDebug;
int hwcFenceDebug[FENCE_IP_ALL];
@@ -87,9 +95,18 @@ ExynosDevice::ExynosDevice()
exynosHWCControl.sysFenceLogging = false;
exynosHWCControl.useDynamicRecomp = false;
- mInterfaceType = getDeviceInterfaceType();
+ hwcDebug = 0;
+ mInterfaceType = getDeviceInterfaceType();
ALOGD("HWC2 : %s : interface type(%d)", __func__, mInterfaceType);
+
+ /*
+ * This order should not be changed
+ * new ExynosResourceManager ->
+ * create displays and add them to the list ->
+ * initDeviceInterface() ->
+ * ExynosResourceManager::updateRestrictions()
+ */
mResourceManager = new ExynosResourceManagerModule(this);
for (size_t i = 0; i < AVAILABLE_DISPLAY_UNITS.size(); i++) {
@@ -98,7 +115,9 @@ ExynosDevice::ExynosDevice()
ALOGD("Create display[%zu] type: %d, index: %d", i, display_t.type, display_t.index);
switch(display_t.type) {
case HWC_DISPLAY_PRIMARY:
- exynos_display = (ExynosDisplay *)(new ExynosPrimaryDisplayModule(display_t.index, this));
+ exynos_display =
+ (ExynosDisplay *)(new ExynosPrimaryDisplayModule(display_t.index, this,
+ display_t.display_name));
if(display_t.index == 0) {
exynos_display->mPlugState = true;
ExynosMPP::mainDisplayWidth = exynos_display->mXres;
@@ -112,10 +131,14 @@ ExynosDevice::ExynosDevice()
}
break;
case HWC_DISPLAY_EXTERNAL:
- exynos_display = (ExynosDisplay *)(new ExynosExternalDisplayModule(display_t.index, this));
+ exynos_display =
+ (ExynosDisplay *)(new ExynosExternalDisplayModule(display_t.index, this,
+ display_t.display_name));
break;
case HWC_DISPLAY_VIRTUAL:
- exynos_display = (ExynosDisplay *)(new ExynosVirtualDisplayModule(display_t.index, this));
+ exynos_display =
+ (ExynosDisplay *)(new ExynosVirtualDisplayModule(display_t.index, this,
+ display_t.display_name));
mNumVirtualDisplay = 0;
break;
default:
@@ -123,8 +146,8 @@ ExynosDevice::ExynosDevice()
break;
}
exynos_display->mDeconNodeName.appendFormat("%s", display_t.decon_node_name.c_str());
- exynos_display->mDisplayName.appendFormat("%s", display_t.display_name.c_str());
mDisplays.add(exynos_display);
+ mDisplayMap.insert(std::make_pair(exynos_display->mDisplayId, exynos_display));
#ifndef FORCE_DISABLE_DR
if (exynos_display->mDREnable)
@@ -136,7 +159,6 @@ ExynosDevice::ExynosDevice()
dynamicRecompositionThreadCreate();
- hwcDebug = 0;
for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
hwcFenceDebug[i] = 0;
@@ -145,35 +167,44 @@ ExynosDevice::ExynosDevice()
sprintf(fence_names[i], "_%2dh", i);
}
- String8 saveString;
- saveString.appendFormat("ExynosDevice is initialized");
- uint32_t errFileSize = saveErrorLog(saveString);
- ALOGI("Initial errlog size: %d bytes\n", errFileSize);
+ for (auto it : mDisplays) {
+ std::string displayName = std::string(it->mDisplayName.string());
+ it->mErrLogFileWriter.setPrefixName(displayName + "_hwc_error_log");
+ it->mDebugDumpFileWriter.setPrefixName(displayName + "_hwc_debug");
+ it->mFenceFileWriter.setPrefixName(displayName + "_hwc_fence_state");
+ String8 saveString;
+ saveString.appendFormat("ExynosDisplay %s is initialized", it->mDisplayName.string());
+ saveErrorLog(saveString, it);
+ }
- /*
- * This order should not be changed
- * new ExynosResourceManager ->
- * create displays and add them to the list ->
- * initDeviceInterface() ->
- * ExynosResourceManager::updateRestrictions()
- */
initDeviceInterface(mInterfaceType);
+
+ // registerRestrictions();
mResourceManager->updateRestrictions();
+ mResourceManager->initDisplays(mDisplays, mDisplayMap);
+ mResourceManager->initDisplaysTDMInfo();
if (mInterfaceType == INTERFACE_TYPE_DRM) {
- /* disable vblank immediately after updates */
- setVBlankOffDelay(-1);
+ setVBlankOffDelay(1);
}
- PixelDisplayInit(this);
-
- ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
char value[PROPERTY_VALUE_MAX];
property_get("vendor.display.lbe.supported", value, "0");
- mLbeSupported = atoi(value) ? true : false;
- if (mLbeSupported) {
- primary_display->initLbe();
+ const bool lbe_supported = atoi(value) ? true : false;
+
+ for (size_t i = 0; i < mDisplays.size(); i++) {
+ if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY) {
+ auto iter = pixelDisplayIntfName.find(getDisplayId(HWC_DISPLAY_PRIMARY, i));
+ if (iter != pixelDisplayIntfName.end()) {
+ PixelDisplayInit(mDisplays[i], iter->second);
+ if (lbe_supported) {
+ mDisplays[i]->initLbe();
+ }
+ }
+ }
}
+
+ mDisplayOffAsync = property_get_bool("vendor.display.async_off.supported", false);
}
void ExynosDevice::initDeviceInterface(uint32_t interfaceType)
@@ -195,6 +226,7 @@ void ExynosDevice::initDeviceInterface(uint32_t interfaceType)
display->mDisplayInterface) != NO_ERROR) {
ALOGD("Remove display[%d], Failed to initialize display interface", i);
mDisplays.removeAt(i);
+ mDisplayMap.erase(display->mDisplayId);
delete display;
} else {
i++;
@@ -203,20 +235,20 @@ void ExynosDevice::initDeviceInterface(uint32_t interfaceType)
}
ExynosDevice::~ExynosDevice() {
-
- ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY,0));
-
mDRLoopStatus = false;
mDRThread.join();
-
- delete primary_display;
+ for(auto& display : mDisplays) {
+ delete display;
+ }
+ mDisplays.clear();
}
bool ExynosDevice::isFirstValidate()
{
for (uint32_t i = 0; i < mDisplays.size(); i++) {
if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
- (mDisplays[i]->mPowerModeState == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
+ (!mDisplays[i]->mPowerModeState.has_value() ||
+ (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
continue;
if ((mDisplays[i]->mPlugState == true) &&
((mDisplays[i]->mRenderingState != RENDERING_STATE_NONE) &&
@@ -233,7 +265,8 @@ bool ExynosDevice::isLastValidate(ExynosDisplay *display)
if (mDisplays[i] == display)
continue;
if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
- (mDisplays[i]->mPowerModeState == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
+ (!mDisplays[i]->mPowerModeState.has_value() ||
+ (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
continue;
if ((mDisplays[i]->mPlugState == true) &&
(mDisplays[i]->mRenderingState != RENDERING_STATE_VALIDATED) &&
@@ -243,6 +276,17 @@ bool ExynosDevice::isLastValidate(ExynosDisplay *display)
return true;
}
+bool ExynosDevice::hasOtherDisplayOn(ExynosDisplay *display) {
+ for (uint32_t i = 0; i < mDisplays.size(); i++) {
+ if (mDisplays[i] == display) continue;
+ if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
+ mDisplays[i]->mPowerModeState.has_value() &&
+ (mDisplays[i]->mPowerModeState.value() != (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
+ return true;
+ }
+ return false;
+}
+
bool ExynosDevice::isDynamicRecompositionThreadAlive()
{
android_atomic_acquire_load(&mDRThreadStatus);
@@ -251,6 +295,7 @@ bool ExynosDevice::isDynamicRecompositionThreadAlive()
void ExynosDevice::checkDynamicRecompositionThread()
{
+ ATRACE_CALL();
// If thread was destroyed, create thread and run. (resume status)
if (isDynamicRecompositionThreadAlive() == false) {
for (uint32_t i = 0; i < mDisplays.size(); i++) {
@@ -266,6 +311,7 @@ void ExynosDevice::checkDynamicRecompositionThread()
return;
}
mDRLoopStatus = false;
+ mDRWakeUpCondition.notify_one();
mDRThread.join();
}
}
@@ -291,15 +337,20 @@ void *ExynosDevice::dynamicRecompositionThreadLoop(void *data)
android_atomic_inc(&(dev->mDRThreadStatus));
while (dev->mDRLoopStatus) {
- uint32_t result = 0;
for (uint32_t i = 0; i < dev->mDisplays.size(); i++)
event_cnt[i] = display[i]->mUpdateEventCnt;
/*
- * If there is no update for more than 100ms, favor the 3D composition mode.
- * If all other conditions are met, mode will be switched to 3D composition.
+ * If there is no update for more than 5s, favor the client composition mode.
+ * If all other conditions are met, mode will be switched to client composition.
*/
- usleep(100000);
+ {
+ std::unique_lock<std::mutex> lock(dev->mDRWakeUpMutex);
+ dev->mDRWakeUpCondition.wait_for(lock, std::chrono::seconds(5));
+ if (!dev->mDRLoopStatus) {
+ break;
+ }
+ }
for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
if (display[i]->mDREnable &&
display[i]->mPlugState == true &&
@@ -307,35 +358,16 @@ void *ExynosDevice::dynamicRecompositionThreadLoop(void *data)
if (display[i]->checkDynamicReCompMode() == DEVICE_2_CLIENT) {
display[i]->mUpdateEventCnt = 0;
display[i]->setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
- result = 1;
+ dev->onRefresh(display[i]->mDisplayId);
}
}
}
- if (result) dev->onRefresh();
}
android_atomic_dec(&(dev->mDRThreadStatus));
return NULL;
}
-/**
- * @param display
- * @return ExynosDisplay
- */
-ExynosDisplay* ExynosDevice::getDisplay(uint32_t display) {
- if (mDisplays.isEmpty()) {
- ALOGE("mDisplays.size(%zu), requested display(%d)",
- mDisplays.size(), display);
- return NULL;
- }
-
- for (size_t i = 0;i < mDisplays.size(); i++) {
- if (mDisplays[i]->mDisplayId == display)
- return (ExynosDisplay*)mDisplays[i];
- }
-
- return NULL;
-}
/**
* Device Functions for HWC 2.0
@@ -459,7 +491,7 @@ int32_t ExynosDevice::registerCallback (
}
}
}
-
+ /* TODO(b/265244856): called by register callback vsync. it's only hwc2. */
if (descriptor == HWC2_CALLBACK_VSYNC)
mResourceManager->doPreProcessing();
@@ -497,16 +529,29 @@ void ExynosDevice::onHotPlug(uint32_t displayId, bool status) {
callbackFunc(callbackData, displayId,
status ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED);
}
+void ExynosDevice::onRefreshDisplays() {
+ for (auto& display : mDisplays) {
+ onRefresh(display->mDisplayId);
+ }
+}
-void ExynosDevice::onRefresh() {
+void ExynosDevice::onRefresh(uint32_t displayId) {
Mutex::Autolock lock(mDeviceCallbackMutex);
if (!isCallbackRegisteredLocked(HWC2_CALLBACK_REFRESH)) return;
+ if (!checkDisplayConnection(displayId)) return;
+
+ ExynosDisplay *display = (ExynosDisplay *)getDisplay(displayId);
+
+ if (!display->mPowerModeState.has_value() ||
+ (display->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
+ return;
+
hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_REFRESH].callbackData;
HWC2_PFN_REFRESH callbackFunc =
reinterpret_cast<HWC2_PFN_REFRESH>(mCallbackInfos[HWC2_CALLBACK_REFRESH].funcPointer);
- callbackFunc(callbackData, getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+ callbackFunc(callbackData, displayId);
}
void ExynosDevice::onVsync(uint32_t displayId, int64_t timestamp) {
@@ -599,21 +644,20 @@ void ExynosDevice::getHWCFenceDebug()
ALOGE("[HWCFenceDebug] IP_Number(%d) : Debug(%x)", i, hwcFenceDebug[i]);
}
-void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val)
-{
+void ExynosDevice::setHWCControl(uint32_t displayId, uint32_t ctrl, int32_t val) {
ExynosDisplay *exynosDisplay = NULL;
switch (ctrl) {
case HWC_CTL_FORCE_GPU:
ALOGI("%s::HWC_CTL_FORCE_GPU on/off=%d", __func__, val);
exynosHWCControl.forceGpu = (unsigned int)val;
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefresh(displayId);
break;
case HWC_CTL_WINDOW_UPDATE:
ALOGI("%s::HWC_CTL_WINDOW_UPDATE on/off=%d", __func__, val);
exynosHWCControl.windowUpdate = (unsigned int)val;
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefresh(displayId);
break;
case HWC_CTL_FORCE_PANIC:
ALOGI("%s::HWC_CTL_FORCE_PANIC on/off=%d", __func__, val);
@@ -634,33 +678,33 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val)
ALOGI("%s::HWC_CTL_SKIP_RESOURCE_ASSIGN on/off=%d", __func__, val);
exynosHWCControl.skipResourceAssign = (unsigned int)val;
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefreshDisplays();
break;
case HWC_CTL_SKIP_VALIDATE:
ALOGI("%s::HWC_CTL_SKIP_VALIDATE on/off=%d", __func__, val);
exynosHWCControl.skipValidate = (unsigned int)val;
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefreshDisplays();
break;
case HWC_CTL_DUMP_MID_BUF:
ALOGI("%s::HWC_CTL_DUMP_MID_BUF on/off=%d", __func__, val);
exynosHWCControl.dumpMidBuf = (unsigned int)val;
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefreshDisplays();
break;
case HWC_CTL_CAPTURE_READBACK:
- captureScreenWithReadback(HWC_DISPLAY_PRIMARY);
+ captureScreenWithReadback(displayId);
break;
case HWC_CTL_DISPLAY_MODE:
ALOGI("%s::HWC_CTL_DISPLAY_MODE mode=%d", __func__, val);
setDisplayMode((uint32_t)val);
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefreshDisplays();
break;
// Support DDI scalser {
case HWC_CTL_DDI_RESOLUTION_CHANGE:
ALOGI("%s::HWC_CTL_DDI_RESOLUTION_CHANGE mode=%d", __func__, val);
- exynosDisplay = (ExynosDisplay*)getDisplay(display);
+ exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
uint32_t width, height;
/* TODO: Add branch here for each resolution/index */
@@ -681,7 +725,7 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val)
exynosDisplay->setDDIScalerEnable(width, height);
}
setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
- onRefresh();
+ onRefreshDisplays();
break;
// } Support DDI scaler
case HWC_CTL_ENABLE_COMPOSITION_CROP:
@@ -690,7 +734,7 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val)
case HWC_CTL_USE_MAX_G2D_SRC:
case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
case HWC_CTL_ENABLE_EARLY_START_MPP:
- exynosDisplay = (ExynosDisplay*)getDisplay(display);
+ exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
if (exynosDisplay == NULL) {
for (uint32_t i = 0; i < mDisplays.size(); i++) {
mDisplays[i]->setHWCControl(ctrl, val);
@@ -699,11 +743,11 @@ void ExynosDevice::setHWCControl(uint32_t display, uint32_t ctrl, int32_t val)
exynosDisplay->setHWCControl(ctrl, val);
}
setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- onRefresh();
+ onRefreshDisplays();
break;
case HWC_CTL_DYNAMIC_RECOMP:
ALOGI("%s::HWC_CTL_DYNAMIC_RECOMP on/off = %d", __func__, val);
- setDynamicRecomposition((unsigned int)val);
+ setDynamicRecomposition(displayId, (unsigned int)val);
break;
case HWC_CTL_ENABLE_FENCE_TRACER:
ALOGI("%s::HWC_CTL_ENABLE_FENCE_TRACER on/off=%d", __func__, val);
@@ -728,9 +772,14 @@ void ExynosDevice::setDisplayMode(uint32_t displayMode)
exynosHWCControl.displayMode = displayMode;
}
-void ExynosDevice::setDynamicRecomposition(unsigned int on)
-{
+void ExynosDevice::setDynamicRecomposition(uint32_t displayId, unsigned int on) {
exynosHWCControl.useDynamicRecomp = on;
+ ExynosDisplay *display = getDisplay(displayId);
+ if (display) {
+ display->mDRDefault = on;
+ display->mDREnable = on;
+ onRefresh(displayId);
+ }
}
bool ExynosDevice::checkDisplayConnection(uint32_t displayId)
@@ -761,13 +810,12 @@ bool ExynosDevice::checkNonInternalConnection()
return false;
}
-void ExynosDevice::getCapabilities(uint32_t *outCount, int32_t* outCapabilities)
-{
+void ExynosDevice::getCapabilitiesLegacy(uint32_t *outCount, int32_t *outCapabilities) {
uint32_t capabilityNum = 0;
#ifdef HWC_SUPPORT_COLOR_TRANSFORM
capabilityNum++;
#endif
-#ifdef HWC_SKIP_VALIDATE
+#ifndef HWC_NO_SUPPORT_SKIP_VALIDATE
capabilityNum++;
#endif
if (outCapabilities == NULL) {
@@ -778,18 +826,38 @@ void ExynosDevice::getCapabilities(uint32_t *outCount, int32_t* outCapabilities)
ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
return;
}
-#if defined(HWC_SUPPORT_COLOR_TRANSFORM) || defined(HWC_SKIP_VALIDATE)
+#if defined(HWC_SUPPORT_COLOR_TRANSFORM) || !defined(HWC_NO_SUPPORT_SKIP_VALIDATE)
uint32_t index = 0;
#endif
#ifdef HWC_SUPPORT_COLOR_TRANSFORM
outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
#endif
-#ifdef HWC_SKIP_VALIDATE
+#ifndef HWC_NO_SUPPORT_SKIP_VALIDATE
outCapabilities[index++] = HWC2_CAPABILITY_SKIP_VALIDATE;
#endif
return;
}
+void ExynosDevice::getCapabilities(uint32_t *outCount, int32_t *outCapabilities) {
+ uint32_t capabilityNum = 0;
+#ifdef HWC_SUPPORT_COLOR_TRANSFORM
+ capabilityNum++;
+#endif
+ if (outCapabilities == NULL) {
+ *outCount = capabilityNum;
+ return;
+ }
+ if (capabilityNum != *outCount) {
+ ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
+ return;
+ }
+#if defined(HWC_SUPPORT_COLOR_TRANSFORM)
+ uint32_t index = 0;
+ outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
+#endif
+ return;
+}
+
void ExynosDevice::clearGeometryChanged()
{
mGeometryChanged = 0;
@@ -838,6 +906,7 @@ bool ExynosDevice::canSkipValidate()
}
bool ExynosDevice::validateFences(ExynosDisplay *display) {
+ std::scoped_lock lock(display->mDevice->mFenceMutex);
if (!validateFencePerFrame(display)) {
ALOGE("You should doubt fence leak!");
@@ -853,7 +922,6 @@ bool ExynosDevice::validateFences(ExynosDisplay *display) {
if (exynosHWCControl.doFenceFileDump) {
ALOGD("Fence file dump !");
- if (mFenceLogSize != 0) ALOGD("Fence file not empty!");
saveFenceTrace(display);
exynosHWCControl.doFenceFileDump = false;
}
@@ -862,20 +930,24 @@ bool ExynosDevice::validateFences(ExynosDisplay *display) {
}
void ExynosDevice::compareVsyncPeriod() {
+ /* TODO(b/265244856): to clarify what purpose of the function */
ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
ExynosDisplay *external_display = getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
mVsyncDisplayId = getDisplayId(HWC_DISPLAY_PRIMARY, 0);
if ((external_display == nullptr) ||
- (external_display->mPowerModeState == HWC2_POWER_MODE_OFF)) {
+ (!external_display->mPowerModeState.has_value() ||
+ (external_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF))) {
return;
- } else if (primary_display->mPowerModeState == HWC2_POWER_MODE_OFF) {
+ } else if (!primary_display->mPowerModeState.has_value() ||
+ (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF)) {
mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
return;
- } else if (((primary_display->mPowerModeState == HWC2_POWER_MODE_DOZE) ||
- (primary_display->mPowerModeState == HWC2_POWER_MODE_DOZE_SUSPEND)) &&
- (external_display->mVsyncPeriod >= DOZE_VSYNC_PERIOD)) { /*30fps*/
+ } else if (primary_display->mPowerModeState.has_value() &&
+ ((primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE) ||
+ (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE_SUSPEND)) &&
+ (external_display->mVsyncPeriod >= DOZE_VSYNC_PERIOD)) { /*30fps*/
mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
return;
} else if (primary_display->mVsyncPeriod <= external_display->mVsyncPeriod) {
@@ -949,6 +1021,7 @@ void ExynosDevice::captureReadbackClass::saveToFile(const String8 &fileName)
} else {
ALOGE("Fail to mmap");
}
+ fclose(fp);
} else {
ALOGE("Fail to open %s", filePath);
}
@@ -962,11 +1035,10 @@ void ExynosDevice::signalReadbackDone()
}
}
-void ExynosDevice::captureScreenWithReadback(uint32_t displayType)
-{
- ExynosDisplay *display = getDisplay(displayType);
+void ExynosDevice::captureScreenWithReadback(uint32_t displayId) {
+ ExynosDisplay *display = getDisplay(displayId);
if (display == nullptr) {
- ALOGE("There is no display(%d)", displayType);
+ ALOGE("There is no display(%d)", displayId);
return;
}
@@ -993,7 +1065,7 @@ void ExynosDevice::captureScreenWithReadback(uint32_t displayType)
}
/* Update screen */
- onRefresh();
+ onRefresh(displayId);
/* Wait for handling readback */
uint32_t waitPeriod = display->mVsyncPeriod * 3;
@@ -1036,20 +1108,22 @@ int32_t ExynosDevice::setDisplayDeviceMode(int32_t display_id, int32_t mode)
{
int32_t ret = HWC2_ERROR_NONE;
- if (display_id == HWC_DISPLAY_PRIMARY) {
- if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE) ||
- mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
- ret = mDisplays[display_id]->setPowerMode(mode);
- if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME) && ret == HWC2_ERROR_NONE) {
- onRefresh();
+ for (size_t i = 0; i < mDisplays.size(); i++) {
+ if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY && mDisplays[i]->mDisplayId == display_id) {
+ if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE) ||
+ mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
+ ret = mDisplays[i]->setPowerMode(mode);
+ if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME) &&
+ ret == HWC2_ERROR_NONE) {
+ onRefresh(display_id);
+ }
+ return ret;
+ } else {
+ return HWC2_ERROR_UNSUPPORTED;
}
- return ret;
- } else {
- return HWC2_ERROR_UNSUPPORTED;
}
- } else {
- return HWC2_ERROR_UNSUPPORTED;
}
+ return HWC2_ERROR_UNSUPPORTED;
}
int32_t ExynosDevice::setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source) {
@@ -1087,63 +1161,6 @@ void ExynosDevice::setVBlankOffDelay(int vblankOffDelay) {
writeIntToFile(kVblankOffDelayPath, vblankOffDelay);
}
-bool ExynosDevice::isLbeSupported() {
- return mLbeSupported;
-}
-
-bool ExynosDevice::isColorCalibratedByDevice() {
- ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- return display->isColorCalibratedByDevice();
-}
-
-void ExynosDevice::setLbeState(LbeState state) {
- if (mLbeSupported) {
- ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- primary_display->setLbeState(state);
- }
-}
-
-void ExynosDevice::setLbeAmbientLight(int value) {
- if (mLbeSupported) {
- ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- primary_display->setLbeAmbientLight(value);
- }
-}
-
-LbeState ExynosDevice::getLbeState() {
- if (mLbeSupported) {
- ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- return primary_display->getLbeState();
- }
- return LbeState::OFF;
-}
-
-bool ExynosDevice::isLhbmSupported() {
- ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- return display->mBrightnessController->isLhbmSupported();
-}
-
-int32_t ExynosDevice::setLhbmState(bool enabled) {
- if (isLhbmSupported()) {
- ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- return display->setLhbmState(enabled);
- }
- return -1;
-}
-
-bool ExynosDevice::getLhbmState() {
- if (isLhbmSupported()) {
- ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- return display->getLhbmState();
- }
- return false;
-}
-
-PanelCalibrationStatus ExynosDevice::getPanelCalibrationStatus() {
- auto display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- return display->getPanelCalibrationStatus();
-}
-
uint32_t ExynosDevice::getWindowPlaneNum()
{
/*
@@ -1179,31 +1196,6 @@ uint64_t ExynosDevice::getSpecialPlaneAttr(uint32_t index)
return mDeviceInterface->getSPPChAttr(index);
}
-int ExynosDevice::setMinIdleRefreshRate(const int fps) {
- ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- if (display) {
- return display->setMinIdleRefreshRate(fps);
- }
- return BAD_VALUE;
-}
-
-int ExynosDevice::setRefreshRateThrottle(const int delayMs) {
- if (delayMs < 0) {
- ALOGE("%s fail: delayMs(%d) is less than 0", __func__, delayMs);
- return BAD_VALUE;
- }
-
- ExynosDisplay *display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
- if (display) {
- return display
- ->setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::milliseconds(delayMs))
- .count(),
- DispIdleTimerRequester::PIXEL_DISP);
- }
- return BAD_VALUE;
-}
-
int32_t ExynosDevice::registerHwc3Callback(uint32_t descriptor, hwc2_callback_data_t callbackData,
hwc2_function_pointer_t point) {
Mutex::Autolock lock(mDeviceCallbackMutex);
@@ -1227,3 +1219,19 @@ void ExynosDevice::onVsyncIdle(hwc2_display_t displayId) {
hwc2_display_t hwcDisplay)>(callbackInfo.funcPointer);
callbackFunc(callbackInfo.callbackData, displayId);
}
+
+void ExynosDevice::onRefreshRateChangedDebug(hwc2_display_t displayId, uint32_t vsyncPeriod) {
+ Mutex::Autolock lock(mDeviceCallbackMutex);
+ const auto &refreshRateCallback =
+ mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug);
+
+ if (refreshRateCallback == mHwc3CallbackInfos.end()) return;
+
+ const auto &callbackInfo = refreshRateCallback->second;
+ if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return;
+
+ auto callbackFunc =
+ reinterpret_cast<void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
+ hwc2_vsync_period_t)>(callbackInfo.funcPointer);
+ callbackFunc(callbackInfo.callbackData, displayId, vsyncPeriod);
+}
diff --git a/libhwc2.1/libdevice/ExynosDevice.h b/libhwc2.1/libdevice/ExynosDevice.h
index 1dd1145..35eb947 100644
--- a/libhwc2.1/libdevice/ExynosDevice.h
+++ b/libhwc2.1/libdevice/ExynosDevice.h
@@ -17,6 +17,7 @@
#ifndef _EXYNOSDEVICE_H
#define _EXYNOSDEVICE_H
+#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
#include <aidl/com/google/hardware/pixel/display/BnDisplay.h>
#include <cutils/atomic.h>
#include <displaycolor/displaycolor.h>
@@ -35,6 +36,7 @@
#include <map>
#include <thread>
+#include "ExynosDeviceInterface.h"
#include "ExynosHWC.h"
#include "ExynosHWCHelper.h"
#include "ExynosHWCModule.h"
@@ -61,6 +63,7 @@ using HbmState = ::aidl::com::google::hardware::pixel::display::HbmState;
using LbeState = ::aidl::com::google::hardware::pixel::display::LbeState;
using PanelCalibrationStatus = ::aidl::com::google::hardware::pixel::display::PanelCalibrationStatus;
+using OverlayProperties = aidl::android::hardware::graphics::composer3::OverlayProperties;
using namespace android;
struct exynos_callback_info_t {
@@ -141,10 +144,8 @@ enum {
GEOMETRY_ERROR_CASE = 1ULL << 63,
};
-class ExynosDevice;
class ExynosDisplay;
class ExynosResourceManager;
-class ExynosDeviceInterface;
class ExynosDevice {
public:
@@ -153,6 +154,7 @@ class ExynosDevice {
* Display list that managed by Device.
*/
android::Vector< ExynosDisplay* > mDisplays;
+ std::map<uint32_t, ExynosDisplay *> mDisplayMap;
int mNumVirtualDisplay;
@@ -174,6 +176,8 @@ class ExynosDevice {
volatile int32_t mDRThreadStatus;
std::atomic<bool> mDRLoopStatus;
bool mPrimaryBlank;
+ std::mutex mDRWakeUpMutex;
+ std::condition_variable mDRWakeUpCondition;
/**
* Callback informations those are used by SurfaceFlinger.
@@ -204,7 +208,8 @@ class ExynosDevice {
uint32_t mDisplayMode;
// Variable for fence tracer
- std::map<int, HwcFenceInfo> mFenceInfos;
+ std::map<int, HwcFenceInfo> mFenceInfos GUARDED_BY(mFenceMutex);
+ std::mutex mFenceMutex;
/**
* This will be initialized with differnt class
@@ -232,7 +237,7 @@ class ExynosDevice {
/**
* @param display
*/
- ExynosDisplay* getDisplay(uint32_t display);
+ ExynosDisplay* getDisplay(uint32_t display) { return mDisplayMap[display]; }
/**
* Device Functions for HWC 2.0
@@ -278,7 +283,9 @@ class ExynosDevice {
int32_t descriptor, hwc2_callback_data_t callbackData, hwc2_function_pointer_t point);
bool isCallbackAvailable(int32_t descriptor);
void onHotPlug(uint32_t displayId, bool status);
- void onRefresh();
+ void onRefresh(uint32_t displayId);
+ void onRefreshDisplays();
+
void onVsync(uint32_t displayId, int64_t timestamp);
bool onVsync_2_4(uint32_t displayId, int64_t timestamp, uint32_t vsyncPeriod);
void onVsyncPeriodTimingChanged(uint32_t displayId,
@@ -292,10 +299,11 @@ class ExynosDevice {
void setDisplayMode(uint32_t displayMode);
bool checkDisplayConnection(uint32_t displayId);
bool checkNonInternalConnection();
+ void getCapabilitiesLegacy(uint32_t *outCount, int32_t *outCapabilities);
void getCapabilities(uint32_t *outCount, int32_t* outCapabilities);
void setGeometryChanged(uint64_t changedBit) { mGeometryChanged|= changedBit;};
void clearGeometryChanged();
- void setDynamicRecomposition(unsigned int on);
+ void setDynamicRecomposition(uint32_t displayId, unsigned int on);
bool canSkipValidate();
bool validateFences(ExynosDisplay *display);
void compareVsyncPeriod();
@@ -332,6 +340,13 @@ class ExynosDevice {
int32_t registerHwc3Callback(uint32_t descriptor, hwc2_callback_data_t callbackData,
hwc2_function_pointer_t point);
void onVsyncIdle(hwc2_display_t displayId);
+ bool isDispOffAsyncSupported() { return mDisplayOffAsync; };
+ bool hasOtherDisplayOn(ExynosDisplay *display);
+ virtual int32_t getOverlaySupport([[maybe_unused]] OverlayProperties* caps){
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
+ void onRefreshRateChangedDebug(hwc2_display_t displayId, uint32_t vsyncPeriod);
protected:
void initDeviceInterface(uint32_t interfaceType);
@@ -345,29 +360,13 @@ class ExynosDevice {
bool isCallbackRegisteredLocked(int32_t descriptor);
public:
- bool isLbeSupported();
- void setLbeState(LbeState state);
- void setLbeAmbientLight(int value);
- LbeState getLbeState();
-
- bool isLhbmSupported();
- int32_t setLhbmState(bool enabled);
- bool getLhbmState();
- int setMinIdleRefreshRate(const int fps);
- int setRefreshRateThrottle(const int delayMs);
-
- bool isColorCalibratedByDevice();
-
- PanelCalibrationStatus getPanelCalibrationStatus();
-
- public:
void enterToTUI() { mIsInTUI = true; };
void exitFromTUI() { mIsInTUI = false; };
bool isInTUI() { return mIsInTUI; };
private:
- bool mLbeSupported;
bool mIsInTUI;
+ bool mDisplayOffAsync;
};
#endif //_EXYNOSDEVICE_H
diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp
index 78f65f2..ffd9cd5 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.cpp
+++ b/libhwc2.1/libdevice/ExynosDisplay.cpp
@@ -31,6 +31,7 @@
#include <sys/ioctl.h>
#include <utils/CallStack.h>
+#include <charconv>
#include <future>
#include <map>
@@ -55,10 +56,13 @@ using ::aidl::google::hardware::power::extension::pixel::IPowerExt;
extern struct exynos_hwc_control exynosHWCControl;
extern struct update_time_info updateTimeInfo;
+constexpr float kDynamicRecompFpsThreshold = 1.0 / 5.0; // 1 frame update per 5 second
+
constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
constexpr int64_t nsecsIdleHintTimeout = std::chrono::nanoseconds(100ms).count();
-ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker()
+ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker(uint32_t displayId,
+ const String8 &displayTraceName)
: Worker("DisplayHints", HAL_PRIORITY_URGENT_DISPLAY),
mNeedUpdateRefreshRateHint(false),
mLastRefreshRateHint(0),
@@ -67,12 +71,23 @@ ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker()
mIdleHintDeadlineTime(0),
mIdleHintSupportIsChecked(false),
mIdleHintIsSupported(false),
+ mDisplayTraceName(displayTraceName),
mPowerModeState(HWC2_POWER_MODE_OFF),
mVsyncPeriod(16666666),
+ mConnectRetryCount(0),
mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)),
mPowerHalExtAidl(nullptr),
mPowerHalAidl(nullptr),
- mPowerHintSession(nullptr) {}
+ mPowerHintSession(nullptr) {
+ if (property_get_bool("vendor.display.powerhal_hint_per_display", false)) {
+ std::string displayIdStr = std::to_string(displayId);
+ mIdleHintStr = "DISPLAY_" + displayIdStr + "_IDLE";
+ mRefreshRateHintPrefixStr = "DISPLAY_" + displayIdStr + "_";
+ } else {
+ mIdleHintStr = "DISPLAY_IDLE";
+ mRefreshRateHintPrefixStr = "REFRESH_";
+ }
+}
ExynosDisplay::PowerHalHintWorker::~PowerHalHintWorker() {
Exit();
@@ -99,7 +114,8 @@ int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHal() {
mPowerHalAidl = IPower::fromBinder(pwBinder);
if (!mPowerHalAidl) {
- ALOGE("failed to connect power HAL");
+ ALOGE("failed to connect power HAL (retry %u)", mConnectRetryCount);
+ mConnectRetryCount++;
return -EINVAL;
}
@@ -110,10 +126,12 @@ int32_t ExynosDisplay::PowerHalHintWorker::connectPowerHal() {
if (!mPowerHalExtAidl) {
mPowerHalAidl = nullptr;
- ALOGE("failed to connect power HAL extension");
+ ALOGE("failed to connect power HAL extension (retry %u)", mConnectRetryCount);
+ mConnectRetryCount++;
return -EINVAL;
}
+ mConnectRetryCount = 0;
AIBinder_linkToDeath(pwExtBinder.get(), mDeathRecipient.get(), reinterpret_cast<void *>(this));
// ensure the hint session is recreated every time powerhal is recreated
mPowerHintSession = nullptr;
@@ -179,10 +197,15 @@ int32_t ExynosDisplay::PowerHalHintWorker::sendPowerHalExtHint(const std::string
int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(int refreshRate) {
int32_t ret = NO_ERROR;
+
+ if (!isPowerHalExist()) {
+ return -EOPNOTSUPP;
+ }
const auto its = mRefreshRateHintSupportMap.find(refreshRate);
if (its == mRefreshRateHintSupportMap.end()) {
/* check new hint */
- std::string refreshRateHintStr = "REFRESH_" + std::to_string(refreshRate) + "FPS";
+ std::string refreshRateHintStr =
+ mRefreshRateHintPrefixStr + std::to_string(refreshRate) + "FPS";
ret = checkPowerHalExtHintSupport(refreshRateHintStr);
if (ret == NO_ERROR || ret == -EOPNOTSUPP) {
mRefreshRateHintSupportMap[refreshRate] = (ret == NO_ERROR);
@@ -200,7 +223,7 @@ int32_t ExynosDisplay::PowerHalHintWorker::checkRefreshRateHintSupport(int refre
}
int32_t ExynosDisplay::PowerHalHintWorker::sendRefreshRateHint(int refreshRate, bool enabled) {
- std::string hintStr = "REFRESH_" + std::to_string(refreshRate) + "FPS";
+ std::string hintStr = mRefreshRateHintPrefixStr + std::to_string(refreshRate) + "FPS";
int32_t ret = sendPowerHalExtHint(hintStr, enabled);
if (ret == -ENOTCONN) {
/* Reset the hints when binder failure occurs */
@@ -250,6 +273,11 @@ int32_t ExynosDisplay::PowerHalHintWorker::updateRefreshRateHintInternal(
int32_t ExynosDisplay::PowerHalHintWorker::checkIdleHintSupport(void) {
int32_t ret = NO_ERROR;
+
+ if (!isPowerHalExist()) {
+ return -EOPNOTSUPP;
+ }
+
Lock();
if (mIdleHintSupportIsChecked) {
ret = mIdleHintIsSupported ? NO_ERROR : -EOPNOTSUPP;
@@ -258,7 +286,7 @@ int32_t ExynosDisplay::PowerHalHintWorker::checkIdleHintSupport(void) {
}
Unlock();
- ret = checkPowerHalExtHintSupport("DISPLAY_IDLE");
+ ret = checkPowerHalExtHintSupport(mIdleHintStr);
Lock();
if (ret == NO_ERROR) {
mIdleHintIsSupported = true;
@@ -281,6 +309,10 @@ int32_t ExynosDisplay::PowerHalHintWorker::checkPowerHintSessionSupport() {
return *(sSharedDisplayData.hintSessionSupported);
}
+ if (!isPowerHalExist()) {
+ return -EOPNOTSUPP;
+ }
+
if (connectPowerHal() != NO_ERROR) {
ALOGW("Error connecting to the PowerHAL");
return -EINVAL;
@@ -315,10 +347,10 @@ int32_t ExynosDisplay::PowerHalHintWorker::updateIdleHint(int64_t deadlineTime,
bool enableIdleHint =
(deadlineTime < systemTime(SYSTEM_TIME_MONOTONIC) && CC_LIKELY(deadlineTime > 0));
- ATRACE_INT("HWCIdleHintTimer:", enableIdleHint);
+ DISPLAY_ATRACE_INT("HWCIdleHintTimer", enableIdleHint);
if (mIdleHintIsEnabled != enableIdleHint || forceUpdate) {
- ret = sendPowerHalExtHint("DISPLAY_IDLE", enableIdleHint);
+ ret = sendPowerHalExtHint(mIdleHintStr, enableIdleHint);
if (ret == NO_ERROR) {
mIdleHintIsEnabled = enableIdleHint;
}
@@ -343,7 +375,6 @@ void ExynosDisplay::PowerHalHintWorker::forceUpdateHints(void) {
int32_t ExynosDisplay::PowerHalHintWorker::sendActualWorkDuration() {
Lock();
if (mPowerHintSession == nullptr) {
- ALOGW("Cannot send actual work duration, power hint session not running");
Unlock();
return -EINVAL;
}
@@ -382,7 +413,6 @@ int32_t ExynosDisplay::PowerHalHintWorker::updateTargetWorkDuration() {
}
if (mPowerHintSession == nullptr) {
- ALOGW("Cannot send target work duration, power hint session not running");
return -EINVAL;
}
@@ -433,13 +463,13 @@ void ExynosDisplay::PowerHalHintWorker::signalActualWorkDuration(nsecs_t actualD
WorkDuration duration = {.durationNanos = reportedDurationNs, .timeStampNanos = systemTime()};
if (sTraceHintSessionData) {
- ATRACE_INT64("Measured duration", actualDurationNanos);
- ATRACE_INT64("Target error term", mTargetWorkDuration - actualDurationNanos);
+ DISPLAY_ATRACE_INT64("Measured duration", actualDurationNanos);
+ DISPLAY_ATRACE_INT64("Target error term", mTargetWorkDuration - actualDurationNanos);
- ATRACE_INT64("Reported duration", reportedDurationNs);
- ATRACE_INT64("Reported target", mLastTargetDurationReported);
- ATRACE_INT64("Reported target error term",
- mLastTargetDurationReported - reportedDurationNs);
+ DISPLAY_ATRACE_INT64("Reported duration", reportedDurationNs);
+ DISPLAY_ATRACE_INT64("Reported target", mLastTargetDurationReported);
+ DISPLAY_ATRACE_INT64("Reported target error term",
+ mLastTargetDurationReported - reportedDurationNs);
}
ALOGV("Sending actual work duration of: %" PRId64 " on reported target: %" PRId64
" with error: %" PRId64,
@@ -463,12 +493,12 @@ void ExynosDisplay::PowerHalHintWorker::signalTargetWorkDuration(nsecs_t targetD
Lock();
mTargetWorkDuration = targetDurationNanos - kTargetSafetyMargin.count();
- if (sTraceHintSessionData) ATRACE_INT64("Time target", mTargetWorkDuration);
+ if (sTraceHintSessionData) DISPLAY_ATRACE_INT64("Time target", mTargetWorkDuration);
bool shouldSignal = false;
if (!sNormalizeTarget) {
shouldSignal = needUpdateTargetWorkDurationLocked();
if (shouldSignal && mActualWorkDuration.has_value() && sTraceHintSessionData) {
- ATRACE_INT64("Target error term", *mActualWorkDuration - mTargetWorkDuration);
+ DISPLAY_ATRACE_INT64("Target error term", *mActualWorkDuration - mTargetWorkDuration);
}
}
Unlock();
@@ -938,9 +968,10 @@ String8 ExynosCompositionInfo::getTypeStr()
}
}
-ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
- : mDisplayId(HWC_DISPLAY_PRIMARY),
- mType(HWC_NUM_DISPLAY_TYPES),
+ExynosDisplay::ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice *device,
+ const std::string &displayName)
+ : mDisplayId(getDisplayId(type, index)),
+ mType(type),
mIndex(index),
mDeconNodeName(""),
mXres(1440),
@@ -950,17 +981,19 @@ ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
mVsyncPeriod(16666666),
mBtsVsyncPeriod(16666666),
mDevice(device),
- mDisplayName(""),
+ mDisplayName(displayName.c_str()),
+ mDisplayTraceName(String8::format("%s(%d)", displayName.c_str(), mDisplayId)),
mPlugState(false),
mHasSingleBuffer(false),
mResourceManager(NULL),
mClientCompositionInfo(COMPOSITION_CLIENT),
mExynosCompositionInfo(COMPOSITION_EXYNOS),
mGeometryChanged(0x0),
+ mBufferUpdates(0),
mRenderingState(RENDERING_STATE_NONE),
mHWCRenderingState(RENDERING_STATE_NONE),
mDisplayBW(0),
- mDynamicReCompMode(NO_MODE_SWITCH),
+ mDynamicReCompMode(CLIENT_2_DEVICE),
mDREnable(false),
mDRDefault(false),
mLastFpsTime(0),
@@ -990,7 +1023,12 @@ ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
mSkipFrame(false),
mVsyncPeriodChangeConstraints{systemTime(SYSTEM_TIME_MONOTONIC), 0},
mVsyncAppliedTimeLine{false, 0, systemTime(SYSTEM_TIME_MONOTONIC)},
- mConfigRequestState(hwc_request_state_t::SET_CONFIG_STATE_NONE) {
+ mConfigRequestState(hwc_request_state_t::SET_CONFIG_STATE_DONE),
+ mPowerHalHint(mDisplayId, mDisplayTraceName),
+ mErrLogFileWriter(2, ERR_LOG_SIZE),
+ mDebugDumpFileWriter(10, 1, ".dump"),
+ mFenceFileWriter(2, FENCE_ERR_LOG_SIZE),
+ mOperationRateManager(nullptr) {
mDisplayControl.enableCompositionCrop = true;
mDisplayControl.enableExynosCompositionOptimization = true;
mDisplayControl.enableClientCompositionOptimization = true;
@@ -1002,7 +1040,8 @@ ExynosDisplay::ExynosDisplay(uint32_t index, ExynosDevice *device)
mDisplayConfigs.clear();
- mPowerModeState = HWC2_POWER_MODE_OFF;
+ mPowerModeState = std::nullopt;
+
mVsyncState = HWC2_VSYNC_DISABLE;
/* TODO : Exception handling here */
@@ -1079,7 +1118,7 @@ void ExynosDisplay::initDisplay() {
mGeometryChanged = 0x0;
mRenderingState = RENDERING_STATE_NONE;
mDisplayBW = 0;
- mDynamicReCompMode = NO_MODE_SWITCH;
+ mDynamicReCompMode = CLIENT_2_DEVICE;
mCursorIndex = -1;
mDpuData.reset();
@@ -1134,6 +1173,7 @@ int32_t ExynosDisplay::destroyLayer(hwc2_layer_t outLayer) {
}
mDisplayInterface->destroyLayer(layer);
+ layer->resetAssignedResource();
delete layer;
@@ -1150,6 +1190,7 @@ int32_t ExynosDisplay::destroyLayer(hwc2_layer_t outLayer) {
* @return void
*/
void ExynosDisplay::destroyLayers() {
+ Mutex::Autolock lock(mDRMutex);
for (uint32_t index = 0; index < mLayers.size();) {
ExynosLayer *layer = mLayers[index];
mLayers.removeAt(index);
@@ -1182,6 +1223,7 @@ ExynosLayer *ExynosDisplay::checkLayer(hwc2_layer_t addr) {
}
void ExynosDisplay::checkIgnoreLayers() {
+ Mutex::Autolock lock(mDRMutex);
for (auto it = mIgnoreLayers.begin(); it != mIgnoreLayers.end();) {
ExynosLayer *layer = *it;
if ((layer->mLayerFlag & EXYNOS_HWC_IGNORE_LAYER) == 0) {
@@ -1266,7 +1308,7 @@ void ExynosDisplay::doPreProcessing() {
/* Set any flag to mGeometryChanged */
setGeometryChanged(GEOMETRY_DEVICE_SCENARIO_CHANGED);
}
-#ifndef HWC_SKIP_VALIDATE
+#ifdef HWC_NO_SUPPORT_SKIP_VALIDATE
if (mDevice->checkNonInternalConnection()) {
/* Set any flag to mGeometryChanged */
mDevice->mGeometryChanged = 0x10;
@@ -1285,16 +1327,15 @@ int ExynosDisplay::checkLayerFps() {
if (mDisplayControl.handleLowFpsLayers == false)
return NO_ERROR;
+ Mutex::Autolock lock(mDRMutex);
+
for (size_t i=0; i < mLayers.size(); i++) {
- if ((mLayers[i]->mOverlayPriority < ePriorityHigh) &&
- (mLayers[i]->getFps() < LOW_FPS_THRESHOLD)) {
- mLowFpsLayerInfo.addLowFpsLayer(i);
- } else {
- if (mLowFpsLayerInfo.mHasLowFpsLayer == true)
- break;
- else
- continue;
- }
+ if ((mLayers[i]->mOverlayPriority < ePriorityHigh) &&
+ (mLayers[i]->getFps() < LOW_FPS_THRESHOLD)) {
+ mLowFpsLayerInfo.addLowFpsLayer(i);
+ } else if (mLowFpsLayerInfo.mHasLowFpsLayer == true) {
+ break;
+ }
}
/* There is only one low fps layer, Overlay is better in this case */
if ((mLowFpsLayerInfo.mHasLowFpsLayer == true) &&
@@ -1304,91 +1345,92 @@ int ExynosDisplay::checkLayerFps() {
return NO_ERROR;
}
+int ExynosDisplay::switchDynamicReCompMode(dynamic_recomp_mode mode) {
+ if (mDynamicReCompMode == mode) return NO_MODE_SWITCH;
+
+ ATRACE_INT("Force client composition by DR", (mode == DEVICE_2_CLIENT));
+ mDynamicReCompMode = mode;
+ setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
+ return mode;
+}
+
/**
* @return int
*/
int ExynosDisplay::checkDynamicReCompMode() {
- unsigned int updateFps = 0;
- unsigned int lcd_size = mXres * mYres;
- uint64_t TimeStampDiff;
- uint64_t w = 0, h = 0, incomingPixels = 0;
- uint64_t maxFps = 0, layerFps = 0;
-
+ ATRACE_CALL();
Mutex::Autolock lock(mDRMutex);
if (!exynosHWCControl.useDynamicRecomp) {
mLastModeSwitchTimeStamp = 0;
- mDynamicReCompMode = NO_MODE_SWITCH;
- return 0;
+ return switchDynamicReCompMode(CLIENT_2_DEVICE);
}
/* initialize the Timestamps */
if (!mLastModeSwitchTimeStamp) {
mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
- mDynamicReCompMode = NO_MODE_SWITCH;
- return 0;
+ return switchDynamicReCompMode(CLIENT_2_DEVICE);
}
- /* If video layer is there, skip the mode switch */
+ /* Avoid to use DEVICE_2_CLIENT if there's a layer with priority >= ePriorityHigh such as:
+ * front buffer, video layer, HDR, DRM layer, etc.
+ */
for (size_t i = 0; i < mLayers.size(); i++) {
if ((mLayers[i]->mOverlayPriority >= ePriorityHigh) ||
mLayers[i]->mPreprocessedInfo.preProcessed) {
- if (mDynamicReCompMode != DEVICE_2_CLIENT) {
- return 0;
- } else {
- mDynamicReCompMode = CLIENT_2_DEVICE;
+ auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
+ if (ret) {
mUpdateCallCnt = 0;
mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] GLES_2_HWC by video layer");
- setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
- return CLIENT_2_DEVICE;
}
+ return ret;
}
}
+ unsigned int incomingPixels = 0;
for (size_t i = 0; i < mLayers.size(); i++) {
- w = WIDTH(mLayers[i]->mPreprocessedInfo.displayFrame);
- h = HEIGHT(mLayers[i]->mPreprocessedInfo.displayFrame);
+ auto w = WIDTH(mLayers[i]->mPreprocessedInfo.displayFrame);
+ auto h = HEIGHT(mLayers[i]->mPreprocessedInfo.displayFrame);
incomingPixels += w * h;
}
/* Mode Switch is not required if total pixels are not more than the threshold */
- if (incomingPixels <= lcd_size) {
- if (mDynamicReCompMode != DEVICE_2_CLIENT) {
- return 0;
- } else {
- mDynamicReCompMode = CLIENT_2_DEVICE;
+ unsigned int lcdSize = mXres * mYres;
+ if (incomingPixels <= lcdSize) {
+ auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
+ if (ret) {
mUpdateCallCnt = 0;
mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] GLES_2_HWC by BW check");
- setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
- return CLIENT_2_DEVICE;
}
+ return ret;
}
/*
* There will be at least one composition call per one minute (because of time update)
- * To minimize the analysis overhead, just analyze it once in a second
+ * To minimize the analysis overhead, just analyze it once in 5 second
*/
- TimeStampDiff = systemTime(SYSTEM_TIME_MONOTONIC) - mLastModeSwitchTimeStamp;
+ auto timeStampDiff = systemTime(SYSTEM_TIME_MONOTONIC) - mLastModeSwitchTimeStamp;
/*
- * previous CompModeSwitch was CLIENT_2_DEVICE: check fps every 250ms from mLastModeSwitchTimeStamp
+ * previous CompModeSwitch was CLIENT_2_DEVICE: check fps after 5s from mLastModeSwitchTimeStamp
* previous CompModeSwitch was DEVICE_2_CLIENT: check immediately
*/
- if ((mDynamicReCompMode != DEVICE_2_CLIENT) && (TimeStampDiff < (VSYNC_INTERVAL * 15)))
+ if ((mDynamicReCompMode != DEVICE_2_CLIENT) && (timeStampDiff < kLayerFpsStableTimeNs))
return 0;
mLastModeSwitchTimeStamp = mLastUpdateTimeStamp;
+ float updateFps = 0;
if ((mUpdateEventCnt != 1) &&
(mDynamicReCompMode == DEVICE_2_CLIENT) && (mUpdateCallCnt == 1)) {
DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] first frame after DEVICE_2_CLIENT");
- updateFps = HWC_FPS_TH;
+ updateFps = kDynamicRecompFpsThreshold + 1;
} else {
+ float maxFps = 0;
for (uint32_t i = 0; i < mLayers.size(); i++) {
- layerFps = mLayers[i]->getFps();
- if (maxFps < layerFps)
- maxFps = layerFps;
+ float layerFps = mLayers[i]->checkFps(/* increaseCount */ false);
+ if (maxFps < layerFps) maxFps = layerFps;
}
updateFps = maxFps;
}
@@ -1396,26 +1438,22 @@ int ExynosDisplay::checkDynamicReCompMode() {
/*
* FPS estimation.
- * If FPS is lower than HWC_FPS_TH, try to switch the mode to GLES
+ * If FPS is lower than kDynamicRecompFpsThreshold, try to switch the mode to GLES
*/
- if (updateFps < HWC_FPS_TH) {
- if (mDynamicReCompMode != DEVICE_2_CLIENT) {
- mDynamicReCompMode = DEVICE_2_CLIENT;
- DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] DEVICE_2_CLIENT by low FPS(%d)", updateFps);
- setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
- return DEVICE_2_CLIENT;
- } else {
- return 0;
+ if (updateFps < kDynamicRecompFpsThreshold) {
+ auto ret = switchDynamicReCompMode(DEVICE_2_CLIENT);
+ if (ret) {
+ DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] DEVICE_2_CLIENT by low FPS(%.2f)",
+ updateFps);
}
+ return ret;
} else {
- if (mDynamicReCompMode == DEVICE_2_CLIENT) {
- mDynamicReCompMode = CLIENT_2_DEVICE;
- DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] CLIENT_2_HWC by high FPS(%d)", updateFps);
- setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
- return CLIENT_2_DEVICE;
- } else {
- return 0;
+ auto ret = switchDynamicReCompMode(CLIENT_2_DEVICE);
+ if (ret) {
+ DISPLAY_LOGD(eDebugDynamicRecomp, "[DYNAMIC_RECOMP] CLIENT_2_HWC by high FPS((%.2f)",
+ updateFps);
}
+ return ret;
}
return 0;
@@ -1440,11 +1478,16 @@ void ExynosDisplay::setGeometryChanged(uint64_t changedBit) {
void ExynosDisplay::clearGeometryChanged()
{
mGeometryChanged = 0;
+ mBufferUpdates = 0;
for (size_t i=0; i < mLayers.size(); i++) {
mLayers[i]->clearGeometryChanged();
}
}
+bool ExynosDisplay::isFrameUpdate() {
+ return mGeometryChanged > 0 || mBufferUpdates > 0;
+}
+
int ExynosDisplay::handleStaticLayers(ExynosCompositionInfo& compositionInfo)
{
if (compositionInfo.mType != COMPOSITION_CLIENT)
@@ -1581,7 +1624,7 @@ bool ExynosDisplay::skipStaticLayerChanged(ExynosCompositionInfo& compositionInf
}
void ExynosDisplay::requestLhbm(bool on) {
- mDevice->onRefresh();
+ mDevice->onRefresh(mDisplayId);
if (mBrightnessController) {
mBrightnessController->processLocalHbm(on);
}
@@ -1666,11 +1709,14 @@ int ExynosDisplay::skipStaticLayers(ExynosCompositionInfo& compositionInfo)
return NO_ERROR;
}
-bool ExynosDisplay::skipSignalIdleForVideoLayer(void) {
- /* ignore the frame update in case we have video layer but ui layer is not updated */
+bool ExynosDisplay::skipSignalIdle(void) {
for (size_t i = 0; i < mLayers.size(); i++) {
- if (!mLayers[i]->isLayerFormatYuv() &&
- mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer) {
+ // Frame update for refresh rate overlay indicator layer can be ignored
+ if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
+ continue;
+ // Frame update for video layer can be ignored
+ if (mLayers[i]->isLayerFormatYuv()) continue;
+ if (mLayers[i]->mLastLayerBuffer != mLayers[i]->mLayerBuffer) {
return false;
}
}
@@ -2378,31 +2424,15 @@ int ExynosDisplay::setWinConfigData() {
return 0;
}
-void ExynosDisplay::printDebugInfos(String8 &reason)
-{
- FILE *pFile = NULL;
+void ExynosDisplay::printDebugInfos(String8 &reason) {
struct timeval tv;
gettimeofday(&tv, NULL);
reason.appendFormat("errFrameNumber: %" PRId64 " time:%s\n", mErrorFrameCount,
getLocalTimeStr(tv).string());
ALOGD("%s", reason.string());
- if (mErrorFrameCount < HWC_PRINT_FRAME_NUM) {
- char filePath[128];
- sprintf(filePath, "%s/%s_hwc_debug%d.dump", ERROR_LOG_PATH0, mDisplayName.string(), (int)mErrorFrameCount);
- pFile = fopen(filePath, "wb");
- if (pFile == NULL) {
- ALOGE("Fail to open file %s, error: %s", filePath, strerror(errno));
- sprintf(filePath, "%s/%s_hwc_debug%d.dump", ERROR_LOG_PATH1, mDisplayName.string(), (int)mErrorFrameCount);
- pFile = fopen(filePath, "wb");
- }
- if (pFile == NULL) {
- ALOGE("Fail to open file %s, error: %s", filePath, strerror(errno));
- } else {
- ALOGI("%s was created", filePath);
- fwrite(reason.string(), 1, reason.size(), pFile);
- }
- }
+ bool fileOpened = mDebugDumpFileWriter.chooseOpenedFile();
+ mDebugDumpFileWriter.write(reason);
mErrorFrameCount++;
android::String8 result;
@@ -2414,24 +2444,20 @@ void ExynosDisplay::printDebugInfos(String8 &reason)
clientCompInfo.dump(result);
exynosCompInfo.dump(result);
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
result.appendFormat("======================= dump exynos layers (%zu) ================================\n",
mLayers.size());
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
for (uint32_t i = 0; i < mLayers.size(); i++) {
ExynosLayer *layer = mLayers[i];
layer->printLayer();
- if (pFile != NULL) {
+ if (fileOpened) {
layer->dump(result);
- fwrite(result.string(), 1, result.size(), pFile);
+ mDebugDumpFileWriter.write(result);
result.clear();
}
}
@@ -2440,16 +2466,14 @@ void ExynosDisplay::printDebugInfos(String8 &reason)
result.appendFormat("======================= dump ignore layers (%zu) ================================\n",
mIgnoreLayers.size());
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
for (uint32_t i = 0; i < mIgnoreLayers.size(); i++) {
ExynosLayer *layer = mIgnoreLayers[i];
layer->printLayer();
- if (pFile != NULL) {
+ if (fileOpened) {
layer->dump(result);
- fwrite(result.string(), 1, result.size(), pFile);
+ mDebugDumpFileWriter.write(result);
result.clear();
}
}
@@ -2457,23 +2481,19 @@ void ExynosDisplay::printDebugInfos(String8 &reason)
result.appendFormat("============================= dump win configs ===================================\n");
ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ mDebugDumpFileWriter.write(result);
result.clear();
for (size_t i = 0; i < mDpuData.configs.size(); i++) {
ALOGD("config[%zu]", i);
printConfig(mDpuData.configs[i]);
- if (pFile != NULL) {
+ if (fileOpened) {
result.appendFormat("config[%zu]\n", i);
dumpConfig(result, mDpuData.configs[i]);
- fwrite(result.string(), 1, result.size(), pFile);
+ mDebugDumpFileWriter.write(result);
result.clear();
}
}
- if (pFile != NULL) {
- fclose(pFile);
- }
+ mDebugDumpFileWriter.flush();
}
int32_t ExynosDisplay::validateWinConfigData()
@@ -3015,6 +3035,9 @@ int32_t ExynosDisplay::getLayerCompositionTypeForValidationType(uint32_t layerIn
} else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_SOLID_COLOR) &&
(mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
type = HWC2_COMPOSITION_SOLID_COLOR;
+ } else if ((mLayers[layerIndex]->mCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR) &&
+ (mLayers[layerIndex]->mValidateCompositionType == HWC2_COMPOSITION_DEVICE)) {
+ type = HWC2_COMPOSITION_REFRESH_RATE_INDICATOR;
} else {
type = mLayers[layerIndex]->mValidateCompositionType;
}
@@ -3202,7 +3225,7 @@ int32_t ExynosDisplay::getDisplayRequests(
for (int32_t i = mClientCompositionInfo.mFirstIndex; i < mClientCompositionInfo.mLastIndex; i++) {
ExynosLayer *layer = mLayers[i];
- if (layer->mOverlayPriority >= ePriorityHigh) {
+ if (layer->needClearClientTarget()) {
if ((outLayers != NULL) && (outLayerRequests != NULL)) {
if (requestNum >= *outNumElements)
return -1;
@@ -3355,8 +3378,7 @@ bool ExynosDisplay::isFullScreenComposition() {
dispRect.right = r.right;
}
- if ((dispRect.top != 0) || (dispRect.left != 0) ||
- (dispRect.right != mXres) || (dispRect.bottom != mYres)) {
+ if ((dispRect.right != mXres) || (dispRect.bottom != mYres)) {
ALOGD("invalid displayFrame disp=[%d %d %d %d] expected=%dx%d",
dispRect.left, dispRect.top, dispRect.right, dispRect.bottom,
mXres, mYres);
@@ -3367,9 +3389,10 @@ bool ExynosDisplay::isFullScreenComposition() {
}
int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
- ATRACE_CALL();
+ DISPLAY_ATRACE_CALL();
gettimeofday(&updateTimeInfo.lastPresentTime, NULL);
+ const bool mixedComposition = isMixedComposition();
// store this once here for the whole frame so it's consistent
mUsePowerHints = usePowerHintSession();
if (mUsePowerHints) {
@@ -3452,7 +3475,7 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
ret = HWC2_ERROR_NOT_VALIDATED;
}
mRenderingState = RENDERING_STATE_PRESENTED;
- mDevice->onRefresh();
+ mDevice->onRefresh(mDisplayId);
return ret;
}
@@ -3461,7 +3484,7 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
* presentDisplay() can be called before validateDisplay()
* when HWC2_CAPABILITY_SKIP_VALIDATE is supported
*/
-#ifndef HWC_SKIP_VALIDATE
+#ifdef HWC_NO_SUPPORT_SKIP_VALIDATE
DISPLAY_LOGE("%s:: Skip validate is not supported. Invalid rendering state : %d", __func__, mRenderingState);
goto err;
#endif
@@ -3592,10 +3615,14 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
goto err;
}
- if (mGeometryChanged != 0 || !skipSignalIdleForVideoLayer()) {
+ if (mGeometryChanged != 0 || !skipSignalIdle()) {
mPowerHalHint.signalIdle();
}
+ if (isFrameUpdate()) {
+ updateRefreshRateIndicator();
+ }
+
handleWindowUpdate();
setDisplayWinConfigData();
@@ -3694,6 +3721,8 @@ int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
mPowerHalHint.signalActualWorkDuration(duration + mValidationDuration.value_or(0));
}
+ mPriorFrameMixedComposition = mixedComposition;
+
return ret;
err:
printDebugInfos(errString);
@@ -3969,9 +3998,16 @@ int32_t ExynosDisplay::getDisplayBrightnessSupport(bool* outSupport)
int32_t ExynosDisplay::setDisplayBrightness(float brightness, bool waitPresent)
{
if (mBrightnessController) {
- return mBrightnessController->processDisplayBrightness(brightness, mVsyncPeriod,
- waitPresent);
+ int32_t ret;
+
+ ret = mBrightnessController->processDisplayBrightness(brightness, mVsyncPeriod,
+ waitPresent);
+ if (ret == NO_ERROR && mOperationRateManager) {
+ mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
+ }
+ return ret;
}
+
return HWC2_ERROR_UNSUPPORTED;
}
@@ -4041,17 +4077,23 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t* outTimeline)
{
- ATRACE_CALL();
+ DISPLAY_ATRACE_CALL();
Mutex::Autolock lock(mDisplayMutex);
+ const nsecs_t current = systemTime(SYSTEM_TIME_MONOTONIC);
+ const nsecs_t diffMs = ns2ms(vsyncPeriodChangeConstraints->desiredTimeNanos - current);
+ DISPLAY_LOGD(eDebugDisplayConfig, "config(%d->%d), seamless(%d), diff(%" PRId64 ")",
+ mActiveConfig, config, vsyncPeriodChangeConstraints->seamlessRequired, diffMs);
- DISPLAY_LOGD(eDebugDisplayConfig,
- "config(%d), seamless(%d), "
- "desiredTime(%" PRId64 ")",
- config, vsyncPeriodChangeConstraints->seamlessRequired,
- vsyncPeriodChangeConstraints->desiredTimeNanos);
+ if (CC_UNLIKELY(ATRACE_ENABLED())) ATRACE_NAME(("diff:" + std::to_string(diffMs)).c_str());
if (isBadConfig(config)) return HWC2_ERROR_BAD_CONFIG;
+ if (!isConfigSettingEnabled()) {
+ mPendingConfig = config;
+ DISPLAY_LOGI("%s: config setting disabled, set pending config=%d", __func__, config);
+ return HWC2_ERROR_NONE;
+ }
+
if (mDisplayConfigs[mActiveConfig].groupId != mDisplayConfigs[config].groupId) {
if (vsyncPeriodChangeConstraints->seamlessRequired) {
DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not allowed");
@@ -4059,9 +4101,7 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
}
outTimeline->newVsyncAppliedTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
-
- // when switching between display group setActiveConfig directly
- return setActiveConfigInternal(config, false);
+ outTimeline->refreshRequired = true;
}
if (needNotChangeConfig(config)) {
@@ -4070,7 +4110,15 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
return HWC2_ERROR_NONE;
}
- if (vsyncPeriodChangeConstraints->seamlessRequired) {
+ if ((mXres != mDisplayConfigs[config].width) || (mYres != mDisplayConfigs[config].height)) {
+ if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
+ ALOGW("Mode change not possible");
+ return HWC2_ERROR_BAD_CONFIG;
+ }
+ mRenderingState = RENDERING_STATE_NONE;
+ setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
+ updateInternalDisplayConfigVariables(config, false);
+ } else if (vsyncPeriodChangeConstraints->seamlessRequired) {
if ((mDisplayInterface->setActiveConfigWithConstraints(config, true)) != NO_ERROR) {
DISPLAY_LOGD(eDebugDisplayConfig, "Case : Seamless is not possible");
return HWC2_ERROR_SEAMLESS_NOT_POSSIBLE;
@@ -4088,6 +4136,7 @@ int32_t ExynosDisplay::setActiveConfigWithConstraints(hwc2_config_t config,
mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_PENDING;
mVsyncPeriodChangeConstraints = *vsyncPeriodChangeConstraints;
mDesiredConfig = config;
+ DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
calculateTimeline(config, vsyncPeriodChangeConstraints, outTimeline);
@@ -4208,7 +4257,8 @@ uint32_t ExynosDisplay::getBtsRefreshRate() const {
void ExynosDisplay::updateRefreshRateHint() {
if (mVsyncPeriod) {
- mPowerHalHint.signalRefreshRate(mPowerModeState, mVsyncPeriod);
+ mPowerHalHint.signalRefreshRate(mPowerModeState.value_or(HWC2_POWER_MODE_OFF),
+ mVsyncPeriod);
}
}
@@ -4226,9 +4276,9 @@ int32_t ExynosDisplay::resetConfigRequestStateLocked(hwc2_config_t config) {
DISPLAY_LOGI("%s: mConfigRequestState (%d) is not REQUESTED", __func__,
mConfigRequestState);
} else {
- DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "%s: Change mConfigRequestState (%d) to NONE",
+ DISPLAY_LOGD(eDebugDisplayInterfaceConfig, "%s: Change mConfigRequestState (%d) to DONE",
__func__, mConfigRequestState);
- mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_NONE;
+ mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
updateAppliedActiveConfig(mActiveConfig, systemTime(SYSTEM_TIME_MONOTONIC));
}
return NO_ERROR;
@@ -4299,6 +4349,7 @@ int32_t ExynosDisplay::doDisplayConfigInternal(hwc2_config_t config) {
int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
{
+ ATRACE_CALL();
uint64_t current = systemTime(SYSTEM_TIME_MONOTONIC);
int64_t actualChangeTime = 0;
@@ -4313,11 +4364,13 @@ int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
if (actualChangeTime >= mVsyncPeriodChangeConstraints.desiredTimeNanos) {
DISPLAY_LOGD(eDebugDisplayConfig, "Request setActiveConfig");
needSetActiveConfig = true;
- ATRACE_INT("Pending ActiveConfig", 0);
+ DISPLAY_ATRACE_INT("Pending ActiveConfig", 0);
+ DISPLAY_ATRACE_INT64("TimeToChangeConfig", 0);
} else {
DISPLAY_LOGD(eDebugDisplayConfig, "setActiveConfig still pending (mDesiredConfig %d)",
mDesiredConfig);
- ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
+ DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
+ DISPLAY_ATRACE_INT64("TimeToChangeConfig", ns2ms(actualChangeTime - current));
}
if (needSetActiveConfig) {
@@ -4352,7 +4405,7 @@ int ExynosDisplay::clearDisplay(bool needModeClear) {
mLastRetireFence = fence_close(mLastRetireFence, this, FENCE_TYPE_RETIRE, FENCE_IP_DPP);
if (mBrightnessController) {
- mBrightnessController->onClearDisplay();
+ mBrightnessController->onClearDisplay(needModeClear);
}
return ret;
}
@@ -4443,8 +4496,7 @@ int32_t ExynosDisplay::setVsyncEnabledInternal(
int32_t ExynosDisplay::validateDisplay(
uint32_t* outNumTypes, uint32_t* outNumRequests) {
-
- ATRACE_CALL();
+ DISPLAY_ATRACE_CALL();
gettimeofday(&updateTimeInfo.lastValidateTime, NULL);
Mutex::Autolock lock(mDisplayMutex);
@@ -4585,6 +4637,7 @@ int32_t ExynosDisplay::validateDisplay(
int32_t ExynosDisplay::startPostProcessing()
{
+ ATRACE_CALL();
int ret = NO_ERROR;
String8 errString;
@@ -4881,8 +4934,10 @@ int32_t ExynosDisplay::addClientCompositionLayer(uint32_t layerIndex)
/* handle sandwiched layers */
for (uint32_t i = (uint32_t)mClientCompositionInfo.mFirstIndex + 1; i < (uint32_t)mClientCompositionInfo.mLastIndex; i++) {
ExynosLayer *layer = mLayers[i];
- if (layer->mOverlayPriority >= ePriorityHigh) {
- DISPLAY_LOGD(eDebugResourceManager, "\t[%d] layer has high or max priority (%d)", i, layer->mOverlayPriority);
+ if (layer->needClearClientTarget()) {
+ DISPLAY_LOGD(eDebugResourceManager,
+ "\t[%d] layer is opaque and has high or max priority (%d)", i,
+ layer->mOverlayPriority);
continue;
}
if (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT)
@@ -4989,9 +5044,7 @@ int32_t ExynosDisplay::removeClientCompositionLayer(uint32_t layerIndex)
return ret;
}
-
-int32_t ExynosDisplay::addExynosCompositionLayer(uint32_t layerIndex)
-{
+int32_t ExynosDisplay::addExynosCompositionLayer(uint32_t layerIndex, float totalUsedCapa) {
bool invalidFlag = false;
int32_t changeFlag = NO_ERROR;
int ret = 0;
@@ -5070,7 +5123,7 @@ int32_t ExynosDisplay::addExynosCompositionLayer(uint32_t layerIndex)
layer->setExynosMidImage(dst_img);
bool isAssignable = false;
if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
- isAssignable = m2mMPP->isAssignable(this, src_img, dst_img);
+ isAssignable = m2mMPP->isAssignable(this, src_img, dst_img, totalUsedCapa);
if (layer->mValidateCompositionType == HWC2_COMPOSITION_CLIENT)
{
@@ -5830,13 +5883,13 @@ void ExynosDisplay::traceLayerTypes() {
break;
}
}
- ATRACE_INT("HWComposer: DPU Layer", dpu_count);
- ATRACE_INT("HWComposer: G2D Layer", g2d_count);
- ATRACE_INT("HWComposer: GPU Layer", gpu_count);
- ATRACE_INT("HWComposer: RCD Layer", rcd_count);
- ATRACE_INT("HWComposer: DPU Cached Layer", skip_count);
- ATRACE_INT("HWComposer: SF Cached Layer", mIgnoreLayers.size());
- ATRACE_INT("HWComposer: Total Layer", mLayers.size() + mIgnoreLayers.size());
+ DISPLAY_ATRACE_INT("HWComposer: DPU Layer", dpu_count);
+ DISPLAY_ATRACE_INT("HWComposer: G2D Layer", g2d_count);
+ DISPLAY_ATRACE_INT("HWComposer: GPU Layer", gpu_count);
+ DISPLAY_ATRACE_INT("HWComposer: RCD Layer", rcd_count);
+ DISPLAY_ATRACE_INT("HWComposer: DPU Cached Layer", skip_count);
+ DISPLAY_ATRACE_INT("HWComposer: SF Cached Layer", mIgnoreLayers.size());
+ DISPLAY_ATRACE_INT("HWComposer: Total Layer", mLayers.size() + mIgnoreLayers.size());
}
void ExynosDisplay::updateBrightnessState() {
@@ -5880,6 +5933,7 @@ void ExynosDisplay::updateBrightnessState() {
if (mBrightnessController) {
mBrightnessController->updateFrameStates(hdrState, sdrDim);
mBrightnessController->processInstantHbm(instantHbm && !clientRgbHdr);
+ mBrightnessController->updateCabcMode();
}
}
@@ -5894,6 +5948,9 @@ void ExynosDisplay::cleanupAfterClientDeath() {
int32_t ExynosDisplay::flushDisplayBrightnessChange() {
if (mBrightnessController) {
+ if (mOperationRateManager) {
+ mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
+ }
return mBrightnessController->applyPendingChangeViaSysfs(mVsyncPeriod);
}
return NO_ERROR;
@@ -5916,7 +5973,6 @@ nsecs_t ExynosDisplay::getExpectedPresentTime(nsecs_t startTime) {
return out;
}
}
- ALOGE("Could not get hint session time target from primary display");
return getPredictedPresentTime(startTime);
}
@@ -6011,3 +6067,265 @@ int32_t ExynosDisplay::setDebugRCDLayerEnabled(bool enable) {
int32_t ExynosDisplay::getDisplayIdleTimerSupport(bool &outSupport) {
return mDisplayInterface->getDisplayIdleTimerSupport(outSupport);
}
+
+int32_t ExynosDisplay::getDisplayMultiThreadedPresentSupport(bool &outSupport) {
+ outSupport = mDisplayControl.multiThreadedPresent;
+ return NO_ERROR;
+}
+
+bool ExynosDisplay::isMixedComposition() {
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ if (mLayers[i]->mBrightness < 1.0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+int ExynosDisplay::lookupDisplayConfigs(const int32_t &width,
+ const int32_t &height,
+ const int32_t &fps,
+ int32_t *outConfig) {
+ if (!fps)
+ return HWC2_ERROR_BAD_CONFIG;
+
+ constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
+ constexpr auto nsecsPerMs = std::chrono::nanoseconds(1ms).count();
+
+ const auto vsyncPeriod = nsecsPerSec / fps;
+
+ for (auto const& [config, mode] : mDisplayConfigs) {
+ long delta = abs(vsyncPeriod - mode.vsyncPeriod);
+ if ((width == mode.width) && (height == mode.height) && (delta < nsecsPerMs)) {
+ ALOGD("%s: found display config for mode: %dx%d@%d=%d",
+ __func__, width, height, fps, config);
+ *outConfig = config;
+ return HWC2_ERROR_NONE;
+ }
+ }
+ return HWC2_ERROR_BAD_CONFIG;
+}
+
+FILE *ExynosDisplay::RotatingLogFileWriter::openLogFile(const std::string &filename,
+ const std::string &mode) {
+ FILE *file = nullptr;
+ auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
+ file = fopen(fullpath.c_str(), mode.c_str());
+ if (file != nullptr) {
+ return file;
+ }
+ ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
+ fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
+ file = fopen(fullpath.c_str(), mode.c_str());
+ if (file == nullptr) {
+ ALOGE("Fail to open file %s, error: %s", fullpath.c_str(), strerror(errno));
+ }
+ return file;
+}
+
+std::optional<nsecs_t> ExynosDisplay::RotatingLogFileWriter::getLastModifiedTimestamp(
+ const std::string &filename) {
+ struct stat fileStat;
+ auto fullpath = std::string(ERROR_LOG_PATH0) + "/" + filename;
+ if (stat(fullpath.c_str(), &fileStat) == 0) {
+ return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
+ }
+ fullpath = std::string(ERROR_LOG_PATH1) + "/" + filename;
+ if (stat(fullpath.c_str(), &fileStat) == 0) {
+ return fileStat.st_mtim.tv_sec * nsecsPerSec + fileStat.st_mtim.tv_nsec;
+ }
+ return std::nullopt;
+}
+
+bool ExynosDisplay::RotatingLogFileWriter::chooseOpenedFile() {
+ if (mLastFileIndex < 0) {
+ // HWC could be restarted, so choose to open new file or continue the last modified file
+ int chosenIndex = 0;
+ nsecs_t lastModifTimestamp = 0;
+ for (int i = 0; i < mMaxFileCount; ++i) {
+ auto timestamp = getLastModifiedTimestamp(mPrefixName + std::to_string(i) + mExtension);
+ if (!timestamp.has_value()) {
+ chosenIndex = i;
+ break;
+ }
+ if (i == 0 || lastModifTimestamp < *timestamp) {
+ chosenIndex = i;
+ lastModifTimestamp = *timestamp;
+ }
+ }
+ auto filename = mPrefixName + std::to_string(chosenIndex) + mExtension;
+ mFile = openLogFile(filename, "ab");
+ if (mFile == nullptr) {
+ ALOGE("Unable to open log file for %s", filename.c_str());
+ return false;
+ }
+ mLastFileIndex = chosenIndex;
+ }
+
+ // Choose to use the same last file or move on to the next file
+ for (int i = 0; i < 2; ++i) {
+ if (mFile == nullptr) {
+ mFile = openLogFile(mPrefixName + std::to_string(mLastFileIndex) + mExtension,
+ (i == 0) ? "ab" : "wb");
+ }
+ if (mFile != nullptr) {
+ auto fileSize = ftell(mFile);
+ if (fileSize < mThresholdSizePerFile) return true;
+ fclose(mFile);
+ mFile = nullptr;
+ }
+ mLastFileIndex = (mLastFileIndex + 1) % mMaxFileCount;
+ }
+ return false;
+}
+
+ExynosDisplay::RefreshRateIndicatorHandler::RefreshRateIndicatorHandler(ExynosDisplay *display)
+ : mDisplay(display), mLastRefreshRate(0), mLastCallbackTime(0) {}
+
+int32_t ExynosDisplay::RefreshRateIndicatorHandler::init() {
+ auto path = String8::format(kRefreshRateStatePathFormat, mDisplay->mIndex);
+ mFd.Set(open(path.c_str(), O_RDONLY));
+ if (mFd.get() < 0) {
+ ALOGE("Failed to open sysfs(%s) for refresh rate debug event: %s", path.c_str(),
+ strerror(errno));
+ return -errno;
+ }
+
+ return NO_ERROR;
+}
+
+void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRateLocked(int refreshRate) {
+ ATRACE_CALL();
+ ATRACE_INT("Refresh rate indicator event", refreshRate);
+ auto lastUpdate = mDisplay->getLastLayerUpdateTime();
+ // Ignore refresh rate increase that is caused by refresh rate indicator update but there's
+ // no update for the other layers
+ if (refreshRate > mLastRefreshRate && mLastRefreshRate > 0 && lastUpdate < mLastCallbackTime) {
+ mIgnoringLastUpdate = true;
+ return;
+ }
+ mIgnoringLastUpdate = false;
+ if (refreshRate == mLastRefreshRate) {
+ return;
+ }
+ mLastRefreshRate = refreshRate;
+ mLastCallbackTime = systemTime(CLOCK_MONOTONIC);
+ ATRACE_INT("Refresh rate indicator callback", mLastRefreshRate);
+ mDisplay->mDevice->onRefreshRateChangedDebug(mDisplay->mDisplayId, s2ns(1) / mLastRefreshRate);
+}
+
+void ExynosDisplay::RefreshRateIndicatorHandler::handleSysfsEvent() {
+ ATRACE_CALL();
+ std::scoped_lock lock(mMutex);
+
+ char buffer[1024];
+ lseek(mFd.get(), 0, SEEK_SET);
+ int ret = read(mFd.get(), &buffer, sizeof(buffer));
+ if (ret < 0) {
+ ALOGE("%s: Failed to read refresh rate from fd %d: %s", __func__, mFd.get(),
+ strerror(errno));
+ return;
+ }
+ std::string_view bufferView(buffer);
+ auto pos = bufferView.find('@');
+ if (pos == std::string::npos) {
+ ALOGE("%s: Failed to parse refresh rate event (invalid format)", __func__);
+ return;
+ }
+ int refreshRate = 0;
+ std::from_chars(bufferView.data() + pos + 1, bufferView.data() + bufferView.size() - 1,
+ refreshRate);
+ updateRefreshRateLocked(refreshRate);
+}
+
+void ExynosDisplay::RefreshRateIndicatorHandler::updateRefreshRate(int refreshRate) {
+ std::scoped_lock lock(mMutex);
+ updateRefreshRateLocked(refreshRate);
+}
+
+int32_t ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
+ if ((!!mRefreshRateIndicatorHandler) == enabled) {
+ ALOGW("%s: RefreshRateChangedCallbackDebug is already %s", __func__,
+ enabled ? "enabled" : "disabled");
+ return NO_ERROR;
+ }
+ int32_t ret = NO_ERROR;
+ if (enabled) {
+ mRefreshRateIndicatorHandler = std::make_shared<RefreshRateIndicatorHandler>(this);
+ if (!mRefreshRateIndicatorHandler) {
+ ALOGE("%s: Failed to create refresh rate debug handler", __func__);
+ return -ENOMEM;
+ }
+ ret = mRefreshRateIndicatorHandler->init();
+ if (ret != NO_ERROR) {
+ ALOGE("%s: Failed to initialize refresh rate debug handler: %d", __func__, ret);
+ mRefreshRateIndicatorHandler.reset();
+ return ret;
+ }
+ ret = mDevice->mDeviceInterface->registerSysfsEventHandler(mRefreshRateIndicatorHandler);
+ if (ret != NO_ERROR) {
+ ALOGE("%s: Failed to register sysfs event handler: %d", __func__, ret);
+ mRefreshRateIndicatorHandler.reset();
+ return ret;
+ }
+ // Call the callback immediately
+ mRefreshRateIndicatorHandler->handleSysfsEvent();
+ } else {
+ ret = mDevice->mDeviceInterface->unregisterSysfsEventHandler(
+ mRefreshRateIndicatorHandler->getFd());
+ mRefreshRateIndicatorHandler.reset();
+ }
+ return ret;
+}
+
+nsecs_t ExynosDisplay::getLastLayerUpdateTime() {
+ Mutex::Autolock lock(mDRMutex);
+ nsecs_t time = 0;
+ for (size_t i = 0; i < mLayers.size(); ++i) {
+ // The update from refresh rate indicator layer should be ignored
+ if (mLayers[i]->mRequestedCompositionType == HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
+ continue;
+ time = max(time, mLayers[i]->mLastUpdateTime);
+ }
+ return time;
+}
+
+void ExynosDisplay::updateRefreshRateIndicator() {
+ // Update refresh rate indicator if the last update event is ignored to make sure that
+ // the refresh rate caused by the current frame update will be applied immediately since
+ // we may not receive the sysfs event if the refresh rate is the same as the last ignored one.
+ if (!mRefreshRateIndicatorHandler || !mRefreshRateIndicatorHandler->isIgnoringLastUpdate())
+ return;
+ mRefreshRateIndicatorHandler->handleSysfsEvent();
+}
+
+uint32_t ExynosDisplay::getPeakRefreshRate() {
+ float opRate = mOperationRateManager ? mOperationRateManager->getOperationRate() : 0;
+ return static_cast<uint32_t>(std::round(opRate ?: mPeakRefreshRate));
+}
+
+VsyncPeriodNanos ExynosDisplay::getVsyncPeriod(const int32_t config) {
+ const auto &it = mDisplayConfigs.find(config);
+ if (it == mDisplayConfigs.end()) return 0;
+ return mDisplayConfigs[config].vsyncPeriod;
+}
+
+uint32_t ExynosDisplay::getRefreshRate(const int32_t config) {
+ VsyncPeriodNanos period = getVsyncPeriod(config);
+ if (!period) return 0;
+ constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
+ return round(nsecsPerSec / period * 0.1f) * 10;
+}
+
+uint32_t ExynosDisplay::getConfigId(const int32_t refreshRate, const int32_t width,
+ const int32_t height) {
+ for (auto entry : mDisplayConfigs) {
+ auto config = entry.first;
+ auto displayCfg = entry.second;
+ if (getRefreshRate(config) == refreshRate && displayCfg.width == width &&
+ displayCfg.height == height) {
+ return config;
+ }
+ }
+ return UINT_MAX;
+}
diff --git a/libhwc2.1/libdevice/ExynosDisplay.h b/libhwc2.1/libdevice/ExynosDisplay.h
index 6c7eded..8a12393 100644
--- a/libhwc2.1/libdevice/ExynosDisplay.h
+++ b/libhwc2.1/libdevice/ExynosDisplay.h
@@ -27,6 +27,7 @@
#include <chrono>
#include <set>
+#include "DeconHeader.h"
#include "ExynosDisplayInterface.h"
#include "ExynosHWC.h"
#include "ExynosHWCDebug.h"
@@ -34,6 +35,7 @@
#include "ExynosHwc3Types.h"
#include "ExynosMPP.h"
#include "ExynosResourceManager.h"
+#include "drmeventlistener.h"
#include "worker.h"
#define HWC_CLEARDISPLAY_WITH_COLORMAP
@@ -141,15 +143,21 @@ enum class PanelGammaSource {
};
enum class hwc_request_state_t {
- SET_CONFIG_STATE_NONE = 0,
+ SET_CONFIG_STATE_DONE = 0,
SET_CONFIG_STATE_PENDING,
SET_CONFIG_STATE_REQUESTED,
};
+enum class VrrThrottleRequester : uint32_t {
+ PIXEL_DISP = 0,
+ TEST,
+ LHBM,
+ MAX,
+};
+
enum class DispIdleTimerRequester : uint32_t {
SF = 0,
- PIXEL_DISP,
- TEST,
+ VRR_THROTTLE,
MAX,
};
@@ -279,6 +287,22 @@ class ExynosSortedLayer : public Vector <ExynosLayer*>
static int compare(ExynosLayer * const *lhs, ExynosLayer *const *rhs);
};
+class DisplayTDMInfo {
+ public:
+ /* Could be extended */
+ typedef struct ResourceAmount {
+ uint32_t totalAmount;
+ } ResourceAmount_t;
+ std::map<tdm_attr_t, ResourceAmount_t> mAmount;
+
+ uint32_t initTDMInfo(ResourceAmount_t amount, tdm_attr_t attr) {
+ mAmount[attr] = amount;
+ return 0;
+ }
+
+ ResourceAmount_t getAvailableAmount(tdm_attr_t attr) { return mAmount[attr]; }
+};
+
class ExynosCompositionInfo : public ExynosMPPSource {
public:
ExynosCompositionInfo():ExynosCompositionInfo(COMPOSITION_NONE){};
@@ -361,13 +385,15 @@ struct DisplayControl {
bool forceReserveMPP = false;
/** Skip M2MMPP processing **/
bool skipM2mProcessing = true;
+ /** Enable multi-thread present **/
+ bool multiThreadedPresent = false;
};
class ExynosDisplay {
public:
- uint32_t mDisplayId;
- uint32_t mType;
- uint32_t mIndex;
+ const uint32_t mDisplayId;
+ const uint32_t mType;
+ const uint32_t mIndex;
String8 mDeconNodeName;
uint32_t mXres;
uint32_t mYres;
@@ -380,19 +406,21 @@ class ExynosDisplay {
int mPsrMode;
/* Constructor */
- ExynosDisplay(uint32_t index, ExynosDevice *device);
+ ExynosDisplay(uint32_t type, uint32_t index, ExynosDevice* device,
+ const std::string& displayName);
/* Destructor */
virtual ~ExynosDisplay();
ExynosDevice *mDevice;
- String8 mDisplayName;
+ const String8 mDisplayName;
+ const String8 mDisplayTraceName;
HwcMountOrientation mMountOrientation = HwcMountOrientation::ROT_0;
Mutex mDisplayMutex;
/** State variables */
bool mPlugState;
- hwc2_power_mode_t mPowerModeState;
+ std::optional<hwc2_power_mode_t> mPowerModeState;
hwc2_vsync_t mVsyncState;
bool mHasSingleBuffer;
bool mPauseDisplay = false;
@@ -422,10 +450,17 @@ class ExynosDisplay {
* Geometry change info is described by bit map.
* This flag is cleared when resource assignment for all displays
* is done.
+ * Geometry changed to layer REFRESH_RATE_INDICATOR will be excluded.
*/
uint64_t mGeometryChanged;
/**
+ * The number of buffer updates in the current frame.
+ * Buffer update for layer REFRESH_RATE_INDICATOR will be excluded.
+ */
+ uint32_t mBufferUpdates;
+
+ /**
* Rendering step information that is seperated by
* VALIDATED, ACCEPTED_CHANGE, PRESENTED.
*/
@@ -527,6 +562,8 @@ class ExynosDisplay {
hwc2_config_t mDesiredConfig;
hwc2_config_t mActiveConfig = UINT_MAX;
+ hwc2_config_t mPendingConfig = UINT_MAX;
+ int64_t mLastVsyncTimestamp = 0;
void initDisplay();
@@ -537,7 +574,7 @@ class ExynosDisplay {
int32_t initializeValidateInfos();
int32_t addClientCompositionLayer(uint32_t layerIndex);
int32_t removeClientCompositionLayer(uint32_t layerIndex);
- int32_t addExynosCompositionLayer(uint32_t layerIndex);
+ int32_t addExynosCompositionLayer(uint32_t layerIndex, float totalUsedCapa);
/**
* Dynamic AFBC Control solution : To get the prepared information is applied to current or not.
@@ -558,6 +595,8 @@ class ExynosDisplay {
int checkLayerFps();
+ int switchDynamicReCompMode(dynamic_recomp_mode mode);
+
int checkDynamicReCompMode();
int handleDynamicReCompMode();
@@ -991,7 +1030,7 @@ class ExynosDisplay {
*/
int32_t getPreferredBootDisplayConfig(int32_t* outConfig);
- virtual int32_t getPreferredDisplayConfigInternal(int32_t *outConfig);
+ virtual int32_t getPreferredDisplayConfigInternal(int32_t* outConfig);
/* setAutoLowLatencyMode(displayToken, on)
* Descriptor: HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE
@@ -1161,6 +1200,7 @@ class ExynosDisplay {
void setHWCControl(uint32_t ctrl, int32_t val);
void setGeometryChanged(uint64_t changedBit);
void clearGeometryChanged();
+ bool isFrameUpdate();
virtual void setDDIScalerEnable(int width, int height);
virtual int getDDIScalerMode(int width, int height);
@@ -1180,12 +1220,14 @@ class ExynosDisplay {
return PanelGammaSource::GAMMA_DEFAULT;
}
virtual void initLbe(){};
+ virtual bool isLbeSupported() { return false; }
virtual void setLbeState(LbeState __unused state) {}
virtual void setLbeAmbientLight(int __unused value) {}
virtual LbeState getLbeState() { return LbeState::OFF; }
int32_t checkPowerHalExtHintSupport(const std::string& mode);
+ virtual bool isLhbmSupported() { return false; }
virtual int32_t setLhbmState(bool __unused enabled) { return NO_ERROR; }
virtual bool getLhbmState() { return false; };
virtual void setEarlyWakeupDisplay() {}
@@ -1193,6 +1235,7 @@ class ExynosDisplay {
virtual uint64_t getPendingExpectedPresentTime() { return 0; }
virtual void applyExpectedPresentTime() {}
virtual int32_t getDisplayIdleTimerSupport(bool& outSupport);
+ virtual int32_t getDisplayMultiThreadedPresentSupport(bool& outSupport);
virtual int32_t setDisplayIdleTimer(const int32_t __unused timeoutMs) {
return HWC2_ERROR_UNSUPPORTED;
}
@@ -1201,6 +1244,8 @@ class ExynosDisplay {
virtual PanelCalibrationStatus getPanelCalibrationStatus() {
return PanelCalibrationStatus::UNCALIBRATED;
}
+ virtual bool isDbmSupported() { return false; }
+ virtual int32_t setDbmState(bool __unused enabled) { return NO_ERROR; }
/* getDisplayPreAssignBit support mIndex up to 1.
It supports only dual LCD and 2 external displays */
@@ -1232,27 +1277,37 @@ class ExynosDisplay {
virtual int setMinIdleRefreshRate(const int __unused fps) { return NO_ERROR; }
virtual int setRefreshRateThrottleNanos(const int64_t __unused delayNanos,
- const DispIdleTimerRequester __unused requester) {
+ const VrrThrottleRequester __unused requester) {
return NO_ERROR;
}
virtual void updateAppliedActiveConfig(const hwc2_config_t /*newConfig*/,
const int64_t /*ts*/) {}
+ virtual bool isConfigSettingEnabled() { return true; }
+ virtual void enableConfigSetting(bool /*en*/) {}
+
// is the hint session both enabled and supported
bool usePowerHintSession();
- void setMinDisplayVsyncPeriod(uint32_t period) { mMinDisplayVsyncPeriod = period; }
+ void setPeakRefreshRate(float rr) { mPeakRefreshRate = rr; }
+ uint32_t getPeakRefreshRate();
+ VsyncPeriodNanos getVsyncPeriod(const int32_t config);
+ uint32_t getRefreshRate(const int32_t config);
+ uint32_t getConfigId(const int32_t refreshRate, const int32_t width, const int32_t height);
- bool isCurrentPeakRefreshRate(void) {
- return ((mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_NONE) &&
- (mVsyncPeriod == mMinDisplayVsyncPeriod));
- }
+ // check if there are any dimmed layers
+ bool isMixedComposition();
+ bool isPriorFrameMixedCompostion() { return mPriorFrameMixedComposition; }
+ int lookupDisplayConfigs(const int32_t& width,
+ const int32_t& height,
+ const int32_t& fps,
+ int32_t* outConfig);
private:
bool skipStaticLayerChanged(ExynosCompositionInfo& compositionInfo);
- bool skipSignalIdleForVideoLayer();
+ bool skipSignalIdle();
/// minimum possible dim rate in the case hbm peak is 1000 nits and norml
// display brightness is 2 nits
@@ -1263,13 +1318,17 @@ class ExynosDisplay {
static constexpr float kHdrFullScreen = 0.5;
uint32_t mHdrFullScrenAreaThreshold;
- // vsync period of peak refresh rate
- uint32_t mMinDisplayVsyncPeriod;
+ // peak refresh rate
+ float mPeakRefreshRate = -1.0f;
+
+ // track if the last frame is a mixed composition, to detect mixed
+ // composition to non-mixed composition transition.
+ bool mPriorFrameMixedComposition;
/* Display hint to notify power hal */
class PowerHalHintWorker : public Worker {
public:
- PowerHalHintWorker();
+ PowerHalHintWorker(uint32_t displayId, const String8& displayTraceName);
virtual ~PowerHalHintWorker();
int Init();
@@ -1342,9 +1401,16 @@ class ExynosDisplay {
// whether idle hint is supported
bool mIdleHintIsSupported;
+ String8 mDisplayTraceName;
+ std::string mIdleHintStr;
+ std::string mRefreshRateHintPrefixStr;
+
hwc2_power_mode_t mPowerModeState;
uint32_t mVsyncPeriod;
+ uint32_t mConnectRetryCount;
+ bool isPowerHalExist() { return mConnectRetryCount < 10; }
+
ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
// for power HAL extension hints
@@ -1424,6 +1490,9 @@ class ExynosDisplay {
static const constexpr nsecs_t SIGNAL_TIME_PENDING = INT64_MAX;
static const constexpr nsecs_t SIGNAL_TIME_INVALID = -1;
std::unordered_map<uint32_t, RollingAverage<kAveragesBufferSize>> mRollingAverages;
+ // mPowerHalHint should be declared only after mDisplayId and mDisplayTraceName have been
+ // declared since mDisplayId and mDisplayTraceName are needed as the parameter of
+ // PowerHalHintWorker's constructor
PowerHalHintWorker mPowerHalHint;
std::optional<nsecs_t> mValidateStartTime;
@@ -1462,6 +1531,106 @@ class ExynosDisplay {
hwc2_config_t config,
hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t* outTimeline);
+
+ public:
+ /* Override for each display's meaning of 'enabled state'
+ * Primary : Power on, this function overrided in primary display module
+ * Exteranal : Plug-in, default */
+ virtual bool isEnabled() { return mPlugState; }
+
+ // Resource TDM (Time-Division Multiplexing)
+ std::map<uint32_t, DisplayTDMInfo> mDisplayTDMInfo;
+
+ class RotatingLogFileWriter {
+ public:
+ RotatingLogFileWriter(uint32_t maxFileCount, uint32_t thresholdSizePerFile,
+ std::string extension = ".txt")
+ : mMaxFileCount(maxFileCount),
+ mThresholdSizePerFile(thresholdSizePerFile),
+ mPrefixName(""),
+ mExtension(extension),
+ mLastFileIndex(-1),
+ mFile(nullptr) {}
+
+ ~RotatingLogFileWriter() {
+ if (mFile) {
+ fclose(mFile);
+ }
+ }
+
+ bool chooseOpenedFile();
+ void write(const String8& content) {
+ if (mFile) {
+ fwrite(content.string(), 1, content.size(), mFile);
+ }
+ }
+ void flush() {
+ if (mFile) {
+ fflush(mFile);
+ }
+ }
+ void setPrefixName(const std::string& prefixName) { mPrefixName = prefixName; }
+
+ private:
+ FILE* openLogFile(const std::string& filename, const std::string& mode);
+ std::optional<nsecs_t> getLastModifiedTimestamp(const std::string& filename);
+
+ uint32_t mMaxFileCount;
+ uint32_t mThresholdSizePerFile;
+ std::string mPrefixName;
+ std::string mExtension;
+ int32_t mLastFileIndex;
+ FILE* mFile;
+ };
+ RotatingLogFileWriter mErrLogFileWriter;
+ RotatingLogFileWriter mDebugDumpFileWriter;
+ RotatingLogFileWriter mFenceFileWriter;
+
+ protected:
+ class OperationRateManager {
+ public:
+ OperationRateManager() {}
+ virtual ~OperationRateManager() {}
+
+ virtual int32_t onLowPowerMode(bool __unused enabled) { return 0; }
+ virtual int32_t onPeakRefreshRate(uint32_t __unused rate) { return 0; }
+ virtual int32_t onConfig(hwc2_config_t __unused cfg) { return 0; }
+ virtual int32_t onBrightness(uint32_t __unused dbv) { return 0; }
+ virtual int32_t onPowerMode(int32_t __unused mode) { return 0; }
+ virtual int32_t getOperationRate() { return 0; }
+ };
+
+ public:
+ std::unique_ptr<OperationRateManager> mOperationRateManager;
+ bool isOperationRateSupported() { return mOperationRateManager != nullptr; }
+
+ class RefreshRateIndicatorHandler : public DrmSysfsEventHandler {
+ public:
+ RefreshRateIndicatorHandler(ExynosDisplay* display);
+ int32_t init();
+ virtual void handleSysfsEvent() override;
+ virtual int getFd() override { return mFd.get(); };
+ bool isIgnoringLastUpdate() { return mIgnoringLastUpdate; }
+ void updateRefreshRate(int refreshRate);
+
+ private:
+ void updateRefreshRateLocked(int refreshRate) REQUIRES(mMutex);
+
+ ExynosDisplay* mDisplay;
+ int mLastRefreshRate GUARDED_BY(mMutex);
+ nsecs_t mLastCallbackTime GUARDED_BY(mMutex);
+ std::atomic_bool mIgnoringLastUpdate = false;
+ UniqueFd mFd;
+ std::mutex mMutex;
+
+ static constexpr auto kRefreshRateStatePathFormat =
+ "/sys/class/backlight/panel%d-backlight/state";
+ };
+
+ std::shared_ptr<RefreshRateIndicatorHandler> mRefreshRateIndicatorHandler;
+ int32_t setRefreshRateChangedCallbackDebugEnabled(bool enabled);
+ void updateRefreshRateIndicator();
+ nsecs_t getLastLayerUpdateTime();
};
#endif //_EXYNOSDISPLAY_H
diff --git a/libhwc2.1/libdevice/ExynosLayer.cpp b/libhwc2.1/libdevice/ExynosLayer.cpp
index 105437e..8f1662d 100644
--- a/libhwc2.1/libdevice/ExynosLayer.cpp
+++ b/libhwc2.1/libdevice/ExynosLayer.cpp
@@ -39,6 +39,7 @@ ExynosLayer::ExynosLayer(ExynosDisplay* display)
: ExynosMPPSource(MPP_SOURCE_LAYER, this),
mDisplay(display),
mCompositionType(HWC2_COMPOSITION_INVALID),
+ mRequestedCompositionType(HWC2_COMPOSITION_INVALID),
mExynosCompositionType(HWC2_COMPOSITION_INVALID),
mValidateCompositionType(HWC2_COMPOSITION_INVALID),
mValidateExynosCompositionType(HWC2_COMPOSITION_INVALID),
@@ -55,8 +56,11 @@ ExynosLayer::ExynosLayer(ExynosDisplay* display)
mFrameCount(0),
mLastFrameCount(0),
mLastFpsTime(0),
+ mNextLastFrameCount(0),
+ mNextLastFpsTime(0),
mLastLayerBuffer(NULL),
mLayerBuffer(NULL),
+ mLastUpdateTime(0),
mDamageNum(0),
mBlending(HWC2_BLEND_MODE_NONE),
mPlaneAlpha(1.0),
@@ -101,27 +105,43 @@ ExynosLayer::~ExynosLayer() {
}
/**
- * @return uint32_t
+ * @return float
*/
-uint32_t ExynosLayer::checkFps() {
+float ExynosLayer::checkFps(bool increaseCount) {
uint32_t frameDiff;
- bool wasLowFps = (mFps < LOW_FPS_THRESHOLD) ? true:false;
- if (mLastLayerBuffer != mLayerBuffer) {
- mFrameCount++;
- }
+ mFrameCount += increaseCount ? 1 : 0;
+
nsecs_t now = systemTime();
- nsecs_t diff = now - mLastFpsTime;
+ if (mLastFpsTime == 0) { // Initialize values
+ mLastFpsTime = now;
+ mNextLastFpsTime = now;
+ // TODO(b/268474771): set the initial FPS to the correct peak refresh rate
+ mFps = 120;
+ return mFps;
+ }
+
+ nsecs_t diff = now - mNextLastFpsTime;
+ // Update mLastFrameCount for every 5s, to ensure that FPS calculation is only based on
+ // frames in the past at most 10s.
+ if (diff >= kLayerFpsStableTimeNs) {
+ mLastFrameCount = mNextLastFrameCount;
+ mNextLastFrameCount = mFrameCount;
+
+ mLastFpsTime = mNextLastFpsTime;
+ mNextLastFpsTime = now;
+ }
+
+ bool wasLowFps = (mFps < LOW_FPS_THRESHOLD) ? true : false;
+
if (mFrameCount >= mLastFrameCount)
frameDiff = (mFrameCount - mLastFrameCount);
else
frameDiff = (mFrameCount + (UINT_MAX - mLastFrameCount));
- if (diff >= ms2ns(250)) {
- mFps = (uint32_t)(frameDiff * float(s2ns(1))) / diff;
- mLastFrameCount = mFrameCount;
- mLastFpsTime = now;
- }
- bool nowLowFps = (mFps < LOW_FPS_THRESHOLD) ? true:false;
+ diff = now - mLastFpsTime;
+ mFps = (frameDiff * float(s2ns(1))) / diff;
+
+ bool nowLowFps = (mFps < LOW_FPS_THRESHOLD) ? true : false;
if ((mDisplay->mDisplayControl.handleLowFpsLayers) &&
(wasLowFps != nowLowFps))
@@ -133,7 +153,7 @@ uint32_t ExynosLayer::checkFps() {
/**
* @return float
*/
-uint32_t ExynosLayer::getFps() {
+float ExynosLayer::getFps() {
return mFps;
}
@@ -397,7 +417,16 @@ int32_t ExynosLayer::setLayerBuffer(buffer_handle_t buffer, int32_t acquireFence
setGeometryChanged(GEOMETRY_LAYER_FRONT_BUFFER_USAGE_CHANGED);
}
- mLayerBuffer = buffer;
+ {
+ Mutex::Autolock lock(mDisplay->mDRMutex);
+ mLayerBuffer = buffer;
+ checkFps(mLastLayerBuffer != mLayerBuffer);
+ if (mLayerBuffer != mLastLayerBuffer) {
+ mLastUpdateTime = systemTime(CLOCK_MONOTONIC);
+ if (mRequestedCompositionType != HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
+ mDisplay->mBufferUpdates++;
+ }
+ }
mPrevAcquireFence =
fence_close(mPrevAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_UNDEFINED);
mAcquireFence = fence_close(mAcquireFence, mDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_UNDEFINED);
@@ -435,9 +464,6 @@ int32_t ExynosLayer::setLayerBuffer(buffer_handle_t buffer, int32_t acquireFence
"internal_format: 0x%" PRIx64 "",
mLayerBuffer, mDataSpace, mAcquireFence, mCompressed, internal_format);
- /* Update fps */
- checkFps();
-
return 0;
}
@@ -487,11 +513,12 @@ int32_t ExynosLayer::setLayerCompositionType(int32_t /*hwc2_composition_t*/ type
type = HWC2_COMPOSITION_DEVICE;
#endif
- if (type != mCompositionType) {
+ if (type != mCompositionType && type != mRequestedCompositionType) {
setGeometryChanged(GEOMETRY_LAYER_TYPE_CHANGED);
}
mCompositionType = type;
+ mRequestedCompositionType = type;
return HWC2_ERROR_NONE;
}
@@ -529,6 +556,11 @@ int32_t ExynosLayer::setLayerDataspace(int32_t /*android_dataspace_t*/ dataspace
if (currentDataSpace != mDataSpace) {
setGeometryChanged(GEOMETRY_LAYER_DATASPACE_CHANGED);
+ // invalidate metadata if dataspace is changed. need metadata update
+ // to be after dataspace update.
+ if (mMetaParcel != nullptr) {
+ mMetaParcel->eType = VIDEO_INFO_TYPE_INVALID;
+ }
}
mDataSpace = currentDataSpace;
@@ -548,9 +580,10 @@ int32_t ExynosLayer::setLayerDisplayFrame(hwc_rect_t frame) {
}
int32_t ExynosLayer::setLayerPlaneAlpha(float alpha) {
-
- if (alpha < 0.0)
- return HWC2_ERROR_BAD_LAYER;
+ if (alpha < 0.0f || alpha > 1.0f) {
+ ALOGE("%s: invalid alpha %f", __func__, alpha);
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
if ((mPlaneAlpha != alpha) && ((mPlaneAlpha == 0.0) || (alpha == 0.0)))
setGeometryChanged(GEOMETRY_LAYER_IGNORE_CHANGED);
@@ -688,7 +721,8 @@ int32_t ExynosLayer::setLayerPerFrameMetadataBlobs(uint32_t numElements, const i
mMetaParcel->eType =
static_cast<ExynosVideoInfoType>(mMetaParcel->eType | VIDEO_INFO_TYPE_HDR_DYNAMIC);
ExynosHdrDynamicInfo *info = &(mMetaParcel->sHdrDynamicInfo);
- Exynos_parsing_user_data_registered_itu_t_t35(info, (void *)metadata_start);
+ Exynos_parsing_user_data_registered_itu_t_t35(info, (void*)metadata_start,
+ sizes[i]);
} else {
ALOGE("Layer has no metaParcel!");
return HWC2_ERROR_UNSUPPORTED;
@@ -939,15 +973,16 @@ int32_t ExynosLayer::resetAssignedResource()
return ret;
}
-bool ExynosLayer::checkDownscaleCap(uint32_t bts_refresh_rate)
-{
+bool ExynosLayer::checkBtsCap(const uint32_t bts_refresh_rate) {
if (mOtfMPP == nullptr) return true;
exynos_image src_img;
exynos_image dst_img;
-
setSrcExynosImage(&src_img);
setDstExynosImage(&dst_img);
+ if (mOtfMPP->checkSpecificRestriction(bts_refresh_rate, src_img, dst_img)) {
+ return false;
+ }
const bool isPerpendicular = !!(src_img.transform & HAL_TRANSFORM_ROT_90);
const uint32_t srcWidth = isPerpendicular ? src_img.h : src_img.w;
@@ -1088,7 +1123,8 @@ void ExynosLayer::printLayer()
mLayerBuffer, fd, fd1, fd2, mAcquireFence, mTransform, mCompressed, mDataSpace, getFormatStr(format, mCompressed? AFBC : 0).string());
result.appendFormat("\tblend: 0x%4x, planeAlpha: %3.1f, zOrder: %d, color[0x%2x, 0x%2x, 0x%2x, 0x%2x]\n",
mBlending, mPlaneAlpha, mZOrder, mColor.r, mColor.g, mColor.b, mColor.a);
- result.appendFormat("\tfps: %2d, priority: %d, windowIndex: %d\n", mFps, mOverlayPriority, mWindowIndex);
+ result.appendFormat("\tfps: %.2f, priority: %d, windowIndex: %d\n", mFps, mOverlayPriority,
+ mWindowIndex);
result.appendFormat("\tsourceCrop[%7.1f,%7.1f,%7.1f,%7.1f], dispFrame[%5d,%5d,%5d,%5d]\n",
mSourceCrop.left, mSourceCrop.top, mSourceCrop.right, mSourceCrop.bottom,
mDisplayFrame.left, mDisplayFrame.top, mDisplayFrame.right, mDisplayFrame.bottom);
@@ -1130,8 +1166,10 @@ void ExynosLayer::printLayer()
void ExynosLayer::setGeometryChanged(uint64_t changedBit)
{
+ mLastUpdateTime = systemTime(CLOCK_MONOTONIC);
mGeometryChanged |= changedBit;
- mDisplay->setGeometryChanged(changedBit);
+ if (mRequestedCompositionType != HWC2_COMPOSITION_REFRESH_RATE_INDICATOR)
+ mDisplay->setGeometryChanged(changedBit);
}
int ExynosLayer::allocMetaParcel()
diff --git a/libhwc2.1/libdevice/ExynosLayer.h b/libhwc2.1/libdevice/ExynosLayer.h
index ead41af..e1df54d 100644
--- a/libhwc2.1/libdevice/ExynosLayer.h
+++ b/libhwc2.1/libdevice/ExynosLayer.h
@@ -41,6 +41,8 @@ using namespace android;
using namespace vendor::graphics;
using ::aidl::android::hardware::graphics::composer3::Composition;
+constexpr nsecs_t kLayerFpsStableTimeNs = s2ns(5);
+
class ExynosMPP;
enum overlay_priority {
@@ -75,6 +77,7 @@ typedef struct pre_processed_layer_info
enum {
HWC2_COMPOSITION_DISPLAY_DECORATION = toUnderlying(Composition::DISPLAY_DECORATION),
+ HWC2_COMPOSITION_REFRESH_RATE_INDICATOR = toUnderlying(Composition::REFRESH_RATE_INDICATOR),
/*add after hwc2_composition_t, margin number here*/
HWC2_COMPOSITION_EXYNOS = 32,
};
@@ -89,10 +92,20 @@ class ExynosLayer : public ExynosMPPSource {
/**
* Layer's compositionType
+ *
+ * If acceptDisplayChanges() is called, it will be set to the validated type
+ * since SF may update their state and doesn't call back into HWC
*/
int32_t mCompositionType;
/**
+ * Composition type that is originally requested by SF only using setLayerComposisionType()
+ *
+ * It will not be changed if applyDisplayChanges() is called.
+ */
+ int32_t mRequestedCompositionType;
+
+ /**
* Composition type that is used by HAL
* (ex: COMPOSITION_G2D)
*/
@@ -127,7 +140,7 @@ class ExynosLayer : public ExynosMPPSource {
/**
* Update rate for using client composition.
*/
- uint32_t mFps;
+ float mFps;
/**
* Assign priority, when priority changing is needded by order infomation in mGeometryChanged
@@ -163,6 +176,8 @@ class ExynosLayer : public ExynosMPPSource {
uint32_t mFrameCount;
uint32_t mLastFrameCount;
nsecs_t mLastFpsTime;
+ uint32_t mNextLastFrameCount;
+ nsecs_t mNextLastFpsTime;
/**
* Previous buffer's handle
@@ -174,6 +189,8 @@ class ExynosLayer : public ExynosMPPSource {
*/
buffer_handle_t mLayerBuffer;
+ nsecs_t mLastUpdateTime;
+
/**
* Surface Damage
*/
@@ -261,9 +278,9 @@ class ExynosLayer : public ExynosMPPSource {
*/
int32_t setCompositionType(int32_t type);
- uint32_t checkFps();
+ float checkFps(bool increaseCount);
- uint32_t getFps();
+ float getFps();
int32_t doPreProcess();
@@ -458,7 +475,7 @@ class ExynosLayer : public ExynosMPPSource {
int32_t setSrcExynosImage(exynos_image *src_img);
int32_t setDstExynosImage(exynos_image *dst_img);
int32_t resetAssignedResource();
- bool checkDownscaleCap(uint32_t btsRefreshRate);
+ bool checkBtsCap(const uint32_t btsRefreshRate);
void setSrcAcquireFence();
@@ -471,6 +488,18 @@ class ExynosLayer : public ExynosMPPSource {
return ((mLayerBuffer != NULL) &&
isFormatYUV(VendorGraphicBufferMeta::get_internal_format(mLayerBuffer)));
}
+ bool isLayerHasAlphaChannel() {
+ return ((mLayerBuffer != NULL) &&
+ formatHasAlphaChannel(
+ VendorGraphicBufferMeta::get_internal_format(mLayerBuffer)));
+ }
+ bool isLayerOpaque() {
+ return (!isLayerHasAlphaChannel() &&
+ std::fabs(mPlaneAlpha - 1.0f) <= std::numeric_limits<float>::epsilon());
+ }
+ bool needClearClientTarget() {
+ return (mOverlayPriority >= ePriorityHigh && isLayerOpaque());
+ }
size_t getDisplayFrameArea() { return HEIGHT(mDisplayFrame) * WIDTH(mDisplayFrame); }
void setGeometryChanged(uint64_t changedBit);
void clearGeometryChanged() {mGeometryChanged = 0;};
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
index 1df6fe9..eab4cd1 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
@@ -236,12 +236,19 @@ void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleEvent(uint64_t times
display->handleHotplugEvent();
}
-void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleHistogramEvent(void *bin) {
- ExynosDisplay *primaryDisplay = mExynosDevice->getDisplay(HWC_DISPLAY_PRIMARY);
- if (primaryDisplay != NULL) {
- ExynosDisplayDrmInterface *displayInterface =
- static_cast<ExynosDisplayDrmInterface *>(primaryDisplay->mDisplayInterface.get());
- displayInterface->setHistogramData(bin);
+void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleHistogramEvent(uint32_t crtc_id,
+ void *bin) {
+ ExynosDisplayDrmInterface *displayInterface;
+ DrmProperty crtc;
+ uint32_t id;
+
+ for (auto display : mExynosDevice->mDisplays) {
+ displayInterface =
+ static_cast<ExynosDisplayDrmInterface *>(display->mDisplayInterface.get());
+ id = displayInterface->getCrtcId();
+ if (id == crtc_id) {
+ displayInterface->setHistogramData(bin);
+ }
}
}
@@ -255,7 +262,7 @@ void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleTUIEvent() {
} else {
/* Received TUI Exit event */
if (mExynosDevice->isInTUI()) {
- mExynosDevice->onRefresh();
+ mExynosDevice->onRefreshDisplays();
mExynosDevice->exitFromTUI();
ALOGV("%s:: DRM device out TUI", __func__);
}
@@ -305,3 +312,12 @@ void ExynosDeviceDrmInterface::ExynosDrmEventHandler::handleIdleEnterEvent(char
primaryDisplay->handleDisplayIdleEnter(idleTeVrefresh);
}
}
+
+int32_t ExynosDeviceDrmInterface::registerSysfsEventHandler(
+ std::shared_ptr<DrmSysfsEventHandler> handler) {
+ return mDrmDevice->event_listener()->RegisterSysfsHandler(std::move(handler));
+}
+
+int32_t ExynosDeviceDrmInterface::unregisterSysfsEventHandler(int sysfsFd) {
+ return mDrmDevice->event_listener()->UnRegisterSysfsHandler(sysfsFd);
+}
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h
index 3e7fbbb..69fc4f0 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h
@@ -31,6 +31,10 @@ class ExynosDeviceDrmInterface : public ExynosDeviceInterface {
virtual int32_t initDisplayInterface(
std::unique_ptr<ExynosDisplayInterface> &dispInterface) override;
virtual void updateRestrictions() override;
+ virtual int32_t registerSysfsEventHandler(
+ std::shared_ptr<DrmSysfsEventHandler> handler) override;
+ virtual int32_t unregisterSysfsEventHandler(int sysfsFd) override;
+
protected:
class ExynosDrmEventHandler : public DrmEventHandler,
public DrmHistogramEventHandler,
@@ -38,7 +42,7 @@ class ExynosDeviceDrmInterface : public ExynosDeviceInterface {
public DrmPanelIdleEventHandler {
public:
void handleEvent(uint64_t timestamp_us) override;
- void handleHistogramEvent(void *bin) override;
+ void handleHistogramEvent(uint32_t crtc_id, void *bin) override;
void handleTUIEvent() override;
void handleIdleEnterEvent(char const *event) override;
void init(ExynosDevice *exynosDevice, DrmDevice *drmDevice);
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp
index eb54aca..fd200e3 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp
@@ -27,9 +27,7 @@
#include "ExynosResourceManager.h"
#include "ExynosResourceRestriction.h"
-#ifndef USE_MODULE_ATTR
-extern feature_support_t feature_table[];
-#endif
+using namespace SOC_VERSION;
void ExynosDeviceInterface::printDppRestriction(struct hwc_dpp_ch_restriction res)
{
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h
index 747f016..dd976b0 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.h
@@ -17,8 +17,9 @@
#ifndef _EXYNOSDEVICEINTERFACE_H
#define _EXYNOSDEVICEINTERFACE_H
-#include "ExynosHWCHelper.h"
#include "ExynosDisplayInterface.h"
+#include "ExynosHWCHelper.h"
+#include "drmeventlistener.h"
struct hwc_dpp_size_range {
uint32_t min;
@@ -82,12 +83,21 @@ class ExynosDeviceInterface {
virtual ~ExynosDeviceInterface(){};
virtual void init(ExynosDevice *exynosDevice) = 0;
virtual int32_t initDisplayInterface(
- std::unique_ptr<ExynosDisplayInterface> &dispInterface)
- { return 0;};
+ std::unique_ptr<ExynosDisplayInterface> __unused &dispInterface) {
+ return 0;
+ };
/* Fill mDPUInfo according to interface type */
virtual void updateRestrictions() = 0;
virtual bool getUseQuery() { return mUseQuery; };
+ virtual int32_t registerSysfsEventHandler(
+ std::shared_ptr<DrmSysfsEventHandler> __unused handler) {
+ return android::INVALID_OPERATION;
+ }
+ virtual int32_t unregisterSysfsEventHandler(int __unused sysfsFd) {
+ return android::INVALID_OPERATION;
+ }
+
uint32_t getNumDPPChs() { return mDPUInfo.dpuInfo.dpp_chs.size(); };
uint32_t getNumSPPChs() { return mDPUInfo.dpuInfo.spp_chs.size(); };
uint32_t getSPPChId(uint32_t index) { return mDPUInfo.dpuInfo.spp_chs.at(index).id; };
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
index 2e5e4e1..f8ca948 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
@@ -30,8 +30,11 @@
#include "BrightnessController.h"
#include "ExynosHWCDebug.h"
#include "ExynosHWCHelper.h"
+#include "ExynosLayer.h"
+#include "ExynosPrimaryDisplay.h"
using namespace std::chrono_literals;
+using namespace SOC_VERSION;
constexpr uint32_t MAX_PLANE_NUM = 3;
constexpr uint32_t CBCR_INDEX = 1;
@@ -117,21 +120,26 @@ bool FramebufferManager::validateLayerInfo(uint32_t state, uint32_t drmFormat,
return true;
}
-bool FramebufferManager::checkShrink() {
+void FramebufferManager::checkShrink() {
Mutex::Autolock lock(mMutex);
mCacheShrinkPending = mCachedLayerBuffers.size() > MAX_CACHED_LAYERS;
- return mCacheShrinkPending;
+ mCacheM2mSecureShrinkPending =
+ mCachedM2mSecureLayerBuffers.size() > MAX_CACHED_M2M_SECURE_LAYERS;
}
void FramebufferManager::cleanup(const ExynosLayer *layer) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
- if (auto it = mCachedLayerBuffers.find(layer); it != mCachedLayerBuffers.end()) {
- mCleanBuffers.splice(mCleanBuffers.end(), std::move(it->second));
- mCachedLayerBuffers.erase(it);
- }
+ auto clean = [&](std::map<const ExynosLayer *, FBList> &layerBuffs) {
+ if (auto it = layerBuffs.find(layer); it != layerBuffs.end()) {
+ mCleanBuffers.splice(mCleanBuffers.end(), std::move(it->second));
+ layerBuffs.erase(it);
+ }
+ };
+ clean(mCachedLayerBuffers);
+ clean(mCachedM2mSecureLayerBuffers);
}
void FramebufferManager::removeFBsThreadRoutine()
@@ -158,6 +166,7 @@ int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint
uint32_t bpp = 0;
uint32_t bufferNum, planeNum = 0;
uint32_t bufWidth, bufHeight = 0;
+ bool isM2mSecureLayer = (config.protection && config.layer && config.layer->mM2mMPP);
DrmArray<uint32_t> pitches = {0};
DrmArray<uint32_t> offsets = {0};
DrmArray<uint64_t> modifiers = {0};
@@ -197,7 +206,7 @@ int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint
return -EINVAL;
}
- fbId = findCachedFbId(config.layer,
+ fbId = findCachedFbId(config.layer, isM2mSecureLayer,
[bufferDesc = Framebuffer::BufferDesc{config.buffer_id, drmFormat,
config.protection}](
auto &buffer) { return buffer->bufferDesc == bufferDesc; });
@@ -256,7 +265,7 @@ int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint
handles[0] = 0xff000000;
bpp = getBytePerPixelOfPrimaryPlane(HAL_PIXEL_FORMAT_BGRA_8888);
pitches[0] = config.dst.w * bpp;
- fbId = findCachedFbId(config.layer,
+ fbId = findCachedFbId(config.layer, isM2mSecureLayer,
[colorDesc = Framebuffer::SolidColorDesc{bufWidth, bufHeight}](
auto &buffer) { return buffer->colorDesc == colorDesc; });
if (fbId != 0) {
@@ -288,11 +297,14 @@ int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint
if (config.layer || config.buffer_id) {
Mutex::Autolock lock(mMutex);
- auto &cachedBuffers = mCachedLayerBuffers[config.layer];
- if (cachedBuffers.size() > MAX_CACHED_BUFFERS_PER_LAYER) {
- ALOGW("FBManager: cached buffers size %zu exceeds limitation while adding fbId %d",
- cachedBuffers.size(), fbId);
- printExynosLayer(config.layer);
+ auto &cachedBuffers = (!isM2mSecureLayer) ? mCachedLayerBuffers[config.layer]
+ : mCachedM2mSecureLayerBuffers[config.layer];
+ auto maxCachedBufferSize = (!isM2mSecureLayer) ? MAX_CACHED_BUFFERS_PER_LAYER
+ : MAX_CACHED_M2M_SECURE_BUFFERS_PER_LAYER;
+
+ if (cachedBuffers.size() > maxCachedBufferSize) {
+ ALOGW("FBManager: cached buffers size %zu exceeds limitation(%zu) while adding fbId %d",
+ cachedBuffers.size(), maxCachedBufferSize, fbId);
mCleanBuffers.splice(mCleanBuffers.end(), cachedBuffers);
}
@@ -306,6 +318,7 @@ int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint
Framebuffer::BufferDesc{config.buffer_id, drmFormat,
config.protection}));
mHasSecureFramebuffer |= (isFramebuffer(config.layer) && config.protection);
+ mHasM2mSecureLayerBuffer |= isM2mSecureLayer;
}
} else {
ALOGW("FBManager: possible leakage fbId %d was created", fbId);
@@ -314,7 +327,7 @@ int32_t FramebufferManager::getBuffer(const exynos_win_config_data &config, uint
return 0;
}
-void FramebufferManager::flip(bool hasSecureFrameBuffer) {
+void FramebufferManager::flip(const bool hasSecureFrameBuffer, const bool hasM2mSecureLayerBuffer) {
bool needCleanup = false;
{
Mutex::Autolock lock(mMutex);
@@ -322,6 +335,10 @@ void FramebufferManager::flip(bool hasSecureFrameBuffer) {
if (!hasSecureFrameBuffer) {
destroySecureFramebufferLocked();
}
+
+ if (!hasM2mSecureLayerBuffer) {
+ destroyM2mSecureLayerBufferLocked();
+ }
needCleanup = mCleanBuffers.size() > 0;
}
@@ -334,6 +351,7 @@ void FramebufferManager::releaseAll()
{
Mutex::Autolock lock(mMutex);
mCachedLayerBuffers.clear();
+ mCachedM2mSecureLayerBuffers.clear();
mCleanBuffers.clear();
}
@@ -351,31 +369,50 @@ void FramebufferManager::freeBufHandle(uint32_t handle) {
}
}
-void FramebufferManager::markInuseLayerLocked(const ExynosLayer *layer) {
- if (mCacheShrinkPending) {
+void FramebufferManager::markInuseLayerLocked(const ExynosLayer *layer,
+ const bool isM2mSecureLayer) {
+ if (!isM2mSecureLayer && mCacheShrinkPending) {
mCachedLayersInuse.insert(layer);
}
-}
-void FramebufferManager::destroyUnusedLayersLocked() {
- if (!mCacheShrinkPending || mCachedLayersInuse.size() == mCachedLayerBuffers.size()) {
- mCachedLayersInuse.clear();
- return;
+ if (isM2mSecureLayer && mCacheM2mSecureShrinkPending) {
+ mCachedM2mSecureLayersInuse.insert(layer);
}
+}
- ALOGW("FBManager: shrink cached layers from %zu to %zu", mCachedLayerBuffers.size(),
- mCachedLayersInuse.size());
+void FramebufferManager::destroyUnusedLayersLocked() {
+ auto destroyUnusedLayers =
+ [&](const bool &cacheShrinkPending, std::set<const ExynosLayer *> &cachedLayersInuse,
+ std::map<const ExynosLayer *, FBList> &cachedLayerBuffers) -> bool {
+ if (!cacheShrinkPending || cachedLayersInuse.size() == cachedLayerBuffers.size()) {
+ cachedLayersInuse.clear();
+ return false;
+ }
- for (auto layer = mCachedLayerBuffers.begin(); layer != mCachedLayerBuffers.end();) {
- if (mCachedLayersInuse.find(layer->first) == mCachedLayersInuse.end()) {
- mCleanBuffers.splice(mCleanBuffers.end(), std::move(layer->second));
- layer = mCachedLayerBuffers.erase(layer);
- } else {
- ++layer;
+ for (auto layer = cachedLayerBuffers.begin(); layer != cachedLayerBuffers.end();) {
+ if (cachedLayersInuse.find(layer->first) == cachedLayersInuse.end()) {
+ mCleanBuffers.splice(mCleanBuffers.end(), std::move(layer->second));
+ layer = cachedLayerBuffers.erase(layer);
+ } else {
+ ++layer;
+ }
}
+ cachedLayersInuse.clear();
+ return true;
+ };
+
+ auto cachedLayerSize = mCachedLayerBuffers.size();
+ if (destroyUnusedLayers(mCacheShrinkPending, mCachedLayersInuse, mCachedLayerBuffers)) {
+ ALOGW("FBManager: shrink cached layers from %zu to %zu", cachedLayerSize,
+ mCachedLayerBuffers.size());
}
- mCachedLayersInuse.clear();
+ cachedLayerSize = mCachedM2mSecureLayerBuffers.size();
+ if (destroyUnusedLayers(mCacheM2mSecureShrinkPending, mCachedM2mSecureLayersInuse,
+ mCachedM2mSecureLayerBuffers)) {
+ ALOGW("FBManager: shrink cached M2M secure layers from %zu to %zu", cachedLayerSize,
+ mCachedM2mSecureLayerBuffers.size());
+ }
}
void FramebufferManager::destroySecureFramebufferLocked() {
@@ -401,6 +438,22 @@ void FramebufferManager::destroySecureFramebufferLocked() {
}
}
+void FramebufferManager::destroyM2mSecureLayerBufferLocked() {
+ if (!mHasM2mSecureLayerBuffer) {
+ return;
+ }
+
+ mHasM2mSecureLayerBuffer = false;
+
+ for (auto &layer : mCachedM2mSecureLayerBuffers) {
+ auto &bufferList = layer.second;
+ if (bufferList.size()) {
+ mCleanBuffers.splice(mCleanBuffers.end(), bufferList, bufferList.begin(),
+ bufferList.end());
+ }
+ }
+}
+
void ExynosDisplayDrmInterface::destroyLayer(ExynosLayer *layer) {
mFBManager.cleanup(layer);
}
@@ -424,7 +477,8 @@ int32_t ExynosDisplayDrmInterface::getDefaultModeId(int32_t *modeId) {
return NO_ERROR;
}
-ExynosDisplayDrmInterface::ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay)
+ExynosDisplayDrmInterface::ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay):
+ mMonitorDescription{0}
{
mType = INTERFACE_TYPE_DRM;
init(exynosDisplay);
@@ -447,6 +501,7 @@ ExynosDisplayDrmInterface::~ExynosDisplayDrmInterface()
void ExynosDisplayDrmInterface::init(ExynosDisplay *exynosDisplay)
{
mExynosDisplay = exynosDisplay;
+ mDisplayTraceName = mExynosDisplay->mDisplayTraceName;
mDrmDevice = NULL;
mDrmCrtc = NULL;
mDrmConnector = NULL;
@@ -592,6 +647,27 @@ void ExynosDisplayDrmInterface::updateMountOrientation()
ALOGW("%s ignore unrecoganized orientation %" PRId64, __func__, drmOrientation);
}
+void ExynosDisplayDrmInterface::parseRCDId(const DrmProperty &property) {
+ if (mExynosDisplay->mType != HWC_DISPLAY_PRIMARY) {
+ ALOGW("%s invalid display type: %d", __func__, mExynosDisplay->mType);
+ return;
+ }
+
+ if (property.id() == 0) {
+ static_cast<ExynosPrimaryDisplay *>(mExynosDisplay)->mRcdId = -1;
+ return;
+ }
+
+ auto [err, rcd_id] = property.value();
+ if (err < 0) {
+ ALOGW("%s failed to get drm prop value", __func__);
+ return;
+ }
+
+ if (getSpecialChannelId(rcd_id) >= 0)
+ static_cast<ExynosPrimaryDisplay *>(mExynosDisplay)->mRcdId = rcd_id;
+}
+
uint32_t ExynosDisplayDrmInterface::getDrmDisplayId(uint32_t type, uint32_t index)
{
return type+index;
@@ -661,7 +737,7 @@ int32_t ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice)
getLowPowerDrmModeModeInfo();
- mDrmVSyncWorker.Init(mDrmDevice, drmDisplayId);
+ mDrmVSyncWorker.Init(mDrmDevice, drmDisplayId, mDisplayTraceName);
mDrmVSyncWorker.RegisterCallback(std::shared_ptr<VsyncCallback>(this));
if (!mDrmDevice->planes().empty()) {
@@ -678,6 +754,8 @@ int32_t ExynosDisplayDrmInterface::initDrmDevice(DrmDevice *drmDevice)
parseMipiSyncEnums(mDrmConnector->mipi_sync());
updateMountOrientation();
+ if (mExynosDisplay->mType == HWC_DISPLAY_PRIMARY) parseRCDId(mDrmCrtc->rcd_plane_id_property());
+
if (mExynosDisplay->mBrightnessController &&
mExynosDisplay->mBrightnessController->initDrm(*mDrmDevice, *mDrmConnector)) {
ALOGW("%s failed to init brightness controller", __func__);
@@ -715,13 +793,37 @@ void ExynosDisplayDrmInterface::Callback(
if (!mExynosDisplay->mPlugState || !mVsyncCallback.getVSyncEnabled()) {
return;
}
+
+ // Refresh rate during enabling LHBM might be different from the one SF expects.
+ // HWC just reports the SF expected Vsync to make UI smoothness consistent even if
+ // HWC runs at different refresh rate temporarily.
+ if (!mExynosDisplay->isConfigSettingEnabled()) {
+ int64_t pendingPeriodNs =
+ mExynosDisplay->getVsyncPeriod(mExynosDisplay->mPendingConfig);
+ int64_t activePeriodNs = mExynosDisplay->getVsyncPeriod(mExynosDisplay->mActiveConfig);
+ if (pendingPeriodNs && mExynosDisplay->mLastVsyncTimestamp) {
+ if (activePeriodNs > pendingPeriodNs) {
+ DISPLAY_DRM_LOGW("wrong vsync period: %" PRId64 "us (active), %" PRId64
+ "us (pending)",
+ activePeriodNs / 1000, pendingPeriodNs / 1000);
+ } else if (activePeriodNs != pendingPeriodNs) {
+ int64_t deltaNs = timestamp - mExynosDisplay->mLastVsyncTimestamp;
+ if (deltaNs < (pendingPeriodNs - ms2ns(2))) {
+ DISPLAY_DRM_LOGI("skip mismatching Vsync callback, delta=%" PRId64 "us",
+ deltaNs / 1000);
+ return;
+ }
+ }
+ }
+ }
+ mExynosDisplay->mLastVsyncTimestamp = timestamp;
}
ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
if (exynosDevice->onVsync_2_4(mExynosDisplay->mDisplayId, timestamp,
mExynosDisplay->mVsyncPeriod)) {
- ATRACE_INT(vsyncPeriodTag, static_cast<int32_t>(mExynosDisplay->mVsyncPeriod));
+ DISPLAY_ATRACE_INT(vsyncPeriodTag, static_cast<int32_t>(mExynosDisplay->mVsyncPeriod));
return;
}
@@ -819,7 +921,7 @@ int32_t ExynosDisplayDrmInterface::setVsyncEnabled(uint32_t enabled)
ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
if (exynosDevice->isCallbackAvailable(HWC2_CALLBACK_VSYNC_2_4)) {
- ATRACE_INT(vsyncPeriodTag, 0);
+ DISPLAY_ATRACE_INT(vsyncPeriodTag, 0);
}
return NO_ERROR;
@@ -832,23 +934,41 @@ int32_t ExynosDisplayDrmInterface::chosePreferredConfig()
if (err != HWC2_ERROR_NONE || !num_configs)
return err;
- hwc2_config_t config;
- int32_t bootConfig;
- err = mExynosDisplay->getPreferredDisplayConfigInternal(&bootConfig);
- if (err == HWC2_ERROR_NONE) {
- config = static_cast<hwc2_config_t>(bootConfig);
+ int32_t config = -1;
+ char modeStr[PROPERTY_VALUE_MAX] = "\0";
+ int32_t width = 0, height = 0, fps = 0;
+ if (property_get("vendor.display.preferred_mode", modeStr, "") > 0 &&
+ sscanf(modeStr, "%dx%d@%d", &width, &height, &fps) == 3) {
+ err = mExynosDisplay->lookupDisplayConfigs(width, height, fps, &config);
} else {
- config = mDrmConnector->get_preferred_mode_id();
+ err = HWC2_ERROR_BAD_CONFIG;
}
- ALOGI("Preferred mode id: %d, state: %d", config, mDrmConnector->state());
- if ((err = setActiveConfig(config)) < 0) {
- ALOGE("failed to set default config, err %d", err);
- return err;
+ const int32_t drmPreferredConfig = mDrmConnector->get_preferred_mode_id();
+ if (err != HWC2_ERROR_NONE) {
+ config = drmPreferredConfig;
}
+ ALOGI("Preferred mode id: %d(%s), state: %d", config, modeStr, mDrmConnector->state());
- mExynosDisplay->updateInternalDisplayConfigVariables(config);
- return err;
+ auto &configs = mExynosDisplay->mDisplayConfigs;
+ if (config != drmPreferredConfig &&
+ (configs[config].width != configs[drmPreferredConfig].width ||
+ configs[config].height != configs[drmPreferredConfig].height)) {
+ // HWC cannot send a resolution change commit here until 1st frame update because of
+ // some panels requirement. Therefore, it calls setActiveConfigWithConstraints() help
+ // set mDesiredModeState correctly, and then trigger modeset in the 1s frame update.
+ if ((err = setActiveConfigWithConstraints(config)) < 0) {
+ ALOGE("failed to setActiveConfigWithConstraints(), err %d", err);
+ return err;
+ }
+ } else {
+ if ((err = setActiveConfig(config)) < 0) {
+ ALOGE("failed to set default config, err %d", err);
+ return err;
+ }
+ }
+
+ return mExynosDisplay->updateInternalDisplayConfigVariables(config);
}
int32_t ExynosDisplayDrmInterface::getDisplayConfigs(
@@ -876,11 +996,12 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs(
/* key: (width<<32 | height) */
std::map<uint64_t, uint32_t> groupIds;
uint32_t groupId = 0;
- uint32_t min_vsync_period = UINT_MAX;
+ float peakRr = -1;
for (const DrmMode &mode : mDrmConnector->modes()) {
displayConfigs_t configs;
- configs.vsyncPeriod = nsecsPerSec/ mode.v_refresh();
+ float rr = mode.v_refresh();
+ configs.vsyncPeriod = nsecsPerSec / rr;
configs.width = mode.h_display();
configs.height = mode.v_display();
uint64_t key = ((uint64_t)configs.width<<32) | configs.height;
@@ -897,14 +1018,15 @@ int32_t ExynosDisplayDrmInterface::getDisplayConfigs(
configs.Xdpi = mm_width ? (mode.h_display() * kUmPerInch) / mm_width : -1;
// Dots per 1000 inches
configs.Ydpi = mm_height ? (mode.v_display() * kUmPerInch) / mm_height : -1;
- // find min vsync period
- if (configs.vsyncPeriod <= min_vsync_period) min_vsync_period = configs.vsyncPeriod;
+ // find peak rr
+ if (rr > peakRr)
+ peakRr = rr;
mExynosDisplay->mDisplayConfigs.insert(std::make_pair(mode.id(), configs));
ALOGD("config group(%d), w(%d), h(%d), vsync(%d), xdpi(%d), ydpi(%d)",
configs.groupId, configs.width, configs.height,
configs.vsyncPeriod, configs.Xdpi, configs.Ydpi);
}
- mExynosDisplay->setMinDisplayVsyncPeriod(min_vsync_period);
+ mExynosDisplay->setPeakRefreshRate(peakRr);
}
uint32_t num_modes = static_cast<uint32_t>(mDrmConnector->modes().size());
@@ -947,7 +1069,12 @@ int32_t ExynosDisplayDrmInterface::getDisplayVsyncPeriod(hwc2_vsync_period_t* ou
int32_t ExynosDisplayDrmInterface::getConfigChangeDuration()
{
- /* TODO: Get from driver */
+ const auto [ret, duration] = mDrmConnector->vrr_switch_duration().value();
+
+ if (!ret && duration > 0) {
+ return duration;
+ }
+
return 2;
};
@@ -1055,6 +1182,7 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints(
{
ALOGD("%s:: %s config(%d) test(%d)", __func__, mExynosDisplay->mDisplayName.string(), config,
test);
+
auto mode = std::find_if(mDrmConnector->modes().begin(), mDrmConnector->modes().end(),
[config](DrmMode const &m) { return m.id() == config;});
if (mode == mDrmConnector->modes().end()) {
@@ -1071,7 +1199,7 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints(
return HWC2_ERROR_NONE;
}
- if (mDesiredModeState.needs_modeset) {
+ if (mDesiredModeState.needsModeSet()) {
ALOGD("Previous mode change request is not applied");
}
@@ -1085,34 +1213,46 @@ int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints(
return HWC2_ERROR_BAD_CONFIG;
}
}
- if (test) {
- if ((ret = setDisplayMode(drmReq, modeBlob? modeBlob : mDesiredModeState.blob_id)) < 0) {
- HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode",
- __func__);
- return ret;
- }
- ret = drmReq.commit(DRM_MODE_ATOMIC_TEST_ONLY, true);
- if (ret) {
- drmReq.addOldBlob(modeBlob);
- HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=%d in applyDisplayMode()\n",
- __func__, ret);
- return ret;
+ const auto isResSwitch =
+ (mActiveModeState.blob_id != 0) && mActiveModeState.isFullModeSwitch(*mode);
+
+ if (!test) {
+ if (modeBlob) { /* only replace desired mode if it has changed */
+ mDesiredModeState.setMode(*mode, modeBlob, drmReq);
+ if (mExynosDisplay->mOperationRateManager) {
+ mExynosDisplay->mOperationRateManager->onConfig(config);
+ }
+ DISPLAY_DRM_LOGI("%s: config(%d)", __func__, config);
+ } else {
+ ALOGD("%s:: same desired mode %d", __func__, config);
}
} else {
- mDesiredModeState.needs_modeset = true;
- }
+ if (!isResSwitch) {
+ ret = setDisplayMode(drmReq, modeBlob ? modeBlob : mDesiredModeState.blob_id);
+ if (ret < 0) {
+ HWC_LOGE(mExynosDisplay, "%s: Fail to apply display mode", __func__);
+ return ret;
+ }
+ ret = drmReq.commit(DRM_MODE_ATOMIC_TEST_ONLY, true);
+ if (ret) {
+ drmReq.addOldBlob(modeBlob);
+ HWC_LOGE(mExynosDisplay,
+ "%s:: Failed to commit pset ret=%d in applyDisplayMode()\n", __func__,
+ ret);
+ return ret;
+ }
+ }
- if (modeBlob != 0) {
- mDesiredModeState.setMode(*mode, modeBlob, drmReq);
+ if (modeBlob) {
+ mDrmDevice->DestroyPropertyBlob(modeBlob);
+ }
}
return HWC2_ERROR_NONE;
}
int32_t ExynosDisplayDrmInterface::setActiveDrmMode(DrmMode const &mode) {
/* Don't skip when power was off */
- if (!(mExynosDisplay->mSkipFrame) &&
- (mActiveModeState.blob_id != 0) &&
- (mActiveModeState.mode.id() == mode.id()) &&
- (mActiveModeState.needs_modeset == false)) {
+ if (!(mExynosDisplay->mSkipFrame) && (mActiveModeState.blob_id != 0) &&
+ (mActiveModeState.mode.id() == mode.id()) && !mActiveModeState.needsModeSet()) {
ALOGD("%s:: same mode %d", __func__, mode.id());
return HWC2_ERROR_NONE;
}
@@ -1130,16 +1270,7 @@ int32_t ExynosDisplayDrmInterface::setActiveDrmMode(DrmMode const &mode) {
uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
bool reconfig = false;
- if ((mActiveModeState.blob_id != 0) &&
- ((mode.h_display() != mActiveModeState.mode.h_display()) ||
- (mode.v_display() != mActiveModeState.mode.v_display()))) {
- ret = clearDisplayPlanes(drmReq);
- if (ret != HWC2_ERROR_NONE) {
- HWC_LOGE(mExynosDisplay, "%s: Failed to clear planes due to resolution change",
- __func__);
- } else {
- ALOGD("%s: switching display resolution, clearing planes", __func__);
- }
+ if (mActiveModeState.isFullModeSwitch(mode)) {
reconfig = true;
}
@@ -1159,7 +1290,7 @@ int32_t ExynosDisplayDrmInterface::setActiveDrmMode(DrmMode const &mode) {
mDrmConnector->set_active_mode(mode);
mActiveModeState.setMode(mode, modeBlob, drmReq);
- mActiveModeState.needs_modeset = false;
+ mActiveModeState.clearPendingModeState();
if (reconfig) {
mDrmConnector->ResetLpMode();
@@ -1177,16 +1308,30 @@ int32_t ExynosDisplayDrmInterface::setActiveConfig(hwc2_config_t config) {
return HWC2_ERROR_BAD_CONFIG;
}
+ if (mExynosDisplay->mOperationRateManager) {
+ mExynosDisplay->mOperationRateManager->onConfig(config);
+ }
+
mExynosDisplay->updateAppliedActiveConfig(config, systemTime(SYSTEM_TIME_MONOTONIC));
if (!setActiveDrmMode(*mode)) {
- ALOGI("%s:: %s config(%d)", __func__, mExynosDisplay->mDisplayName.string(), config);
+ DISPLAY_DRM_LOGI("%s: config(%d)", __func__, config);
} else {
- ALOGE("%s:: %s config(%d) failed", __func__, mExynosDisplay->mDisplayName.string(), config);
+ DISPLAY_DRM_LOGE("%s: config(%d) failed", __func__, config);
}
return 0;
}
+int32_t ExynosDisplayDrmInterface::getPanelResolution() {
+ for (auto it = mDrmConnector->modes().begin(); it != mDrmConnector->modes().end(); it++) {
+ if (it->h_display() * it->v_display() > mPanelResolutionHsize * mPanelResolutionVsize) {
+ mPanelResolutionHsize = it->h_display();
+ mPanelResolutionVsize = it->v_display();
+ }
+ }
+ return 0;
+}
+
int32_t ExynosDisplayDrmInterface::createModeBlob(const DrmMode &mode,
uint32_t &modeBlob)
{
@@ -1328,11 +1473,11 @@ int32_t ExynosDisplayDrmInterface::updateHdrCapabilities()
int ExynosDisplayDrmInterface::getDeconChannel(ExynosMPP *otfMPP)
{
- int32_t channelNum = sizeof(IDMA_CHANNEL_MAP)/sizeof(dpp_channel_map_t);
+ int32_t channelNum = sizeof(idma_channel_map)/sizeof(dpp_channel_map_t);
for (int i = 0; i < channelNum; i++) {
- if((IDMA_CHANNEL_MAP[i].type == otfMPP->mPhysicalType) &&
- (IDMA_CHANNEL_MAP[i].index == otfMPP->mPhysicalIndex))
- return IDMA_CHANNEL_MAP[i].channel;
+ if((idma_channel_map[i].type == otfMPP->mPhysicalType) &&
+ (idma_channel_map[i].index == otfMPP->mPhysicalIndex))
+ return idma_channel_map[i].channel;
}
return -EINVAL;
}
@@ -1344,6 +1489,7 @@ int32_t ExynosDisplayDrmInterface::setupCommitFromDisplayConfig(
const std::unique_ptr<DrmPlane> &plane,
uint32_t &fbId)
{
+ ATRACE_CALL();
int ret = NO_ERROR;
if (fbId == 0) {
@@ -1603,10 +1749,14 @@ int32_t ExynosDisplayDrmInterface::updateColorSettings(DrmModeAtomicReq &drmReq,
}
auto &plane = mDrmDevice->planes().at(channelId);
- if ((ret = setPlaneColorSetting(drmReq, plane, config)) != 0) {
+ uint32_t solidColor = config.color;
+ if ((ret = setPlaneColorSetting(drmReq, plane, config, solidColor)) != 0) {
HWC_LOGE(mExynosDisplay, "Failed to set plane color setting, config[%zu]", i);
return ret;
}
+ if (config.state == config.WIN_STATE_COLOR && solidColor != config.color) {
+ config.color = solidColor;
+ }
}
}
@@ -1620,11 +1770,16 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
std::unordered_map<uint32_t, uint32_t> planeEnableInfo;
android::String8 result;
bool hasSecureFrameBuffer = false;
+ bool hasM2mSecureLayerBuffer = false;
+ if (mExynosDisplay->isFrameUpdate()) {
+ mFrameCounter++;
+ }
funcReturnCallback retCallback([&]() {
if ((ret == NO_ERROR) && !drmReq.getError()) {
- mFBManager.flip(hasSecureFrameBuffer);
+ mFBManager.flip(hasSecureFrameBuffer, hasM2mSecureLayerBuffer);
} else if (ret == -ENOMEM) {
+ ALOGW("OOM, release all cached buffers by FBManager");
mFBManager.releaseAll();
}
});
@@ -1651,7 +1806,7 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
}
uint64_t mipi_sync_type = 0;
- if (mDesiredModeState.needs_modeset) {
+ if (mDesiredModeState.needsModeSet()) {
if (mExynosDisplay->checkRrCompensationEnabled()) {
mipi_sync_type |=
1 << mMipiSyncEnums[toUnderlying(HalMipiSyncType::HAL_MIPI_CMD_SYNC_REFRESH_RATE)];
@@ -1691,6 +1846,13 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
return ret;
}
+ // Update of color settings could change layer's solid color. So it should
+ // be called before use of layer's solid color.
+ if ((ret = updateColorSettings(drmReq, dqeEnable)) != 0) {
+ HWC_LOGE(mExynosDisplay, "failed to update color settings (%d)", ret);
+ return ret;
+ }
+
for (size_t i = 0; i < mExynosDisplay->mDpuData.configs.size(); i++) {
exynos_win_config_data& config = mExynosDisplay->mDpuData.configs[i];
if ((config.state == config.WIN_STATE_BUFFER) ||
@@ -1714,6 +1876,7 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
return ret;
}
hasSecureFrameBuffer |= (isFramebuffer(config.layer) && config.protection);
+ hasM2mSecureLayerBuffer |= (config.protection && config.layer && config.layer->mM2mMPP);
/* Set this plane is enabled */
planeEnableInfo[plane->id()] = 1;
}
@@ -1721,15 +1884,18 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
for (size_t i = 0; i < mExynosDisplay->mDpuData.rcdConfigs.size(); ++i) {
exynos_win_config_data &config = mExynosDisplay->mDpuData.rcdConfigs[i];
- if (config.state == config.WIN_STATE_RCD) {
- const int channelId = mExynosDisplay->mDevice->getSpecialPlaneId(
- mExynosDisplay->mIndex); // TODO: b/227584297
- auto &plane = mDrmDevice->planes().at(channelId);
- uint32_t fbId = 0;
- if ((ret = setupCommitFromDisplayConfig(drmReq, config, i, plane, fbId)) < 0) {
- HWC_LOGE(mExynosDisplay, "setupCommitFromDisplayConfig failed, config[%zu]", i);
+ if ((config.state == config.WIN_STATE_RCD) &&
+ (mExynosDisplay->mType == HWC_DISPLAY_PRIMARY)) {
+ const int32_t rcdId = static_cast<ExynosPrimaryDisplay *>(mExynosDisplay)->mRcdId;
+ const int32_t channelId = getSpecialChannelId(rcdId);
+ if (channelId >= 0) {
+ auto &plane = mDrmDevice->planes().at(channelId);
+ uint32_t fbId = 0;
+ if ((ret = setupCommitFromDisplayConfig(drmReq, config, i, plane, fbId)) < 0) {
+ HWC_LOGE(mExynosDisplay, "setupCommitFromDisplayConfig failed, config[%zu]", i);
+ }
+ planeEnableInfo[plane->id()] = 1;
}
- planeEnableInfo[plane->id()] = 1;
}
}
@@ -1743,6 +1909,15 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
(exynosMPP->mReservedDisplay != (int32_t)mExynosDisplay->mDisplayId))
continue;
+ if ((exynosMPP == NULL) && (mExynosDisplay->mType == HWC_DISPLAY_PRIMARY) &&
+ (plane->id() != static_cast<ExynosPrimaryDisplay *>(mExynosDisplay)->mRcdId))
+ continue;
+
+ /* If this plane is not supported by the CRTC binded with ExynosDisplay,
+ * it should be disabled by this ExynosDisplay */
+ if (!plane->GetCrtcSupported(*mDrmCrtc))
+ continue;
+
if ((ret = drmReq.atomicAddProperty(plane->id(),
plane->crtc_property(), 0)) < 0)
return ret;
@@ -1759,8 +1934,11 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
if (mExynosDisplay->mBrightnessController) {
bool ghbmSync, lhbmSync, blSync;
+ bool mixedComposition = mExynosDisplay->isMixedComposition()
+ || mExynosDisplay->isPriorFrameMixedCompostion();
ret = mExynosDisplay->mBrightnessController->prepareFrameCommit(*mExynosDisplay,
- *mDrmConnector, drmReq, ghbmSync, lhbmSync, blSync);
+ *mDrmConnector, drmReq, mixedComposition,
+ ghbmSync, lhbmSync, blSync);
if (ret < 0) {
HWC_LOGE(mExynosDisplay, "%s: Fail to config brightness", __func__);
} else {
@@ -1780,7 +1958,7 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
}
uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK;
- if (needModesetForReadback)
+ if (needModesetForReadback || !mDesiredModeState.isSeamless())
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
/* For Histogram */
@@ -1789,17 +1967,16 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
return ret;
}
- if ((ret = updateColorSettings(drmReq, dqeEnable)) != 0) {
- HWC_LOGE(mExynosDisplay, "failed to update color settings (%d)", ret);
- return ret;
- }
-
if (mDrmConnector->mipi_sync().id() && (mipi_sync_type != 0)) {
- ATRACE_NAME("mipi_sync"); // mark this commit
- if ((ret = drmReq.atomicAddProperty(mDrmConnector->id(),
- mDrmConnector->mipi_sync(),
- mipi_sync_type)) < 0) {
- HWC_LOGE(mExynosDisplay, "%s: Fail to set mipi_sync property (%d)", __func__, ret);
+ // skip mipi sync in Doze mode
+ bool inDoze = isDozeModeAvailable() && mDozeDrmMode.id() == mActiveModeState.mode.id();
+ if (!inDoze) {
+ ATRACE_NAME("mipi_sync"); // mark this commit
+ if ((ret = drmReq.atomicAddProperty(mDrmConnector->id(),
+ mDrmConnector->mipi_sync(),
+ mipi_sync_type)) < 0) {
+ HWC_LOGE(mExynosDisplay, "%s: Fail to set mipi_sync property (%d)", __func__, ret);
+ }
}
}
@@ -1839,8 +2016,12 @@ int32_t ExynosDisplayDrmInterface::deliverWinConfigData()
}
}
- if (mDesiredModeState.needs_modeset) {
+ if (mDesiredModeState.needsModeSet()) {
mDesiredModeState.apply(mActiveModeState, drmReq);
+ if (!mActiveModeState.isSeamless()) {
+ mDrmConnector->ResetLpMode();
+ getLowPowerDrmModeModeInfo();
+ }
mVsyncCallback.setDesiredVsyncPeriod(
nsecsPerSec/mActiveModeState.mode.v_refresh());
/* Enable vsync to check vsync period */
@@ -1869,6 +2050,21 @@ int32_t ExynosDisplayDrmInterface::clearDisplayMode(DrmModeAtomicReq &drmReq)
return NO_ERROR;
}
+int32_t ExynosDisplayDrmInterface::triggerClearDisplayPlanes()
+{
+ ATRACE_CALL();
+ DrmModeAtomicReq drmReq(this);
+
+ clearDisplayPlanes(drmReq);
+ int ret = NO_ERROR;
+ if ((ret = drmReq.commit(0, true))) {
+ HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=(%d)\n",
+ __func__, ret);
+ return ret;
+ }
+ return ret;
+}
+
int32_t ExynosDisplayDrmInterface::clearDisplayPlanes(DrmModeAtomicReq &drmReq)
{
int ret = NO_ERROR;
@@ -1882,6 +2078,11 @@ int32_t ExynosDisplayDrmInterface::clearDisplayPlanes(DrmModeAtomicReq &drmReq)
(exynosMPP->mReservedDisplay != (int32_t)mExynosDisplay->mDisplayId))
continue;
+ /* If this plane is not supported by the CRTC binded with ExynosDisplay,
+ * it should not be disabled by this ExynosDisplay */
+ if (!plane->GetCrtcSupported(*mDrmCrtc))
+ continue;
+
if ((ret = drmReq.atomicAddProperty(plane->id(),
plane->crtc_property(), 0)) < 0) {
break;
@@ -1898,6 +2099,9 @@ int32_t ExynosDisplayDrmInterface::clearDisplayPlanes(DrmModeAtomicReq &drmReq)
int32_t ExynosDisplayDrmInterface::clearDisplay(bool needModeClear)
{
+ ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
+ const bool isAsyncOff = needModeClear && exynosDevice->isDispOffAsyncSupported() &&
+ !exynosDevice->hasOtherDisplayOn(mExynosDisplay);
int ret = NO_ERROR;
DrmModeAtomicReq drmReq(this);
@@ -1918,7 +2122,7 @@ int32_t ExynosDisplayDrmInterface::clearDisplay(bool needModeClear)
}
/* Disable ModeSet */
- if (needModeClear) {
+ if (needModeClear && !isAsyncOff) {
if ((ret = clearDisplayMode(drmReq)) < 0) {
HWC_LOGE(mExynosDisplay, "%s: Failed to apply display mode", __func__);
return ret;
@@ -1932,8 +2136,24 @@ int32_t ExynosDisplayDrmInterface::clearDisplay(bool needModeClear)
return ret;
}
- if (needModeClear)
- mActiveModeState.needs_modeset = true;
+ /* During async off we're clearing planes within a single refresh cycle
+ * and then offloading display off asynchronously.
+ */
+ if (isAsyncOff) {
+ if ((ret = clearDisplayMode(drmReq)) < 0) {
+ HWC_LOGE(mExynosDisplay, "%s: Failed to apply display mode", __func__);
+ return ret;
+ }
+
+ ret = drmReq.commit(DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, true);
+ if (ret) {
+ HWC_LOGE(mExynosDisplay, "%s:: Failed to commit pset ret=%d in clearDisplay()\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ if (needModeClear) mActiveModeState.forceModeSet();
return NO_ERROR;
}
@@ -2305,6 +2525,11 @@ int32_t ExynosDisplayDrmInterface::getDisplayFakeEdid(uint8_t &outPort, uint32_t
edid_buf[59] = height & 0xff;
edid_buf[61] = (height >> 4) & 0xf0;
+ if (mMonitorDescription[0] != 0) {
+ /* Descriptor block 3 starts at address 90, data offset is 5 bytes */
+ memcpy(&edid_buf[95], mMonitorDescription.data(), mMonitorDescription.size());
+ }
+
unsigned int sum = std::accumulate(edid_buf.begin(), edid_buf.end() - 1, 0);
edid_buf[127] = (0x100 - (sum & 0xFF)) & 0xFF;
if (outData) {
@@ -2370,3 +2595,16 @@ int32_t ExynosDisplayDrmInterface::getDisplayIdentificationData(
return HWC2_ERROR_NONE;
}
+
+int32_t ExynosDisplayDrmInterface::getSpecialChannelId(uint32_t planeId) {
+ ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
+ for (int i = 0; i < exynosDevice->getSpecialPlaneNum(); i++) {
+ const int32_t channelId = exynosDevice->getSpecialPlaneId(i);
+ auto &plane = mDrmDevice->planes().at(channelId);
+ if (plane->id() == planeId) return channelId;
+ }
+
+ ALOGE("%s: Failed to get RCD planeId.", __func__);
+
+ return -EINVAL;
+}
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
index 6233ef6..3997b0f 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
@@ -31,11 +31,15 @@
#include "ExynosMPP.h"
#include "drmconnector.h"
#include "drmcrtc.h"
+#include "histogram/histogram.h"
#include "vsyncworker.h"
/* Max plane number of buffer object */
#define HWC_DRM_BO_MAX_PLANES 4
+/* Monitor Descriptor data is 13 bytes in VESA EDID Standard */
+#define MONITOR_DESCRIPTOR_DATA_LENGTH 13
+
#ifndef HWC_FORCE_PANIC_PATH
#define HWC_FORCE_PANIC_PATH "/d/dpu/panic"
#endif
@@ -59,7 +63,7 @@ class FramebufferManager {
// layer. Those fbIds will be cleaned up once the layer was destroyed.
int32_t getBuffer(const exynos_win_config_data &config, uint32_t &fbId);
- bool checkShrink();
+ void checkShrink();
void cleanup(const ExynosLayer *layer);
@@ -67,7 +71,7 @@ class FramebufferManager {
// layers after the previous fdIds were update successfully on the
// screen.
// This should be called after the frame update.
- void flip(bool hasSecureFrameBuffer);
+ void flip(const bool hasSecureFrameBuffer, const bool hasM2mSecureLayerBuffer);
// release all currently tracked buffers, this can be called for example when display is turned
// off
@@ -108,7 +112,8 @@ class FramebufferManager {
using FBList = std::list<std::unique_ptr<Framebuffer>>;
template <class UnaryPredicate>
- uint32_t findCachedFbId(const ExynosLayer *layer, UnaryPredicate predicate);
+ uint32_t findCachedFbId(const ExynosLayer *layer, const bool isM2mSecureLayer,
+ UnaryPredicate predicate);
int addFB2WithModifiers(uint32_t state, uint32_t width, uint32_t height, uint32_t drmFormat,
const DrmArray<uint32_t> &handles,
const DrmArray<uint32_t> &pitches,
@@ -122,15 +127,19 @@ class FramebufferManager {
void freeBufHandle(uint32_t handle);
void removeFBsThreadRoutine();
- void markInuseLayerLocked(const ExynosLayer *layer) REQUIRES(mMutex);
+ void markInuseLayerLocked(const ExynosLayer *layer, const bool isM2mSecureLayer)
+ REQUIRES(mMutex);
void destroyUnusedLayersLocked() REQUIRES(mMutex);
void destroySecureFramebufferLocked() REQUIRES(mMutex);
+ void destroyM2mSecureLayerBufferLocked() REQUIRES(mMutex);
int mDrmFd = -1;
- // mCachedLayerBuffers map keep the relationship between Layer and
- // FBList. The map entry will be deleted once the layer is destroyed.
+ // mCachedLayerBuffers map keep the relationship between Layer and FBList.
+ // mCachedM2mSecureLayerBuffers map keep the relationship between M2M secure
+ // Layer and FBList. The map entry will be deleted once the layer is destroyed.
std::map<const ExynosLayer *, FBList> mCachedLayerBuffers;
+ std::map<const ExynosLayer *, FBList> mCachedM2mSecureLayerBuffers;
// mCleanBuffers list keeps fbIds of destroyed layers. Those fbIds will
// be destroyed in mRmFBThread thread.
@@ -139,11 +148,15 @@ class FramebufferManager {
// mCacheShrinkPending is set when we want to clean up unused layers
// in mCachedLayerBuffers. When the flag is set, mCachedLayersInuse will
// keep in-use layers in this frame update. Those unused layers will be
- // freed at the end of the update.
+ // freed at the end of the update. mCacheM2mSecureShrinkPending is same to
+ // mCacheShrinkPending but for mCachedM2mSecureLayerBuffers.
// TODO: have a better way to maintain inuse layers
bool mCacheShrinkPending = false;
+ bool mCacheM2mSecureShrinkPending = false;
bool mHasSecureFramebuffer = false;
+ bool mHasM2mSecureLayerBuffer = false;
std::set<const ExynosLayer *> mCachedLayersInuse;
+ std::set<const ExynosLayer *> mCachedM2mSecureLayersInuse;
std::thread mRmFBThread;
bool mRmFBThreadRunning = false;
@@ -151,7 +164,9 @@ class FramebufferManager {
Mutex mMutex;
static constexpr size_t MAX_CACHED_LAYERS = 16;
+ static constexpr size_t MAX_CACHED_M2M_SECURE_LAYERS = 1;
static constexpr size_t MAX_CACHED_BUFFERS_PER_LAYER = 32;
+ static constexpr size_t MAX_CACHED_M2M_SECURE_BUFFERS_PER_LAYER = 3;
};
inline bool isFramebuffer(const ExynosLayer *layer) {
@@ -159,10 +174,12 @@ inline bool isFramebuffer(const ExynosLayer *layer) {
}
template <class UnaryPredicate>
-uint32_t FramebufferManager::findCachedFbId(const ExynosLayer *layer, UnaryPredicate predicate) {
+uint32_t FramebufferManager::findCachedFbId(const ExynosLayer *layer, const bool isM2mSecureLayer,
+ UnaryPredicate predicate) {
Mutex::Autolock lock(mMutex);
- markInuseLayerLocked(layer);
- const auto &cachedBuffers = mCachedLayerBuffers[layer];
+ markInuseLayerLocked(layer, isM2mSecureLayer);
+ const auto &cachedBuffers =
+ (!isM2mSecureLayer) ? mCachedLayerBuffers[layer] : mCachedM2mSecureLayerBuffers[layer];
const auto it = std::find_if(cachedBuffers.begin(), cachedBuffers.end(), predicate);
return (it != cachedBuffers.end()) ? (*it)->fbId : 0;
}
@@ -293,12 +310,14 @@ class ExynosDisplayDrmInterface :
hwc2_config_t config, bool test = false);
virtual int32_t setDisplayColorSetting(
- ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq)
- { return NO_ERROR;};
+ ExynosDisplayDrmInterface::DrmModeAtomicReq __unused &drmReq) {
+ return NO_ERROR;
+ }
virtual int32_t setPlaneColorSetting(
ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq,
const std::unique_ptr<DrmPlane> &plane,
- const exynos_win_config_data& config)
+ const exynos_win_config_data& config,
+ uint32_t &solidColor)
{ return NO_ERROR;};
virtual void destroyLayer(ExynosLayer *layer) override;
@@ -314,7 +333,18 @@ class ExynosDisplayDrmInterface :
ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) {
return NO_ERROR;
}
- virtual int32_t setHistogramData(void *__unused bin) { return NO_ERROR; }
+ int32_t getFrameCount() { return mFrameCounter; }
+ virtual void registerHistogramInfo(const std::shared_ptr<IDLHistogram> &info) { return; }
+ virtual int32_t setHistogramControl(hidl_histogram_control_t enabled) { return NO_ERROR; }
+ virtual int32_t setHistogramData(void *bin) { return NO_ERROR; }
+ int32_t getActiveModeHDisplay() { return mActiveModeState.mode.h_display(); }
+ int32_t getActiveModeVDisplay() { return mActiveModeState.mode.v_display(); }
+ uint32_t getActiveModeId() { return mActiveModeState.mode.id(); }
+ int32_t panelHsize() { return mPanelResolutionHsize; }
+ int32_t panelVsize() { return mPanelResolutionVsize; }
+ int32_t getPanelResolution();
+ uint32_t getCrtcId() { return mDrmCrtc->id(); }
+ int32_t triggerClearDisplayPlanes();
protected:
enum class HalMipiSyncType : uint32_t {
@@ -325,12 +355,24 @@ class ExynosDisplayDrmInterface :
};
struct ModeState {
- bool needs_modeset = false;
+ enum ModeStateType {
+ MODE_STATE_NONE = 0U,
+ MODE_STATE_REFRESH_RATE = 1U << 0,
+ MODE_STATE_RESOLUTION = 1U << 1,
+ MODE_STATE_FORCE_MODE_SET = 1U << 2,
+ };
DrmMode mode;
uint32_t blob_id = 0;
uint32_t old_blob_id = 0;
void setMode(const DrmMode newMode, const uint32_t modeBlob,
DrmModeAtomicReq &drmReq) {
+ if (newMode.v_refresh() != mode.v_refresh()) {
+ mModeState |= ModeStateType::MODE_STATE_REFRESH_RATE;
+ }
+ if (isFullModeSwitch(newMode)) {
+ mModeState |= ModeStateType::MODE_STATE_RESOLUTION;
+ }
+
drmReq.addOldBlob(old_blob_id);
mode = newMode;
old_blob_id = blob_id;
@@ -344,6 +386,18 @@ class ExynosDisplayDrmInterface :
drmReq.addOldBlob(old_blob_id);
reset();
};
+
+ int32_t mModeState = ModeStateType::MODE_STATE_NONE;
+ void forceModeSet() { mModeState |= ModeStateType::MODE_STATE_FORCE_MODE_SET; }
+ void clearPendingModeState() { mModeState = ModeStateType::MODE_STATE_NONE; }
+ bool needsModeSet() const { return mModeState != ModeStateType::MODE_STATE_NONE; }
+ bool isSeamless() const { return !(mModeState & ModeStateType::MODE_STATE_RESOLUTION); }
+ bool isFullModeSwitch(const DrmMode &newMode) {
+ if ((mode.h_display() != newMode.h_display()) ||
+ (mode.v_display() != newMode.v_display()))
+ return true;
+ return false;
+ }
};
int32_t createModeBlob(const DrmMode &mode, uint32_t &modeBlob);
int32_t setDisplayMode(DrmModeAtomicReq &drmReq, const uint32_t modeBlob);
@@ -369,6 +423,7 @@ class ExynosDisplayDrmInterface :
void parseColorModeEnums(const DrmProperty &property);
void parseMipiSyncEnums(const DrmProperty &property);
void updateMountOrientation();
+ void parseRCDId(const DrmProperty &property);
int32_t setupWritebackCommit(DrmModeAtomicReq &drmReq);
int32_t clearWritebackCommit(DrmModeAtomicReq &drmReq);
@@ -378,6 +433,7 @@ class ExynosDisplayDrmInterface :
int32_t getLowPowerDrmModeModeInfo();
int32_t setActiveDrmMode(DrmMode const &mode);
void setMaxWindowNum(uint32_t num) { mMaxWindowNum = num; };
+ int32_t getSpecialChannelId(uint32_t planeId);
protected:
struct PartialRegionState {
@@ -453,12 +509,17 @@ class ExynosDisplayDrmInterface :
DrmReadbackInfo mReadbackInfo;
FramebufferManager mFBManager;
+ std::array<uint8_t, MONITOR_DESCRIPTOR_DATA_LENGTH> mMonitorDescription;
private:
int32_t getDisplayFakeEdid(uint8_t &outPort, uint32_t &outDataSize, uint8_t *outData);
+ String8 mDisplayTraceName;
DrmMode mDozeDrmMode;
uint32_t mMaxWindowNum = 0;
+ int32_t mFrameCounter = 0;
+ int32_t mPanelResolutionHsize = 0;
+ int32_t mPanelResolutionVsize = 0;
};
#endif
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h b/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h
index d133774..b87c2e2 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayInterface.h
@@ -53,6 +53,7 @@ class ExynosDisplayInterface {
virtual int32_t updateHdrCapabilities();
virtual int32_t deliverWinConfigData() {return NO_ERROR;};
virtual int32_t clearDisplay(bool __unused needModeClear = false) {return NO_ERROR;};
+ virtual int32_t triggerClearDisplayPlanes() { return NO_ERROR; }
virtual int32_t disableSelfRefresh(uint32_t __unused disable) {return NO_ERROR;};
virtual int32_t setForcePanic() {return NO_ERROR;};
virtual int getDisplayFd() {return -1;};
@@ -79,6 +80,7 @@ class ExynosDisplayInterface {
virtual int32_t getDefaultModeId(int32_t* __unused modeId) {
return HWC2_ERROR_UNSUPPORTED;
}
+ virtual uint32_t getActiveModeId() { return UINT_MAX; }
virtual int32_t waitVBlank() { return 0; };
public:
diff --git a/libhwc2.1/libdrmresource/drm/drmconnector.cpp b/libhwc2.1/libdrmresource/drm/drmconnector.cpp
index 3cbd24e..2f9943e 100644
--- a/libhwc2.1/libdrmresource/drm/drmconnector.cpp
+++ b/libhwc2.1/libdrmresource/drm/drmconnector.cpp
@@ -155,6 +155,11 @@ int DrmConnector::Init() {
ALOGE("Could not get panel_idle_support property\n");
}
+ ret = drm_->GetConnectorProperty(*this, "vrr_switch_duration", &vrr_switch_duration_);
+ if (ret) {
+ ALOGE("Could not get vrr_switch_duration property\n");
+ }
+
properties_.push_back(&dpms_property_);
properties_.push_back(&crtc_id_property_);
properties_.push_back(&edid_property_);
@@ -176,6 +181,7 @@ int DrmConnector::Init() {
properties_.push_back(&lhbm_on_);
properties_.push_back(&mipi_sync_);
properties_.push_back(&panel_idle_support_);
+ properties_.push_back(&vrr_switch_duration_);
return 0;
}
@@ -391,6 +397,10 @@ const DrmProperty &DrmConnector::panel_idle_support() const {
return panel_idle_support_;
}
+const DrmProperty &DrmConnector::vrr_switch_duration() const {
+ return vrr_switch_duration_;
+}
+
DrmEncoder *DrmConnector::encoder() const {
return encoder_;
}
diff --git a/libhwc2.1/libdrmresource/drm/drmcrtc.cpp b/libhwc2.1/libdrmresource/drm/drmcrtc.cpp
index 765444b..55cee3c 100644
--- a/libhwc2.1/libdrmresource/drm/drmcrtc.cpp
+++ b/libhwc2.1/libdrmresource/drm/drmcrtc.cpp
@@ -95,6 +95,10 @@ int DrmCrtc::Init() {
ALOGI("Failed to get &histogram_weights property");
if (drm_->GetCrtcProperty(*this, "histogram_threshold", &histogram_threshold_property_))
ALOGI("Failed to get &histogram_threshold property");
+ if (drm_->GetCrtcProperty(*this, "histogram_pos", &histogram_position_property_))
+ ALOGI("Failed to get &histogram_position property");
+ if (drm_->GetCrtcProperty(*this, "rcd_plane_id", &rcd_plane_id_property_))
+ ALOGI("Failed to get &rcd_plane_id property");
properties_.push_back(&active_property_);
properties_.push_back(&mode_property_);
@@ -122,6 +126,9 @@ int DrmCrtc::Init() {
properties_.push_back(&histogram_roi_property_);
properties_.push_back(&histogram_weights_property_);
properties_.push_back(&histogram_threshold_property_);
+ properties_.push_back(&histogram_position_property_);
+
+ properties_.push_back(&rcd_plane_id_property_);
return 0;
}
@@ -255,4 +262,12 @@ const DrmProperty &DrmCrtc::histogram_threshold_property() const {
return histogram_threshold_property_;
}
+const DrmProperty &DrmCrtc::histogram_position_property() const {
+ return histogram_position_property_;
+}
+
+const DrmProperty &DrmCrtc::rcd_plane_id_property() const {
+ return rcd_plane_id_property_;
+}
+
} // namespace android
diff --git a/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp b/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp
index c16b372..bd12d30 100644
--- a/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp
+++ b/libhwc2.1/libdrmresource/drm/drmeventlistener.cpp
@@ -17,19 +17,21 @@
#define LOG_TAG "hwc-drm-event-listener"
#include "drmeventlistener.h"
-#include "drmdevice.h"
-#include <drm/samsung_drm.h>
#include <assert.h>
+#include <drm/samsung_drm.h>
#include <errno.h>
-#include <linux/netlink.h>
-#include <sys/socket.h>
-
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include <inttypes.h>
+#include <linux/netlink.h>
#include <log/log.h>
+#include <sys/socket.h>
+#include <utils/String8.h>
#include <xf86drm.h>
+#include "drmdevice.h"
+
namespace android {
DrmEventListener::DrmEventListener(DrmDevice *drm)
@@ -143,6 +145,43 @@ void DrmEventListener::UnRegisterPanelIdleHandler(DrmPanelIdleEventHandler *hand
panel_idle_handler_ = NULL;
}
+int DrmEventListener::RegisterSysfsHandler(std::shared_ptr<DrmSysfsEventHandler> handler) {
+ if (!handler)
+ return -EINVAL;
+ if (handler->getFd() < 0)
+ return -EINVAL;
+ std::scoped_lock lock(mutex_);
+ if (sysfs_handlers_.find(handler->getFd()) != sysfs_handlers_.end()) {
+ ALOGE("%s: DrmSysfsEventHandler for fd:%d has been added to epoll", __func__, handler->getFd());
+ return -EINVAL;
+ }
+
+ struct epoll_event ev;
+ ev.events = EPOLLPRI;
+ ev.data.fd = handler->getFd();
+ if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, handler->getFd(), &ev) < 0) {
+ ALOGE("%s: Failed to add fd into epoll: %s", __func__, strerror(errno));
+ return -errno;
+ }
+ sysfs_handlers_.emplace(handler->getFd(), std::move(handler));
+ return 0;
+}
+
+int DrmEventListener::UnRegisterSysfsHandler(int sysfs_fd) {
+ std::scoped_lock lock(mutex_);
+ auto it = sysfs_handlers_.find(sysfs_fd);
+ if (it == sysfs_handlers_.end()) {
+ ALOGE("%s: DrmSysfsEventHandler for fd:%d not found", __func__, sysfs_fd);
+ return -EINVAL;
+ }
+ if (epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, sysfs_fd, nullptr) < 0) {
+ ALOGE("%s: Failed to remove fd from epoll: %s", __func__, strerror(errno));
+ return -errno;
+ }
+ sysfs_handlers_.erase(it);
+ return 0;
+}
+
bool DrmEventListener::IsDrmInTUI() {
char buffer[1024];
int ret;
@@ -235,7 +274,8 @@ void DrmEventListener::DRMEventHandler() {
case EXYNOS_DRM_HISTOGRAM_EVENT:
if (histogram_handler_) {
histo = (struct exynos_drm_histogram_event *)e;
- histogram_handler_->handleHistogramEvent((void *)&(histo->bins));
+ histogram_handler_->handleHistogramEvent(histo->crtc_id,
+ (void *)&(histo->bins));
}
break;
case DRM_EVENT_FLIP_COMPLETE:
@@ -266,6 +306,23 @@ void DrmEventListener::TUIEventHandler() {
tui_handler_->handleTUIEvent();
}
+void DrmEventListener::SysfsEventHandler(int fd) {
+ std::shared_ptr<DrmSysfsEventHandler> handler;
+ {
+ std::scoped_lock lock(mutex_);
+ // Copy the shared_ptr to avoid the handler object gets destroyed
+ // while it's handling the event without holding mutex_
+ auto it = sysfs_handlers_.find(fd);
+ if (it != sysfs_handlers_.end())
+ handler = it->second;
+ }
+ if (handler) {
+ handler->handleSysfsEvent();
+ } else {
+ ALOGW("Unhandled sysfs event from fd:%d", fd);
+ }
+}
+
void DrmEventListener::Routine() {
struct epoll_event events[maxFds];
int nfds, n;
@@ -279,11 +336,13 @@ void DrmEventListener::Routine() {
if (events[n].data.fd == uevent_fd_.get()) {
UEventHandler();
} else if (events[n].data.fd == drm_->fd()) {
- DRMEventHandler();
+ DRMEventHandler();
}
} else if (events[n].events & EPOLLPRI) {
if (tuievent_fd_.get() >= 0 && events[n].data.fd == tuievent_fd_.get()) {
TUIEventHandler();
+ } else {
+ SysfsEventHandler(events[n].data.fd);
}
}
}
diff --git a/libhwc2.1/libdrmresource/drm/vsyncworker.cpp b/libhwc2.1/libdrmresource/drm/vsyncworker.cpp
index d2b4a02..bd55d47 100644
--- a/libhwc2.1/libdrmresource/drm/vsyncworker.cpp
+++ b/libhwc2.1/libdrmresource/drm/vsyncworker.cpp
@@ -36,7 +36,6 @@
using namespace std::chrono_literals;
constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
-constexpr auto hwVsyncPeriodTag = "HWVsyncPeriod";
namespace android {
@@ -52,9 +51,12 @@ VSyncWorker::~VSyncWorker() {
Exit();
}
-int VSyncWorker::Init(DrmDevice *drm, int display) {
+int VSyncWorker::Init(DrmDevice *drm, int display, const String8 &display_trace_name) {
drm_ = drm;
display_ = display;
+ display_trace_name_ = display_trace_name;
+ hw_vsync_period_tag_.appendFormat("HWVsyncPeriod for %s", display_trace_name.string());
+ hw_vsync_enabled_tag_.appendFormat("HWCVsync for %s", display_trace_name.string());
return InitWorker();
}
@@ -71,8 +73,8 @@ void VSyncWorker::VSyncControl(bool enabled) {
last_timestamp_ = -1;
Unlock();
- ATRACE_INT("HWCVsync", static_cast<int32_t>(enabled));
- ATRACE_INT64(hwVsyncPeriodTag, 0);
+ ATRACE_INT(hw_vsync_enabled_tag_.string(), static_cast<int32_t>(enabled));
+ ATRACE_INT64(hw_vsync_period_tag_.string(), 0);
Signal();
}
@@ -211,8 +213,8 @@ void VSyncWorker::Routine() {
if (last_timestamp_ >= 0) {
int64_t period = timestamp - last_timestamp_;
- ATRACE_INT64(hwVsyncPeriodTag, period);
- ALOGV("HW vsync period %" PRId64 "ns", period);
+ ATRACE_INT64(hw_vsync_period_tag_.string(), period);
+ ALOGV("HW vsync period %" PRId64 "ns for %s", period, display_trace_name_.string());
}
last_timestamp_ = timestamp;
diff --git a/libhwc2.1/libdrmresource/include/drmconnector.h b/libhwc2.1/libdrmresource/include/drmconnector.h
index cb6d1b2..df03661 100644
--- a/libhwc2.1/libdrmresource/include/drmconnector.h
+++ b/libhwc2.1/libdrmresource/include/drmconnector.h
@@ -81,6 +81,7 @@ class DrmConnector {
const DrmProperty &lhbm_on() const;
const DrmProperty &mipi_sync() const;
const DrmProperty &panel_idle_support() const;
+ const DrmProperty &vrr_switch_duration() const;
const std::vector<DrmProperty *> &properties() const {
return properties_;
@@ -138,6 +139,7 @@ class DrmConnector {
DrmProperty lhbm_on_;
DrmProperty mipi_sync_;
DrmProperty panel_idle_support_;
+ DrmProperty vrr_switch_duration_;
std::vector<DrmProperty *> properties_;
std::vector<DrmEncoder *> possible_encoders_;
diff --git a/libhwc2.1/libdrmresource/include/drmcrtc.h b/libhwc2.1/libdrmresource/include/drmcrtc.h
index a4130d3..6bb73fd 100644
--- a/libhwc2.1/libdrmresource/include/drmcrtc.h
+++ b/libhwc2.1/libdrmresource/include/drmcrtc.h
@@ -70,6 +70,9 @@ class DrmCrtc {
const DrmProperty &histogram_roi_property() const;
const DrmProperty &histogram_weights_property() const;
const DrmProperty &histogram_threshold_property() const;
+ const DrmProperty &histogram_position_property() const;
+
+ const DrmProperty &rcd_plane_id_property() const;
const std::vector<DrmProperty *> &properties() const {
return properties_;
@@ -110,6 +113,9 @@ class DrmCrtc {
DrmProperty histogram_roi_property_;
DrmProperty histogram_weights_property_;
DrmProperty histogram_threshold_property_;
+ DrmProperty histogram_position_property_;
+
+ DrmProperty rcd_plane_id_property_;
std::vector<DrmProperty *> properties_;
};
diff --git a/libhwc2.1/libdrmresource/include/drmeventlistener.h b/libhwc2.1/libdrmresource/include/drmeventlistener.h
index bd2fec6..e85ca0a 100644
--- a/libhwc2.1/libdrmresource/include/drmeventlistener.h
+++ b/libhwc2.1/libdrmresource/include/drmeventlistener.h
@@ -17,11 +17,13 @@
#ifndef ANDROID_DRM_EVENT_LISTENER_H_
#define ANDROID_DRM_EVENT_LISTENER_H_
+#include <sys/epoll.h>
+
+#include <map>
+
#include "autofd.h"
#include "worker.h"
-#include <sys/epoll.h>
-
namespace android {
class DrmDevice;
@@ -41,7 +43,7 @@ public:
DrmHistogramEventHandler() {}
virtual ~DrmHistogramEventHandler() {}
- virtual void handleHistogramEvent(void *) = 0;
+ virtual void handleHistogramEvent(uint32_t crtc_id, void *) = 0;
};
class DrmTUIEventHandler {
@@ -62,9 +64,19 @@ class DrmPanelIdleEventHandler {
virtual void handleIdleEnterEvent(char const *event) = 0;
};
+class DrmSysfsEventHandler {
+ public:
+ DrmSysfsEventHandler() {}
+ virtual ~DrmSysfsEventHandler() {}
+
+ virtual void handleSysfsEvent() = 0;
+ virtual int getFd() = 0;
+};
+
class DrmEventListener : public Worker {
- static constexpr const char kTUIStatusPath[] = "/sys/devices/platform/exynos-drm/tui_status";
- static const uint32_t maxFds = 3;
+ static constexpr const char kTUIStatusPath[] = "/sys/devices/platform/exynos-drm/tui_status";
+ static const uint32_t maxFds = 4;
+
public:
DrmEventListener(DrmDevice *drm);
virtual ~DrmEventListener();
@@ -79,11 +91,13 @@ class DrmEventListener : public Worker {
void UnRegisterTUIHandler(DrmTUIEventHandler *handler);
void RegisterPanelIdleHandler(DrmPanelIdleEventHandler *handler);
void UnRegisterPanelIdleHandler(DrmPanelIdleEventHandler *handler);
+ int RegisterSysfsHandler(std::shared_ptr<DrmSysfsEventHandler> handler);
+ int UnRegisterSysfsHandler(int sysfs_fd);
bool IsDrmInTUI();
- static void FlipHandler(int fd, unsigned int sequence, unsigned int tv_sec,
- unsigned int tv_usec, void *user_data);
+ static void FlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec,
+ void *user_data);
protected:
virtual void Routine();
@@ -92,6 +106,7 @@ class DrmEventListener : public Worker {
void UEventHandler();
void DRMEventHandler();
void TUIEventHandler();
+ void SysfsEventHandler(int fd);
UniqueFd epoll_fd_;
UniqueFd uevent_fd_;
@@ -102,7 +117,10 @@ class DrmEventListener : public Worker {
std::unique_ptr<DrmHistogramEventHandler> histogram_handler_;
std::unique_ptr<DrmTUIEventHandler> tui_handler_;
std::unique_ptr<DrmPanelIdleEventHandler> panel_idle_handler_;
+ std::mutex mutex_;
+ std::map<int, std::shared_ptr<DrmSysfsEventHandler>> sysfs_handlers_;
};
+
} // namespace android
#endif
diff --git a/libhwc2.1/libdrmresource/include/vsyncworker.h b/libhwc2.1/libdrmresource/include/vsyncworker.h
index bd69712..ce12eea 100644
--- a/libhwc2.1/libdrmresource/include/vsyncworker.h
+++ b/libhwc2.1/libdrmresource/include/vsyncworker.h
@@ -17,14 +17,15 @@
#ifndef ANDROID_EVENT_WORKER_H_
#define ANDROID_EVENT_WORKER_H_
-#include "drmdevice.h"
-#include "worker.h"
-
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
#include <stdint.h>
+#include <utils/String8.h>
+
#include <map>
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
+#include "drmdevice.h"
+#include "worker.h"
namespace android {
@@ -39,7 +40,7 @@ class VSyncWorker : public Worker {
VSyncWorker();
~VSyncWorker() override;
- int Init(DrmDevice *drm, int display);
+ int Init(DrmDevice *drm, int display, const String8 &display_trace_name);
void RegisterCallback(std::shared_ptr<VsyncCallback> callback);
void VSyncControl(bool enabled);
@@ -61,6 +62,9 @@ class VSyncWorker : public Worker {
int display_;
std::atomic_bool enabled_;
int64_t last_timestamp_;
+ String8 hw_vsync_period_tag_;
+ String8 hw_vsync_enabled_tag_;
+ String8 display_trace_name_;
};
} // namespace android
diff --git a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
index 39c2e79..ed99759 100644
--- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
+++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
@@ -30,15 +30,11 @@ extern struct exynos_hwc_control exynosHWCControl;
using namespace SOC_VERSION;
-ExynosExternalDisplay::ExynosExternalDisplay(uint32_t index, ExynosDevice *device)
- : ExynosDisplay(index, device)
-{
+ExynosExternalDisplay::ExynosExternalDisplay(uint32_t index, ExynosDevice* device,
+ const std::string& displayName)
+ : ExynosDisplay(HWC_DISPLAY_EXTERNAL, index, device, displayName) {
DISPLAY_LOGD(eDebugExternalDisplay, "");
- mType = HWC_DISPLAY_EXTERNAL;
- mIndex = index;
- mDisplayId = getDisplayId(mType, mIndex);
-
mDisplayControl.cursorSupport = true;
mEnabled = false;
@@ -102,7 +98,8 @@ void ExynosExternalDisplay::closeExternalDisplay()
setVsyncEnabledInternal(HWC2_VSYNC_DISABLE);
- if (mPowerModeState != (hwc2_power_mode_t)HWC_POWER_MODE_OFF) {
+ if (mPowerModeState.has_value() &&
+ (*mPowerModeState != (hwc2_power_mode_t)HWC_POWER_MODE_OFF)) {
if (mDisplayInterface->setPowerMode(HWC_POWER_MODE_OFF) < 0) {
DISPLAY_LOGE("%s: set powermode ioctl failed errno : %d", __func__, errno);
return;
@@ -276,7 +273,8 @@ int32_t ExynosExternalDisplay::canSkipValidate() {
return SKIP_ERR_DISP_NOT_CONNECTED;
if ((mSkipStartFrame > (SKIP_EXTERNAL_FRAME - 1)) && (mEnabled == false) &&
- (mPowerModeState == (hwc2_power_mode_t)HWC_POWER_MODE_NORMAL))
+ (mPowerModeState.has_value() &&
+ (*mPowerModeState == (hwc2_power_mode_t)HWC_POWER_MODE_NORMAL)))
return SKIP_ERR_DISP_NOT_POWER_ON;
if (checkRotate() || (mIsSkipFrame) ||
@@ -309,7 +307,7 @@ int32_t ExynosExternalDisplay::presentDisplay(
ret = HWC2_ERROR_NOT_VALIDATED;
}
mRenderingState = RENDERING_STATE_PRESENTED;
- mDevice->onRefresh();
+ mDevice->onRefresh(mDisplayId);
return ret;
}
@@ -348,7 +346,7 @@ int32_t ExynosExternalDisplay::presentDisplay(
*/
setGeometryChanged(GEOMETRY_DISPLAY_FORCE_VALIDATE);
- mDevice->onRefresh();
+ mDevice->onRefresh(mDisplayId);
return HWC2_ERROR_NONE;
}
@@ -544,7 +542,7 @@ void ExynosExternalDisplay::handleHotplugEvent()
closeExternalDisplay();
}
hotplug();
- mDevice->onRefresh();
+ mDevice->onRefresh(mDisplayId);
}
}
diff --git a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.h b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.h
index 199ef4d..f0caabc 100644
--- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.h
+++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.h
@@ -28,7 +28,7 @@ class ExynosExternalDisplay : public ExynosDisplay {
hwc2_config_t mActiveConfigIndex;
/* Methods */
- ExynosExternalDisplay(uint32_t index, ExynosDevice *device);
+ ExynosExternalDisplay(uint32_t index, ExynosDevice* device, const std::string& displayName);
~ExynosExternalDisplay();
virtual void init();
diff --git a/libhwc2.1/libhwcService/ExynosHWCService.cpp b/libhwc2.1/libhwcService/ExynosHWCService.cpp
index 7974fee..fd8278b 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.cpp
+++ b/libhwc2.1/libhwcService/ExynosHWCService.cpp
@@ -27,12 +27,8 @@ namespace android {
ANDROID_SINGLETON_STATIC_INSTANCE(ExynosHWCService);
-ExynosHWCService::ExynosHWCService() :
- mHWCService(NULL),
- mHWCCtx(NULL),
- bootFinishedCallback(NULL),
- doPSRExit(NULL)
-{
+ExynosHWCService::ExynosHWCService()
+ : mHWCService(NULL), mHWCCtx(NULL), bootFinishedCallback(NULL) {
ALOGD_IF(HWC_SERVICE_DEBUG, "ExynosHWCService Constructor is called");
}
@@ -252,7 +248,7 @@ void ExynosHWCService::enableMPP(uint32_t physicalType, uint32_t physicalIndex,
__func__, physicalType, physicalIndex, logicalIndex, enable);
ExynosResourceManager::enableMPP(physicalType, physicalIndex, logicalIndex, enable);
mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- mHWCCtx->device->onRefresh();
+ mHWCCtx->device->onRefreshDisplays();
}
void ExynosHWCService::setScaleDownRatio(uint32_t physicalType,
@@ -262,7 +258,7 @@ void ExynosHWCService::setScaleDownRatio(uint32_t physicalType,
__func__, physicalType, physicalIndex, logicalIndex, scaleDownRatio);
ExynosResourceManager::setScaleDownRatio(physicalType, physicalIndex, logicalIndex, scaleDownRatio);
mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- mHWCCtx->device->onRefresh();
+ mHWCCtx->device->onRefreshDisplays();
}
void ExynosHWCService::setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) {
@@ -322,6 +318,7 @@ int ExynosHWCService::setHWCCtl(uint32_t display, uint32_t ctrl, int32_t val)
case HWC_CTL_ENABLE_EARLY_START_MPP:
case HWC_CTL_DISPLAY_MODE:
case HWC_CTL_DDI_RESOLUTION_CHANGE:
+ case HWC_CTL_DYNAMIC_RECOMP:
case HWC_CTL_ENABLE_FENCE_TRACER:
case HWC_CTL_SYS_FENCE_LOGGING:
case HWC_CTL_DO_FENCE_FILE_DUMP:
@@ -336,11 +333,10 @@ int ExynosHWCService::setHWCCtl(uint32_t display, uint32_t ctrl, int32_t val)
return err;
}
-int ExynosHWCService::setDDIScaler(uint32_t width, uint32_t height)
-{
+int ExynosHWCService::setDDIScaler(uint32_t display_id, uint32_t width, uint32_t height) {
ALOGD_IF(HWC_SERVICE_DEBUG, "%s, width=%d, height=%d", __func__, width, height);
if (mHWCCtx) {
- ExynosDisplay *display = (ExynosDisplay*)mHWCCtx->device->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+ ExynosDisplay *display = (ExynosDisplay *)mHWCCtx->device->getDisplay(display_id);
if (display == NULL)
return -EINVAL;
@@ -353,25 +349,6 @@ int ExynosHWCService::setDDIScaler(uint32_t width, uint32_t height)
}
}
-#if 0
-void ExynosHWCService::setPSRExitCallback(void (*callback)(exynos_hwc_composer_device_1_t *))
-{
- ALOGD_IF(HWC_SERVICE_DEBUG, "%s, callback %p", __func__, callback);
- doPSRExit = callback;
-}
-
-void ExynosHWCService::notifyPSRExit()
-{
- ALOGD_IF(HWC_SERVICE_DEBUG, "%s, doPSRExit %p", __func__, doPSRExit);
- if (doPSRExit != NULL) {
- ALOGD_IF(HWC_SERVICE_DEBUG, "%s, line %d", __func__, __LINE__);
- doPSRExit(mHWCCtx);
- }
- ALOGD_IF(HWC_SERVICE_DEBUG, "%s, line %d", __func__, __LINE__);
-}
-
-#endif
-
int ExynosHWCService::createServiceLocked()
{
ALOGD_IF(HWC_SERVICE_DEBUG, "%s::", __func__);
@@ -437,7 +414,7 @@ int32_t ExynosHWCService::setDisplayLhbm(int32_t display_id, uint32_t on) {
auto display = mHWCCtx->device->getDisplay(display_id);
if (display != nullptr) {
- display->requestLhbm(!!on);
+ display->setLhbmState(!!on);
return NO_ERROR;
}
@@ -466,7 +443,7 @@ int32_t ExynosHWCService::setRefreshRateThrottle(uint32_t display_id, int32_t de
->setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::milliseconds(delayMs))
.count(),
- DispIdleTimerRequester::TEST);
+ VrrThrottleRequester::TEST);
}
return -EINVAL;
@@ -482,7 +459,7 @@ int32_t ExynosHWCService::setDisplayRCDLayerEnabled(uint32_t displayIndex, bool
auto ret = primaryDisplay->setDebugRCDLayerEnabled(enable);
mHWCCtx->device->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
- mHWCCtx->device->onRefresh();
+ mHWCCtx->device->onRefresh(getDisplayId(HWC_DISPLAY_PRIMARY, displayIndex));
return ret;
}
@@ -502,4 +479,41 @@ int32_t ExynosHWCService::triggerDisplayIdleEnter(uint32_t displayIndex,
return NO_ERROR;
}
+int32_t ExynosHWCService::setDisplayDbm(int32_t display_id, uint32_t on) {
+ if (on > 1) return -EINVAL;
+
+ auto display = mHWCCtx->device->getDisplay(display_id);
+
+ if (display == nullptr) return -EINVAL;
+
+ ALOGD("ExynosHWCService::%s() display(%u) on=%d", __func__, display_id, on);
+ display->setDbmState(!!on);
+ mHWCCtx->device->onRefresh(display_id);
+ return NO_ERROR;
+}
+
+int32_t ExynosHWCService::setDisplayMultiThreadedPresent(const int32_t& displayId,
+ const bool& enable) {
+ auto display = mHWCCtx->device->getDisplay(displayId);
+
+ if (display == nullptr) return -EINVAL;
+
+ display->mDisplayControl.multiThreadedPresent = enable;
+ ALOGD("ExynosHWCService::%s() display(%u) enable=%d", __func__, displayId, enable);
+ return NO_ERROR;
+}
+
+int32_t ExynosHWCService::triggerRefreshRateIndicatorUpdate(uint32_t displayId,
+ uint32_t refreshRate) {
+ auto display = mHWCCtx->device->getDisplay(displayId);
+
+ if (display == nullptr) return -EINVAL;
+
+ ALOGD("ExynosHWCService::%s() displayID(%u) refreshRate(%u)", __func__, displayId, refreshRate);
+ if (display->mRefreshRateIndicatorHandler) {
+ display->mRefreshRateIndicatorHandler->updateRefreshRate(refreshRate);
+ }
+ return NO_ERROR;
+}
+
} //namespace android
diff --git a/libhwc2.1/libhwcService/ExynosHWCService.h b/libhwc2.1/libhwcService/ExynosHWCService.h
index f4224fb..abb525f 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.h
+++ b/libhwc2.1/libhwcService/ExynosHWCService.h
@@ -65,12 +65,8 @@ public:
virtual void getHWCFenceDebug();
virtual int setHWCCtl(uint32_t display, uint32_t ctrl, int32_t val);
- virtual int setDDIScaler(uint32_t width, uint32_t height);
+ virtual int setDDIScaler(uint32_t display_id, uint32_t width, uint32_t height);
virtual void setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) override;
-#if 0
- void setPSRExitCallback(void (*callback)(exynos_hwc_composer_device_1_t *));
- virtual void notifyPSRExit();
-#endif
virtual int32_t setDisplayDeviceMode(int32_t display_id, int32_t mode);
virtual int32_t setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source);
virtual int32_t setDisplayBrightness(int32_t display_id, float brightness);
@@ -78,9 +74,16 @@ public:
virtual int32_t setMinIdleRefreshRate(uint32_t display_id, int32_t fps);
virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t delayMs);
+ virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on);
+
int32_t setDisplayRCDLayerEnabled(uint32_t displayIndex, bool enable) override;
int32_t triggerDisplayIdleEnter(uint32_t displayIndex, uint32_t idleTeRefreshRate) override;
+ virtual int32_t setDisplayMultiThreadedPresent(const int32_t& display_id,
+ const bool& enable) override;
+ virtual int32_t triggerRefreshRateIndicatorUpdate(uint32_t displayId,
+ uint32_t refreshRate) override;
+
private:
friend class Singleton<ExynosHWCService>;
ExynosHWCService();
@@ -89,7 +92,6 @@ private:
Mutex mLock;
ExynosHWCCtx *mHWCCtx;
void (*bootFinishedCallback)(ExynosHWCCtx *);
- void (*doPSRExit)(ExynosHWCCtx *ctx);
};
}
diff --git a/libhwc2.1/libhwcService/IExynosHWC.cpp b/libhwc2.1/libhwcService/IExynosHWC.cpp
index 181fdf2..f092696 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.cpp
+++ b/libhwc2.1/libhwcService/IExynosHWC.cpp
@@ -50,9 +50,6 @@ enum {
SET_DDISCALER,
GET_EXTERNAL_HDR_CAPA,
SET_SCALE_DOWN_RATIO,
-#if 0
- NOTIFY_PSR_EXIT,
-#endif
SET_HWC_DEBUG = 105,
GET_HWC_DEBUG = 106,
SET_HWC_FENCE_DEBUG = 107,
@@ -66,6 +63,9 @@ enum {
SET_REFRESH_RATE_THROTTLE = 1006,
SET_DISPLAY_RCDLAYER_ENABLED = 1007,
TRIGGER_DISPLAY_IDLE_ENTER = 1008,
+ SET_DISPLAY_DBM = 1009,
+ SET_DISPLAY_MULTI_THREADED_PRESENT = 1010,
+ TRIGGER_REFRESH_RATE_INDICATOR_UPDATE = 1011,
};
class BpExynosHWCService : public BpInterface<IExynosHWCService> {
@@ -364,11 +364,12 @@ public:
return result;
};
- virtual int setDDIScaler(uint32_t width, uint32_t height) {
+ virtual int setDDIScaler(uint32_t displayId, uint32_t width, uint32_t height) {
Parcel data, reply;
data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
- data.writeInt32(width);
- data.writeInt32(height);
+ data.writeUint32(displayId);
+ data.writeUint32(width);
+ data.writeUint32(height);
int result = remote()->transact(SET_DDISCALER, data, &reply);
if (result == NO_ERROR)
result = reply.readInt32();
@@ -377,15 +378,6 @@ public:
return result;
}
- /*
- virtual void notifyPSRExit()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
- remote()->transact(NOTIFY_PSR_EXIT, data, &reply);
- }
- */
-
int32_t setDisplayDeviceMode(int32_t display_id, int32_t mode)
{
ALOGD("null func: %s(%d %d)", __func__, display_id, mode);
@@ -455,10 +447,44 @@ public:
data.writeUint32(displayIndex);
data.writeUint32(idleTeRefreshRate);
- auto result = remote()->transact(SET_DISPLAY_RCDLAYER_ENABLED, data, &reply);
+ auto result = remote()->transact(TRIGGER_DISPLAY_IDLE_ENTER, data, &reply);
ALOGE_IF(result != NO_ERROR, "TRIGGER_DISPLAY_IDLE_ENTER transact error(%d)", result);
return result;
}
+
+ virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeInt32(display_id);
+ data.writeInt32(on);
+ int result = remote()->transact(SET_DISPLAY_DBM, data, &reply);
+ if (result) ALOGE("SET_DISPLAY_DBM transact error(%d)", result);
+ return result;
+ }
+
+ virtual int32_t setDisplayMultiThreadedPresent(const int32_t& displayId,
+ const bool& enable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeInt32(displayId);
+ data.writeBool(enable);
+ int result = remote()->transact(SET_DISPLAY_MULTI_THREADED_PRESENT, data, &reply);
+ if (result) ALOGE("SET_DISPLAY_MULTI_THREADED_PRESENT transact error(%d)", result);
+ return result;
+ }
+
+ virtual int32_t triggerRefreshRateIndicatorUpdate(uint32_t displayId,
+ uint32_t refreshRate) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IExynosHWCService::getInterfaceDescriptor());
+ data.writeUint32(displayId);
+ data.writeUint32(refreshRate);
+
+ auto result = remote()->transact(TRIGGER_REFRESH_RATE_INDICATOR_UPDATE, data, &reply);
+ ALOGE_IF(result != NO_ERROR, "TRIGGER_REFRESH_RATE_INDICATOR_UPDATE transact error(%d)",
+ result);
+ return result;
+ }
};
IMPLEMENT_META_INTERFACE(ExynosHWCService, "android.hal.ExynosHWCService");
@@ -624,50 +650,13 @@ status_t BnExynosHWCService::onTransact(
} break;
case SET_DDISCALER: {
CHECK_INTERFACE(IExynosHWCService, data, reply);
- uint32_t width = data.readInt32();
- uint32_t height = data.readInt32();
- int error = setDDIScaler(width, height);
+ uint32_t display_id = data.readUint32();
+ uint32_t width = data.readUint32();
+ uint32_t height = data.readUint32();
+ int error = setDDIScaler(display_id, width, height);
reply->writeInt32(error);
return NO_ERROR;
} break;
-
-#if 0
- case SET_HWC_CTL_MAX_OVLY_CNT: {
- CHECK_INTERFACE(IExynosHWCService, data, reply);
- int val = data.readInt32();
- setHWCCtl(SET_HWC_CTL_MAX_OVLY_CNT, val);
- return NO_ERROR;
- } break;
- case SET_HWC_CTL_VIDEO_OVLY_CNT: {
- CHECK_INTERFACE(IExynosHWCService, data, reply);
- int val = data.readInt32();
- setHWCCtl(SET_HWC_CTL_VIDEO_OVLY_CNT, val);
- return NO_ERROR;
- } break;
- case SET_HWC_CTL_DYNAMIC_RECOMP: {
- CHECK_INTERFACE(IExynosHWCService, data, reply);
- int val = data.readInt32();
- setHWCCtl(SET_HWC_CTL_DYNAMIC_RECOMP, val);
- return NO_ERROR;
- } break;
- case SET_HWC_CTL_SKIP_STATIC: {
- CHECK_INTERFACE(IExynosHWCService, data, reply);
- int val = data.readInt32();
- setHWCCtl(SET_HWC_CTL_SKIP_STATIC, val);
- return NO_ERROR;
- } break;
- case SET_HWC_CTL_SECURE_DMA: {
- CHECK_INTERFACE(IExynosHWCService, data, reply);
- int val = data.readInt32();
- setHWCCtl(SET_HWC_CTL_SECURE_DMA, val);
- return NO_ERROR;
- } break;
- case NOTIFY_PSR_EXIT: {
- CHECK_INTERFACE(IExynosHWCService, data, reply);
- notifyPSRExit();
- return NO_ERROR;
- }
-#endif
case SET_DISPLAY_DEVICE_MODE: {
CHECK_INTERFACE(IExynosHWCService, data, reply);
int32_t display_id = data.readInt32();
@@ -741,6 +730,31 @@ status_t BnExynosHWCService::onTransact(
return triggerDisplayIdleEnter(displayIndex, idleTeRefreshRate);
} break;
+ case SET_DISPLAY_DBM: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ int32_t display_id = data.readInt32();
+ uint32_t on = data.readInt32();
+ int32_t error = setDisplayDbm(display_id, on);
+ reply->writeInt32(error);
+ return NO_ERROR;
+ } break;
+
+ case SET_DISPLAY_MULTI_THREADED_PRESENT: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ int32_t displayId = data.readInt32();
+ bool enable = data.readBool();
+ int32_t error = setDisplayMultiThreadedPresent(displayId, enable);
+ reply->writeInt32(error);
+ return NO_ERROR;
+ } break;
+
+ case TRIGGER_REFRESH_RATE_INDICATOR_UPDATE: {
+ CHECK_INTERFACE(IExynosHWCService, data, reply);
+ uint32_t displayId = data.readUint32();
+ uint32_t refreshRate = data.readUint32();
+ return triggerRefreshRateIndicatorUpdate(displayId, refreshRate);
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libhwc2.1/libhwcService/IExynosHWC.h b/libhwc2.1/libhwcService/IExynosHWC.h
index debf6fb..bf51c85 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.h
+++ b/libhwc2.1/libhwcService/IExynosHWC.h
@@ -62,20 +62,21 @@ public:
virtual void getHWCFenceDebug() = 0;
virtual int setHWCCtl(uint32_t display, uint32_t ctrl, int32_t val) = 0;
- virtual int setDDIScaler(uint32_t width, uint32_t height) = 0;
+ virtual int setDDIScaler(uint32_t display_id, uint32_t width, uint32_t height) = 0;
virtual int32_t setDisplayDeviceMode(int32_t display_id, int32_t mode) = 0;
virtual int32_t setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source) = 0;
virtual void setLbeCtrl(uint32_t display_id, uint32_t state, uint32_t lux) = 0;
- /*
- virtual void notifyPSRExit() = 0;
- */
virtual int32_t setDisplayBrightness(int32_t display_id, float brightness) = 0;
virtual int32_t setDisplayLhbm(int32_t display_id, uint32_t on) = 0;
virtual int32_t setMinIdleRefreshRate(uint32_t display_id, int32_t refresh_rate) = 0;
virtual int32_t setRefreshRateThrottle(uint32_t display_id, int32_t throttle) = 0;
virtual int32_t setDisplayRCDLayerEnabled(uint32_t displayIndex, bool enable) = 0;
virtual int32_t triggerDisplayIdleEnter(uint32_t displayIndex, uint32_t idleTeRefreshRate) = 0;
+ virtual int32_t setDisplayDbm(int32_t display_id, uint32_t on) = 0;
+ virtual int32_t setDisplayMultiThreadedPresent(const int32_t& displayId,
+ const bool& enable) = 0;
+ virtual int32_t triggerRefreshRateIndicatorUpdate(uint32_t displayId, uint32_t refreshRate) = 0;
};
/* Native Interface */
diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp
index 60593c8..56b3b83 100644
--- a/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp
+++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.cpp
@@ -36,6 +36,7 @@
using vendor::graphics::BufferUsage;
using vendor::graphics::VendorGraphicBufferUsage;
using vendor::graphics::VendorGraphicBufferMeta;
+using namespace SOC_VERSION;
#define AFBC_MAGIC 0xafbc
@@ -271,6 +272,30 @@ bool isFormatP010(int format)
return false;
}
+bool isFormat10Bit(int format) {
+ for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++) {
+ if (exynos_format_desc[i].halFormat == format) {
+ if ((exynos_format_desc[i].type & BIT_MASK) == BIT10)
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+}
+
+bool isFormat8Bit(int format) {
+ for (unsigned int i = 0; i < FORMAT_MAX_CNT; i++) {
+ if (exynos_format_desc[i].halFormat == format) {
+ if ((exynos_format_desc[i].type & BIT_MASK) == BIT8)
+ return true;
+ else
+ return false;
+ }
+ }
+ return false;
+}
+
bool isFormatYCrCb(int format)
{
return format == HAL_PIXEL_FORMAT_EXYNOS_YV12_M;
@@ -647,11 +672,13 @@ uint32_t getExynosBufferYLength(uint32_t width, uint32_t height, int format)
HDEBUGLOGD(eDebugMPP, "size(Y) : %d", P010_Y_SIZE(width, height));
return P010_Y_SIZE(width, height);
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
- return YUV420N_Y_SIZE(width, height);
+ return NV12N_Y_SIZE(width, height);
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN:
+ return 2 * __ALIGN_UP(width, 64) * __ALIGN_UP(height, 16);
case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B:
- return 2 * __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8);
+ return 2 * __ALIGN_UP(width, 64) * __ALIGN_UP(height, 16);
case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP:
- return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8);
+ return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 16);
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
@@ -672,6 +699,8 @@ uint32_t getExynosBufferYLength(uint32_t width, uint32_t height, int format)
case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
return SBWC_10B_Y_SIZE(width, height) +
SBWC_10B_Y_HEADER_SIZE(width, height);
+ case MALI_GRALLOC_FORMAT_INTERNAL_NV21:
+ return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 2);
}
return NV12M_Y_SIZE(width, height) + ((width % 128) == 0 ? 0 : 256);
@@ -696,10 +725,12 @@ uint32_t getExynosBufferCbCrLength(uint32_t width, uint32_t height, int format)
case HAL_PIXEL_FORMAT_YCBCR_P010:
HDEBUGLOGD(eDebugMPP, "size(CbCr) : %d", P010_CBCR_SIZE(width, height));
return P010_CBCR_SIZE(width, height);
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN:
+ return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 16);
case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP_10B:
- return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8);
+ return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 16);
case HAL_PIXEL_FORMAT_GOOGLE_NV12_SP:
- return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 8) / 2;
+ return __ALIGN_UP(width, 64) * __ALIGN_UP(height, 16) / 2;
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
@@ -825,6 +856,8 @@ void setFenceInfo(uint32_t fd, ExynosDisplay* display, HwcFdebugFenceType type,
if (!fence_valid(fd) || display == NULL) return;
ExynosDevice* device = display->mDevice;
+
+ std::scoped_lock lock(device->mFenceMutex);
HwcFenceInfo& info = device->mFenceInfos[fd];
info.displayId = display->mDisplayId;
@@ -991,10 +1024,10 @@ bool validateFencePerFrame(ExynosDisplay* display) {
String8 getMPPStr(int typeId) {
if (typeId < MPP_DPP_NUM){
- int cnt = sizeof(AVAILABLE_OTF_MPP_UNITS)/sizeof(exynos_mpp_t);
+ int cnt = sizeof(available_otf_mpp_units)/sizeof(exynos_mpp_t);
for (int i = 0; i < cnt; i++){
- if (AVAILABLE_OTF_MPP_UNITS[i].physicalType == typeId)
- return String8(AVAILABLE_OTF_MPP_UNITS[i].name);
+ if (available_otf_mpp_units[i].physicalType == typeId)
+ return String8(available_otf_mpp_units[i].name);
}
} else {
int cnt = sizeof(AVAILABLE_M2M_MPP_UNITS)/sizeof(exynos_mpp_t);
@@ -1102,10 +1135,6 @@ int32_t writeIntToFile(const char* file, uint32_t value) {
return 0;
}
-uint32_t getDisplayId(int32_t displayType, int32_t displayIndex) {
- return (displayType << DISPLAYID_MASK_LEN) | displayIndex;
-}
-
int32_t load_png_image(const char* filepath, buffer_handle_t buffer) {
png_structp png_ptr;
png_infop info_ptr;
@@ -1159,8 +1188,9 @@ int32_t load_png_image(const char* filepath, buffer_handle_t buffer) {
return -EINVAL;
}
- uint32_t bufferHandleSize = gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format) / 8;
- if (bufferHandleSize > gmeta.size) {
+ size_t bufferHandleSize = gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format) / 8;
+ size_t png_size = png_get_rowbytes(png_ptr, info_ptr) * height;
+ if (bufferHandleSize > gmeta.size || (bufferHandleSize < png_size)) {
fclose(fp);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return -EINVAL;
diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.h b/libhwc2.1/libhwchelper/ExynosHWCHelper.h
index 6fb9ea5..87b6163 100644
--- a/libhwc2.1/libhwchelper/ExynosHWCHelper.h
+++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.h
@@ -82,22 +82,35 @@ enum {
};
typedef enum format_type {
- TYPE_UNDEF = 0,
+ TYPE_UNDEF = 0,
/* format */
- FORMAT_SHIFT = 0,
- FORMAT_MASK = 0x00000fff,
- RGB = 0x00000001,
- YUV420 = 0x00000002,
- YUV422 = 0x00000004,
- P010 = 0x00000008,
+ FORMAT_SHIFT = 0,
+ FORMAT_MASK = 0x00000fff,
+
+ FORMAT_RGB_MASK = 0x0000000f,
+ RGB = 0x00000001,
+
+ FORMAT_YUV_MASK = 0x000000f0,
+ YUV420 = 0x00000010,
+ YUV422 = 0x00000020,
+ P010 = 0x00000030,
+
+ FORMAT_SBWC_MASK = 0x00000f00,
+ SBWC_LOSSLESS = 0x00000100,
+ SBWC_LOSSY_40 = 0x00000200,
+ SBWC_LOSSY_50 = 0x00000300,
+ SBWC_LOSSY_60 = 0x00000400,
+ SBWC_LOSSY_75 = 0x00000500,
+ SBWC_LOSSY_80 = 0x00000600,
/* bit */
- BIT_SHIFT = 12,
- BIT_MASK = 0x000ff000,
- BIT8 = 0x00001000,
- BIT10 = 0x00002000,
- BIT8_2 = 0x00004000,
+ BIT_SHIFT = 16,
+ BIT_MASK = 0x000f0000,
+ BIT8 = 0x00010000,
+ BIT10 = 0x00020000,
+ BIT8_2 = 0x00030000,
+ BIT16 = 0x00040000,
/* compression */
/*
@@ -105,12 +118,12 @@ typedef enum format_type {
* descriptions of format (ex: drmFormat, bufferNum, bpp...)
* in format_description
*/
- COMP_SHIFT = 20,
- COMP_MASK = 0x0ff00000,
- COMP_ANY = 0x08000000, /* the highest bit */
- AFBC = 0x00100000,
- SBWC = 0x00200000,
- SBWC_LOSSY = 0x00400000,
+ COMP_SHIFT = 20,
+ COMP_MASK = 0x0ff00000,
+ COMP_ANY = 0x08000000, /* the highest bit */
+ AFBC = 0x00100000,
+ SBWC = 0x00200000,
+ SBWC_LOSSY = 0x00400000,
} format_type_t;
@@ -190,6 +203,8 @@ const format_description_t exynos_format_desc[] = {
2, 2, 24, YUV420|BIT10|P010, false, String8("EXYNOS_YCbCr_P010_M"), 0},
{HAL_PIXEL_FORMAT_YCBCR_P010, DECON_PIXEL_FORMAT_NV12_P010, DRM_FORMAT_P010,
2, 1, 24, YUV420|BIT10|P010, false, String8("EXYNOS_YCbCr_P010"), 0},
+ {HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_SPN, DECON_PIXEL_FORMAT_NV12_P010, DRM_FORMAT_P010,
+ 2, 1, 24, YUV420|BIT10|P010, false, String8("EXYNOS_YCbCr_P010_SPN"), 0},
{HAL_PIXEL_FORMAT_GOOGLE_NV12_SP, DECON_PIXEL_FORMAT_MAX, DRM_FORMAT_NV12,
2, 1, 12, YUV420|BIT8, false, String8("GOOGLE_YCbCr_420_SP"), 0},
@@ -199,6 +214,8 @@ const format_description_t exynos_format_desc[] = {
1, 1, 12, YUV420|BIT8|AFBC, false, String8("MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I"), 0},
{MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I, DECON_PIXEL_FORMAT_MAX, DRM_FORMAT_YUV420_10BIT,
1, 1, 15, YUV420|BIT10|AFBC, false, String8("MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I"), 0},
+ {MALI_GRALLOC_FORMAT_INTERNAL_NV21, DECON_PIXEL_FORMAT_NV21, DRM_FORMAT_NV21,
+ 2, 1, 12, YUV420|BIT8, false, String8("MALI_GRALLOC_FORMAT_INTERNAL_NV21"), 0},
/* YUV 422 */
{HAL_PIXEL_FORMAT_EXYNOS_CbYCrY_422_I, DECON_PIXEL_FORMAT_MAX, DRM_FORMAT_UNDEFINED,
@@ -426,6 +443,8 @@ bool isFormat10BitYUV420(int format);
bool isFormatLossy(int format);
bool isFormatSBWC(int format);
bool isFormatP010(int format);
+bool isFormat10Bit(int format);
+bool isFormat8Bit(int format);
bool formatHasAlphaChannel(int format);
unsigned int isNarrowRgb(int format, android_dataspace data_space);
bool isAFBCCompressed(const buffer_handle_t handle);
@@ -564,7 +583,10 @@ private:
void writeFileNode(FILE *fd, int value);
int32_t writeIntToFile(const char *file, uint32_t value);
-uint32_t getDisplayId(int32_t displayType, int32_t displayIndex = 0);
+constexpr uint32_t getDisplayId(int32_t displayType, int32_t displayIndex) {
+ return (displayType << DISPLAYID_MASK_LEN) | displayIndex;
+}
+
int32_t load_png_image(const char *filepath, buffer_handle_t buffer);
int readLineFromFile(const std::string &filename, std::string &out, char delim);
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
index 099ad73..d24d1f9 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
@@ -38,15 +38,20 @@ extern struct exynos_hwc_control exynosHWCControl;
using namespace SOC_VERSION;
constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
-constexpr auto nsecsPerMs = std::chrono::nanoseconds(1ms).count();
static const std::map<const DisplayType, const std::string> panelSysfsPath =
{{DisplayType::DISPLAY_PRIMARY, "/sys/devices/platform/exynos-drm/primary-panel/"},
{DisplayType::DISPLAY_SECONDARY, "/sys/devices/platform/exynos-drm/secondary-panel/"}};
-static constexpr const char* PROPERTY_BOOT_MODE = "persist.vendor.display.primary.boot_config";
-static constexpr const char *PROPERTY_DEFAULT_BOOT_MODE =
- "vendor.display.primary.default_boot_config";
+static String8 getPropertyBootModeStr(const int32_t dispId) {
+ String8 str;
+ if (dispId == 0) {
+ str.appendFormat("persist.vendor.display.primary.boot_config");
+ } else {
+ str.appendFormat("persist.vendor.display.%d.primary.boot_config", dispId);
+ }
+ return str;
+}
static std::string loadPanelGammaCalibration(const std::string &file) {
std::ifstream ifs(file);
@@ -76,8 +81,9 @@ static std::string loadPanelGammaCalibration(const std::string &file) {
return gamma;
}
-ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
- : ExynosDisplay(index, device),
+ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device,
+ const std::string &displayName)
+ : ExynosDisplay(HWC_DISPLAY_PRIMARY, index, device, displayName),
mMinIdleRefreshRate(0),
mRefreshRateDelayNanos(0),
mLastRefreshRateAppliedNanos(0),
@@ -88,12 +94,17 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
mNumMaxPriorityAllowed = 5;
/* Initialization */
- mType = HWC_DISPLAY_PRIMARY;
- mIndex = index;
- mDisplayId = getDisplayId(mType, mIndex);
mFramesToReachLhbmPeakBrightness =
property_get_int32("vendor.primarydisplay.lhbm.frames_to_reach_peak_brightness", 3);
+ // Allow to enable dynamic recomposition after every power on
+ // since it will always be disabled for every power off
+ // TODO(b/268474771): to enable DR by default if video mode panel is detected
+ if (property_get_int32("vendor.display.dynamic_recomposition", 0) & (1 << index)) {
+ mDRDefault = true;
+ mDREnable = true;
+ }
+
// Prepare multi resolution
// Will be exynosHWCControl.multiResoultion
mResolutionInfo.nNum = 1;
@@ -113,12 +124,20 @@ ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device)
mResolutionInfo.nDSCXSliceSize[2] = 720;
mResolutionInfo.nPanelType[2] = PANEL_LEGACY;
- mEarlyWakeupDispFd = fopen(EARLY_WAKUP_NODE_0_BASE, "w");
+ char value[PROPERTY_VALUE_MAX];
+ const char *earlyWakeupNodeBase = early_wakeup_node_0_base;
+ if (getDisplayTypeFromIndex(mIndex) == DisplayType::DISPLAY_SECONDARY &&
+ property_get("vendor.display.secondary_early_wakeup_node", value, "") > 0) {
+ earlyWakeupNodeBase = value;
+ }
+ mEarlyWakeupDispFd = fopen(earlyWakeupNodeBase, "w");
if (mEarlyWakeupDispFd == nullptr)
- ALOGE("open %s failed! %s", EARLY_WAKUP_NODE_0_BASE, strerror(errno));
+ ALOGE("open %s failed! %s", earlyWakeupNodeBase, strerror(errno));
mBrightnessController = std::make_unique<BrightnessController>(
- mIndex, [this]() { mDevice->onRefresh(); },
+ mIndex, [this]() { mDevice->onRefresh(mDisplayId); },
[this]() { updatePresentColorConversionInfo(); });
+
+ mDisplayControl.multiThreadedPresent = true;
}
ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
@@ -159,9 +178,10 @@ int ExynosPrimaryDisplay::getDDIScalerMode(int width, int height) {
}
int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) {
- if (mPowerModeState != HWC2_POWER_MODE_ON) {
- mPendActiveConfig = config;
- mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_NONE;
+ if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
+ !isConfigSettingEnabled()) {
+ mPendingConfig = config;
+ mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
DISPLAY_LOGI("%s:: Pending desired Config: %d", __func__, config);
return NO_ERROR;
}
@@ -169,8 +189,8 @@ int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) {
}
int32_t ExynosPrimaryDisplay::getActiveConfigInternal(hwc2_config_t *outConfig) {
- if (outConfig && mPendActiveConfig != UINT_MAX) {
- *outConfig = mPendActiveConfig;
+ if (outConfig && mPendingConfig != UINT_MAX) {
+ *outConfig = mPendingConfig;
return HWC2_ERROR_NONE;
}
return ExynosDisplay::getActiveConfigInternal(outConfig);
@@ -184,19 +204,21 @@ int32_t ExynosPrimaryDisplay::setActiveConfigInternal(hwc2_config_t config, bool
ALOGI("%s:: Same display config is set", __func__);
return HWC2_ERROR_NONE;
}
- if (mPowerModeState != HWC2_POWER_MODE_ON) {
- mPendActiveConfig = config;
+ if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
+ !isConfigSettingEnabled()) {
+ mPendingConfig = config;
return HWC2_ERROR_NONE;
}
return ExynosDisplay::setActiveConfigInternal(config, force);
}
int32_t ExynosPrimaryDisplay::applyPendingConfig() {
- hwc2_config_t config;
+ if (!isConfigSettingEnabled()) return HWC2_ERROR_NONE;
- if (mPendActiveConfig != UINT_MAX) {
- config = mPendActiveConfig;
- mPendActiveConfig = UINT_MAX;
+ hwc2_config_t config;
+ if (mPendingConfig != UINT_MAX) {
+ config = mPendingConfig;
+ mPendingConfig = UINT_MAX;
} else {
getActiveConfigInternal(&config);
}
@@ -226,22 +248,21 @@ int32_t ExynosPrimaryDisplay::setBootDisplayConfig(int32_t config) {
ALOGD("%s: mode=%s (%d) vsyncPeriod=%d", __func__, modeStr, config,
mode.vsyncPeriod);
- ret = property_set(PROPERTY_BOOT_MODE, modeStr);
+ ret = property_set(getPropertyBootModeStr(mDisplayId).string(), modeStr);
return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
}
int32_t ExynosPrimaryDisplay::clearBootDisplayConfig() {
- auto ret = property_set(PROPERTY_BOOT_MODE, nullptr);
+ auto ret = property_set(getPropertyBootModeStr(mDisplayId).string(), nullptr);
ALOGD("%s: clearing boot mode", __func__);
return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
}
int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
- char modeStr[PROPERTY_VALUE_MAX], defaultModeStr[PROPERTY_VALUE_MAX];
- property_get(PROPERTY_DEFAULT_BOOT_MODE, defaultModeStr, "");
- auto ret = property_get(PROPERTY_BOOT_MODE, modeStr, defaultModeStr);
+ char modeStr[PROPERTY_VALUE_MAX];
+ auto ret = property_get(getPropertyBootModeStr(mDisplayId).string(), modeStr, "");
if (ret <= 0) {
return mDisplayInterface->getDefaultModeId(outConfig);
@@ -256,27 +277,22 @@ int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConf
return HWC2_ERROR_BAD_CONFIG;
}
- const auto vsyncPeriod = nsecsPerSec / fps;
-
- for (auto const& [config, mode] : mDisplayConfigs) {
- long delta = abs(vsyncPeriod - mode.vsyncPeriod);
- if ((width == mode.width) && (height == mode.height) &&
- (delta < nsecsPerMs)) {
- ALOGD("%s: found preferred display config for mode: %s=%d",
- __func__, modeStr, config);
- *outConfig = config;
- return HWC2_ERROR_NONE;
- }
- }
- return HWC2_ERROR_BAD_CONFIG;
+ return lookupDisplayConfigs(width, height, fps, outConfig);
}
int32_t ExynosPrimaryDisplay::setPowerOn() {
ATRACE_CALL();
updateAppliedActiveConfig(0, 0);
- int ret = applyPendingConfig();
+ int ret = NO_ERROR;
+ if (mDisplayId != 0 || !mFirstPowerOn) {
+ if (mDevice->hasOtherDisplayOn(this)) {
+ // TODO: This is useful for cmd mode, and b/282094671 tries to handles video mode
+ mDisplayInterface->triggerClearDisplayPlanes();
+ }
+ ret = applyPendingConfig();
+ }
- if (mPowerModeState == HWC2_POWER_MODE_OFF) {
+ if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
// check the dynamic recomposition thread by following display
mDevice->checkDynamicRecompositionThread();
if (ret) {
@@ -285,7 +301,14 @@ int32_t ExynosPrimaryDisplay::setPowerOn() {
setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
}
- mPowerModeState = HWC2_POWER_MODE_ON;
+ {
+ std::lock_guard<std::mutex> lock(mPowerModeMutex);
+ mPowerModeState = HWC2_POWER_MODE_ON;
+ if (mNotifyPowerOn) {
+ mPowerOnCondition.notify_one();
+ mNotifyPowerOn = false;
+ }
+ }
if (mFirstPowerOn) {
firstPowerOn();
@@ -303,7 +326,11 @@ int32_t ExynosPrimaryDisplay::setPowerOff() {
mDevice->checkDynamicRecompositionThread();
mDisplayInterface->setPowerMode(HWC2_POWER_MODE_OFF);
- mPowerModeState = HWC2_POWER_MODE_OFF;
+
+ {
+ std::lock_guard<std::mutex> lock(mPowerModeMutex);
+ mPowerModeState = HWC2_POWER_MODE_OFF;
+ }
/* It should be called from validate() when the screen is on */
mSkipFrame = true;
@@ -326,14 +353,23 @@ int32_t ExynosPrimaryDisplay::setPowerDoze(hwc2_power_mode_t mode) {
return HWC2_ERROR_UNSUPPORTED;
}
- if ((mPowerModeState == HWC2_POWER_MODE_OFF) || (mPowerModeState == HWC2_POWER_MODE_ON)) {
+ if (mPowerModeState.has_value() &&
+ ((*mPowerModeState == HWC2_POWER_MODE_OFF) || (*mPowerModeState == HWC2_POWER_MODE_ON))) {
if (mDisplayInterface->setLowPowerMode()) {
ALOGI("Not support LP mode.");
return HWC2_ERROR_UNSUPPORTED;
}
}
- mPowerModeState = mode;
+ {
+ std::lock_guard<std::mutex> lock(mPowerModeMutex);
+ mPowerModeState = mode;
+ }
+
+ // LHBM will be disabled in the kernel while entering AOD mode if it's
+ // already enabled. Reset the state to avoid the sync problem.
+ mBrightnessController->resetLhbmState();
+ mLhbmOn = false;
ExynosDisplay::updateRefreshRateHint();
@@ -349,9 +385,12 @@ int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) {
} else if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
mode = HWC2_POWER_MODE_ON;
mPauseDisplay = false;
+ } else if (mPauseDisplay) {
+ ALOGI("Skip power mode transition due to pause display.");
+ return HWC2_ERROR_NONE;
}
- if (mode == static_cast<int32_t>(mPowerModeState)) {
+ if (mPowerModeState.has_value() && (mode == static_cast<int32_t>(mPowerModeState.value()))) {
ALOGI("Skip power mode transition due to the same power state.");
return HWC2_ERROR_NONE;
}
@@ -364,6 +403,7 @@ int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) {
else
mDREnable = mDRDefault;
+ if (mOperationRateManager) mOperationRateManager->onPowerMode(mode);
switch (mode) {
case HWC2_POWER_MODE_DOZE_SUSPEND:
case HWC2_POWER_MODE_DOZE:
@@ -496,72 +536,250 @@ int32_t ExynosPrimaryDisplay::SetCurrentPanelGammaSource(const DisplayType type,
return HWC2_ERROR_NONE;
}
+bool ExynosPrimaryDisplay::isLhbmSupported() {
+ return mBrightnessController->isLhbmSupported();
+}
+
+bool ExynosPrimaryDisplay::isConfigSettingEnabled() {
+ int64_t msSinceDisabled =
+ (systemTime(SYSTEM_TIME_MONOTONIC) - mConfigSettingDisabledTimestamp) / 1000000;
+ return !mConfigSettingDisabled || msSinceDisabled > kConfigDisablingMaxDurationMs;
+}
+
+void ExynosPrimaryDisplay::enableConfigSetting(bool en) {
+ DISPLAY_ATRACE_INT("ConfigSettingDisabled", !en);
+
+ if (!en) {
+ mConfigSettingDisabled = true;
+ mConfigSettingDisabledTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+ return;
+ }
+
+ mConfigSettingDisabled = false;
+}
+
+int32_t ExynosPrimaryDisplay::setLhbmDisplayConfigLocked(uint32_t peakRate) {
+ auto hwConfig = mDisplayInterface->getActiveModeId();
+ auto config = getConfigId(peakRate, mDisplayConfigs[hwConfig].width,
+ mDisplayConfigs[hwConfig].height);
+ if (config == UINT_MAX) {
+ DISPLAY_LOGE("%s: failed to get config for rate=%d", __func__, peakRate);
+ return -EINVAL;
+ }
+
+ if (mPendingConfig == UINT_MAX && mActiveConfig != config) mPendingConfig = mActiveConfig;
+ if (config != hwConfig) {
+ if (ExynosDisplay::setActiveConfigInternal(config, true) == HWC2_ERROR_NONE) {
+ DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, config, peakRate);
+ } else {
+ DISPLAY_LOGW("%s: failed to set config=%d rate=%d", __func__, config, peakRate);
+ }
+ } else {
+ DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, config, peakRate);
+ }
+ enableConfigSetting(false);
+ return OK;
+}
+
+void ExynosPrimaryDisplay::restoreLhbmDisplayConfigLocked() {
+ enableConfigSetting(true);
+ hwc2_config_t pendingConfig = mPendingConfig;
+ auto hwConfig = mDisplayInterface->getActiveModeId();
+ if (pendingConfig != UINT_MAX && pendingConfig != hwConfig) {
+ if (applyPendingConfig() == HWC2_ERROR_NONE) {
+ DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, pendingConfig,
+ getRefreshRate(pendingConfig));
+ } else {
+ DISPLAY_LOGE("%s: failed to set config=%d rate=%d", __func__, pendingConfig,
+ getRefreshRate(pendingConfig));
+ }
+ } else {
+ mPendingConfig = UINT_MAX;
+ DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, hwConfig, getRefreshRate(hwConfig));
+ }
+}
+
+// This function should be called by other threads (e.g. sensor HAL).
+// HWCService can call this function but it should be for test purpose only.
int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
+ int ret = OK;
// NOTE: mLhbmOn could be set to false at any time by setPowerOff in another
// thread. Make sure no side effect if that happens. Or add lock if we have
// to when new code is added.
- ATRACE_CALL();
- if (enabled) {
- ATRACE_NAME("wait for peak refresh rate");
- for (int32_t i = 0; i <= kLhbmWaitForPeakRefreshRate; i++) {
- if (!isCurrentPeakRefreshRate()) {
- if (i == kLhbmWaitForPeakRefreshRate) {
- ALOGW("setLhbmState(on) wait for peak refresh rate timeout !");
- return TIMED_OUT;
- }
- usleep(mVsyncPeriod / 1000 + 1);
- } else {
- ALOGI_IF(i, "waited %d vsync to reach peak refresh rate", i);
- break;
+ DISPLAY_ATRACE_CALL();
+ DISPLAY_LOGI("%s: enabled=%d", __func__, enabled);
+ {
+ ATRACE_NAME("wait_for_power_on");
+ std::unique_lock<std::mutex> lock(mPowerModeMutex);
+ if (mPowerModeState != HWC2_POWER_MODE_ON) {
+ mNotifyPowerOn = true;
+ if (!mPowerOnCondition.wait_for(lock, std::chrono::milliseconds(2000), [this]() {
+ return (mPowerModeState == HWC2_POWER_MODE_ON);
+ })) {
+ DISPLAY_LOGW("%s: wait for power mode on timeout !", __func__);
+ return TIMED_OUT;
}
}
}
- requestLhbm(enabled);
- constexpr uint32_t kSysfsCheckTimeoutMs = 500;
- ALOGI("setLhbmState =%d", enabled);
- bool succeed = mBrightnessController->checkSysfsStatus(
- BrightnessController::kLocalHbmModeFileNode,
- std::to_string(enabled ? 1 : 0),
- ms2ns(kSysfsCheckTimeoutMs));
- if (!succeed) {
- ALOGE("failed to update lhbm mode");
- return -ENODEV;
+ auto lhbmSysfs = mBrightnessController->GetPanelSysfileByIndex(
+ BrightnessController::kLocalHbmModeFileNode);
+ ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
+ {std::to_string(static_cast<int>(
+ BrightnessController::LhbmMode::DISABLED))},
+ 0);
+ bool wasDisabled = ret == OK;
+ if (!enabled && wasDisabled) {
+ DISPLAY_LOGW("%s: lhbm is at DISABLED state, skip disabling", __func__);
+ return NO_ERROR;
+ } else if (enabled && !wasDisabled) {
+ requestLhbm(true);
+ DISPLAY_LOGI("%s: lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer",
+ __func__);
+ return NO_ERROR;
+ }
+
+ std::vector<std::string> checkingValue;
+ if (!enabled) {
+ ATRACE_NAME("disable_lhbm");
+ {
+ Mutex::Autolock lock(mDisplayMutex);
+ restoreLhbmDisplayConfigLocked();
+ }
+ requestLhbm(false);
+ {
+ ATRACE_NAME("wait_for_lhbm_off_cmd");
+ checkingValue = {
+ std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))};
+ ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
+ ms2ns(kSysfsCheckTimeoutMs));
+ if (ret != OK) {
+ DISPLAY_LOGW("%s: failed to send lhbm-off cmd", __func__);
+ }
+ }
+ setLHBMRefreshRateThrottle(0);
+ mLhbmOn = false;
+ return NO_ERROR;
}
+ ATRACE_NAME("enable_lhbm");
+ int64_t lhbmWaitForRrNanos, lhbmEnablingNanos, lhbmEnablingDoneNanos;
+ bool enablingStateSupported = !mFramesToReachLhbmPeakBrightness;
+ uint32_t peakRate = 0;
+ auto rrSysfs = mBrightnessController->GetPanelRefreshRateSysfile();
+ lhbmWaitForRrNanos = systemTime(SYSTEM_TIME_MONOTONIC);
{
- // lhbm takes effect at next vblank
- ATRACE_NAME("lhbm_wait_apply");
- if (mDisplayInterface->waitVBlank()) {
- ALOGE("%s failed to wait vblank", __func__);
- return -ENODEV;
+ Mutex::Autolock lock(mDisplayMutex);
+ peakRate = getPeakRefreshRate();
+ if (peakRate < 60) {
+ DISPLAY_LOGE("%s: invalid peak rate=%d", __func__, peakRate);
+ return -EINVAL;
}
+ ret = setLhbmDisplayConfigLocked(peakRate);
+ if (ret != OK) return ret;
}
- if (enabled) {
- for (int32_t i = mFramesToReachLhbmPeakBrightness; i > 0; i--) {
- ATRACE_NAME("lhbm_wait_peak_brightness");
- mDevice->onRefresh();
+ if (mBrightnessController->fileExists(rrSysfs)) {
+ ATRACE_NAME("wait_for_peak_rate_cmd");
+ ret = mBrightnessController->checkSysfsStatus(rrSysfs, {std::to_string(peakRate)},
+ ms2ns(kLhbmWaitForPeakRefreshRateMs));
+ if (ret != OK) {
+ DISPLAY_LOGW("%s: failed to poll peak refresh rate=%d, ret=%d", __func__, peakRate,
+ ret);
+ }
+ } else {
+ ATRACE_NAME("wait_for_peak_rate_blindly");
+ DISPLAY_LOGW("%s: missing refresh rate path: %s", __func__, rrSysfs.c_str());
+ // blindly wait for (3 full frames + 1 frame uncertainty) to ensure DM finishes
+ // switching refresh rate
+ for (int32_t i = 0; i < 4; i++) {
if (mDisplayInterface->waitVBlank()) {
- ALOGE("%s failed to wait vblank, %d", __func__, i);
- return -ENODEV;
+ DISPLAY_LOGE("%s: failed to blindly wait for peak refresh rate=%d, i=%d", __func__,
+ peakRate, i);
+ ret = -ENODEV;
+ goto enable_err;
}
}
}
- mLhbmOn = enabled;
- if (mPowerModeState == HWC2_POWER_MODE_OFF && mLhbmOn) {
+ setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs);
+ checkingValue = {std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLING)),
+ std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLED))};
+ lhbmEnablingNanos = systemTime(SYSTEM_TIME_MONOTONIC);
+ requestLhbm(true);
+ {
+ ATRACE_NAME("wait_for_lhbm_on_cmd");
+ ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
+ ms2ns(kSysfsCheckTimeoutMs));
+ if (ret != OK) {
+ DISPLAY_LOGE("%s: failed to enable lhbm", __func__);
+ setLHBMRefreshRateThrottle(0);
+ goto enable_err;
+ }
+ }
+
+ lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC);
+ {
+ ATRACE_NAME("wait_for_peak_brightness");
+ if (enablingStateSupported) {
+ ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
+ {std::to_string(static_cast<int>(
+ BrightnessController::LhbmMode::ENABLED))},
+ ms2ns(kSysfsCheckTimeoutMs));
+ if (ret != OK) {
+ DISPLAY_LOGE("%s: failed to wait for lhbm becoming effective", __func__);
+ goto enable_err;
+ }
+ } else {
+ // lhbm takes effect at next vblank
+ for (int32_t i = mFramesToReachLhbmPeakBrightness + 1; i > 0; i--) {
+ ret = mDisplayInterface->waitVBlank();
+ if (ret) {
+ DISPLAY_LOGE("%s: failed to wait vblank for peak brightness, %d", __func__, i);
+ goto enable_err;
+ }
+ }
+ }
+ }
+ DISPLAY_LOGI("%s: latency: %04d = %03d|rr@%03d + %03d|en + %03d|boost@%s", __func__,
+ getTimestampDeltaMs(0, lhbmWaitForRrNanos),
+ getTimestampDeltaMs(lhbmEnablingNanos, lhbmWaitForRrNanos), peakRate,
+ getTimestampDeltaMs(lhbmEnablingDoneNanos, lhbmEnablingNanos),
+ getTimestampDeltaMs(0, lhbmEnablingDoneNanos),
+ enablingStateSupported ? "polling" : "fixed");
+
+ mLhbmOn = true;
+ if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF && mLhbmOn)) {
mLhbmOn = false;
- ALOGE("%s power off during request lhbm on", __func__);
+ DISPLAY_LOGE("%s: power off during request lhbm on", __func__);
return -EINVAL;
}
return NO_ERROR;
+enable_err:
+ Mutex::Autolock lock(mDisplayMutex);
+ restoreLhbmDisplayConfigLocked();
+ return ret;
}
bool ExynosPrimaryDisplay::getLhbmState() {
return mLhbmOn;
}
+void ExynosPrimaryDisplay::setLHBMRefreshRateThrottle(const uint32_t delayMs) {
+ ATRACE_CALL();
+
+ if (delayMs) {
+ // make new throttle take effect
+ mLastRefreshRateAppliedNanos = systemTime(SYSTEM_TIME_MONOTONIC);
+ DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
+ }
+
+ setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::milliseconds(delayMs))
+ .count(),
+ VrrThrottleRequester::LHBM);
+}
+
void ExynosPrimaryDisplay::setEarlyWakeupDisplay() {
if (mEarlyWakeupDispFd) {
writeFileNode(mEarlyWakeupDispFd, 1);
@@ -595,10 +813,10 @@ int32_t ExynosPrimaryDisplay::setDisplayIdleTimer(const int32_t timeoutMs) {
}
if (timeoutMs > 0) {
- setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::milliseconds(timeoutMs))
- .count(),
- DispIdleTimerRequester::SF);
+ setDisplayIdleDelayNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::milliseconds(timeoutMs))
+ .count(),
+ DispIdleTimerRequester::SF);
}
bool enabled = (timeoutMs > 0);
@@ -617,7 +835,7 @@ int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
return HWC2_ERROR_UNSUPPORTED;
}
- const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "panel_idle";
+ const std::string path = getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "panel_idle";
std::ifstream ifs(path);
if (!ifs.is_open()) {
ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
@@ -633,7 +851,7 @@ int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
}
int32_t ExynosPrimaryDisplay::setDisplayIdleTimerEnabled(const bool enabled) {
- const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "panel_idle";
+ const std::string path = getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "panel_idle";
std::ofstream ofs(path);
if (!ofs.is_open()) {
ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
@@ -646,13 +864,48 @@ int32_t ExynosPrimaryDisplay::setDisplayIdleTimerEnabled(const bool enabled) {
return NO_ERROR;
}
+int32_t ExynosPrimaryDisplay::setDisplayIdleDelayNanos(const int32_t delayNanos,
+ const DispIdleTimerRequester requester) {
+ std::lock_guard<std::mutex> lock(mDisplayIdleDelayMutex);
+
+ int64_t maxDelayNanos = 0;
+ mDisplayIdleTimerNanos[toUnderlying(requester)] = delayNanos;
+ for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
+ if (mDisplayIdleTimerNanos[i] > maxDelayNanos) {
+ maxDelayNanos = mDisplayIdleTimerNanos[i];
+ }
+ }
+
+ if (mDisplayIdleDelayNanos == maxDelayNanos) {
+ return NO_ERROR;
+ }
+
+ mDisplayIdleDelayNanos = maxDelayNanos;
+
+ const int32_t displayIdleDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::nanoseconds(mDisplayIdleDelayNanos))
+ .count();
+ const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "idle_delay_ms";
+ std::ofstream ofs(path);
+ if (!ofs.is_open()) {
+ ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
+ return errno;
+ } else {
+ ofs << displayIdleDelayMs;
+ ALOGI("%s() writes idle_delay_ms(%d) to the sysfs node (0x%x)", __func__,
+ displayIdleDelayMs, ofs.rdstate());
+ ofs.close();
+ }
+ return NO_ERROR;
+}
+
void ExynosPrimaryDisplay::initDisplayHandleIdleExit() {
if (bool support; getDisplayIdleTimerSupport(support) || support == false) {
return;
}
const std::string path =
- getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "panel_need_handle_idle_exit";
+ getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "panel_need_handle_idle_exit";
mDisplayNeedHandleIdleExitOfs.open(path, std::ofstream::out);
if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
ALOGI("%s() '%s' doesn't exist(%s)", __func__, path.c_str(), strerror(errno));
@@ -698,7 +951,7 @@ void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRa
bool needed = false;
for (size_t i = 0; i < mLayers.size(); i++) {
if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
- !mLayers[i]->checkDownscaleCap(idleTeRefreshRate)) {
+ !mLayers[i]->checkBtsCap(idleTeRefreshRate)) {
needed = true;
break;
}
@@ -710,7 +963,7 @@ void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRa
int ExynosPrimaryDisplay::setMinIdleRefreshRate(const int fps) {
mMinIdleRefreshRate = fps;
- const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "min_vrefresh";
+ const std::string path = getPanelSysfsPath(getDisplayTypeFromIndex(mIndex)) + "min_vrefresh";
std::ofstream ofs(path);
if (!ofs.is_open()) {
ALOGW("Unable to open node '%s', error = %s", path.c_str(), strerror(errno));
@@ -725,7 +978,8 @@ int ExynosPrimaryDisplay::setMinIdleRefreshRate(const int fps) {
}
int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
- const DispIdleTimerRequester requester) {
+ const VrrThrottleRequester requester) {
+ ATRACE_CALL();
ALOGI("%s() requester(%u) set delay to %" PRId64 "ns", __func__, toUnderlying(requester),
delayNanos);
if (delayNanos < 0) {
@@ -736,45 +990,36 @@ int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
int64_t maxDelayNanos = 0;
- mDisplayIdleTimerNanos[toUnderlying(requester)] = delayNanos;
- for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
- if (mDisplayIdleTimerNanos[i] > maxDelayNanos) {
- maxDelayNanos = mDisplayIdleTimerNanos[i];
+ mVrrThrottleNanos[toUnderlying(requester)] = delayNanos;
+ for (uint32_t i = 0; i < toUnderlying(VrrThrottleRequester::MAX); i++) {
+ if (mVrrThrottleNanos[i] > maxDelayNanos) {
+ maxDelayNanos = mVrrThrottleNanos[i];
}
}
+ DISPLAY_ATRACE_INT64("RefreshRateDelay", ns2ms(maxDelayNanos));
if (mRefreshRateDelayNanos == maxDelayNanos) {
return NO_ERROR;
}
mRefreshRateDelayNanos = maxDelayNanos;
-
- const int32_t refreshRateDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::nanoseconds(mRefreshRateDelayNanos))
- .count();
- const std::string path = getPanelSysfsPath(DisplayType::DISPLAY_PRIMARY) + "idle_delay_ms";
- std::ofstream ofs(path);
- if (!ofs.is_open()) {
- ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
- return errno;
- } else {
- ofs << refreshRateDelayMs;
- ALOGI("%s() writes idle_delay_ms(%d) to the sysfs node (0x%x)", __func__,
- refreshRateDelayMs, ofs.rdstate());
- ofs.close();
- }
-
- return NO_ERROR;
+ return setDisplayIdleDelayNanos(mRefreshRateDelayNanos, DispIdleTimerRequester::VRR_THROTTLE);
}
void ExynosPrimaryDisplay::dump(String8 &result) {
ExynosDisplay::dump(result);
result.appendFormat("Display idle timer: %s\n",
(mDisplayIdleTimerEnabled) ? "enabled" : "disabled");
+ for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
+ result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mDisplayIdleTimerNanos[i]);
+ }
result.appendFormat("Min idle refresh rate: %d\n", mMinIdleRefreshRate);
result.appendFormat("Refresh rate delay: %" PRId64 " ns\n", mRefreshRateDelayNanos);
- for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
- result.appendFormat("\t[%u] set to %" PRId64 " ns\n", i, mDisplayIdleTimerNanos[i]);
+ for (uint32_t i = 0; i < toUnderlying(VrrThrottleRequester::MAX); i++) {
+ result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mVrrThrottleNanos[i]);
+ }
+ if (mOperationRateManager) {
+ result.appendFormat("Operation rate: %d\n", mOperationRateManager->getOperationRate());
}
result.appendFormat("\n");
}
@@ -782,6 +1027,7 @@ void ExynosPrimaryDisplay::dump(String8 &result) {
void ExynosPrimaryDisplay::calculateTimeline(
hwc2_config_t config, hwc_vsync_period_change_constraints_t *vsyncPeriodChangeConstraints,
hwc_vsync_period_change_timeline_t *outTimeline) {
+ ATRACE_CALL();
int64_t desiredUpdateTime = vsyncPeriodChangeConstraints->desiredTimeNanos;
const int64_t origDesiredUpdateTime = desiredUpdateTime;
const int64_t threshold = mRefreshRateDelayNanos;
@@ -809,31 +1055,30 @@ void ExynosPrimaryDisplay::calculateTimeline(
getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
- if (isDelayed) {
- DISPLAY_LOGD(eDebugDisplayConfig,
- "requested config : %d(%d)->%d(%d) is delayed! "
- "delta %" PRId64 ", delay %" PRId64 ", threshold %" PRId64 ", "
- "desired %" PRId64 "->%" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64
- ", refreshTimeNanos:%" PRId64,
- mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
- mDisplayConfigs[config].vsyncPeriod, lastUpdateDelta,
- threshold - lastUpdateDelta, threshold, origDesiredUpdateTime,
- mVsyncPeriodChangeConstraints.desiredTimeNanos,
- outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
- } else {
- DISPLAY_LOGD(eDebugDisplayConfig,
- "requested config : %d(%d)->%d(%d), "
- "lastUpdateDelta %" PRId64 ", threshold %" PRId64 ", "
- "desired %" PRId64 ", newVsyncAppliedTimeNanos : %" PRId64 "",
- mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
- mDisplayConfigs[config].vsyncPeriod, lastUpdateDelta, threshold,
- mVsyncPeriodChangeConstraints.desiredTimeNanos,
- outTimeline->newVsyncAppliedTimeNanos);
- }
+ const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ DISPLAY_LOGD_AND_ATRACE_NAME(eDebugDisplayConfig,
+ "requested config : %d(%d)->%d(%d), isDelay:%d,"
+ " delta %" PRId64 ", delay %" PRId64 ", threshold %" PRId64 ", "
+ "now:%" PRId64 ", desired %" PRId64 "->%" PRId64
+ ", newVsyncAppliedTimeNanos : %" PRId64
+ ", refreshTimeNanos:%" PRId64
+ ", mLastRefreshRateAppliedNanos:%" PRId64,
+ mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
+ mDisplayConfigs[config].vsyncPeriod, isDelayed,
+ ns2ms(lastUpdateDelta), ns2ms(threshold - lastUpdateDelta),
+ ns2ms(threshold), ns2ms(now), ns2ms(origDesiredUpdateTime),
+ ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos),
+ ns2ms(outTimeline->newVsyncAppliedTimeNanos),
+ ns2ms(outTimeline->refreshTimeNanos),
+ ns2ms(mLastRefreshRateAppliedNanos));
+
+ const int64_t diffMs = ns2ms(outTimeline->refreshTimeNanos - now);
+ DISPLAY_ATRACE_INT64("TimeToChangeConfig", diffMs);
}
void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConfig,
const int64_t ts) {
+ ATRACE_CALL();
if (mAppliedActiveConfig == 0 ||
getDisplayVsyncPeriodFromConfig(mAppliedActiveConfig) !=
getDisplayVsyncPeriodFromConfig(newConfig)) {
@@ -842,6 +1087,7 @@ void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConf
" -> %" PRIu64 ")",
__func__, mAppliedActiveConfig, newConfig, mLastRefreshRateAppliedNanos, ts);
mLastRefreshRateAppliedNanos = ts;
+ DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
}
mAppliedActiveConfig = newConfig;
@@ -852,10 +1098,11 @@ void ExynosPrimaryDisplay::checkBtsReassignResource(const uint32_t vsyncPeriod,
ATRACE_CALL();
uint32_t refreshRate = static_cast<uint32_t>(round(nsecsPerSec / vsyncPeriod * 0.1f) * 10);
+ Mutex::Autolock lock(mDRMutex);
if (vsyncPeriod < btsVsyncPeriod) {
for (size_t i = 0; i < mLayers.size(); i++) {
if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
- !mLayers[i]->checkDownscaleCap(refreshRate)) {
+ !mLayers[i]->checkBtsCap(refreshRate)) {
mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
break;
}
@@ -878,3 +1125,12 @@ void ExynosPrimaryDisplay::checkBtsReassignResource(const uint32_t vsyncPeriod,
}
}
}
+
+bool ExynosPrimaryDisplay::isDbmSupported() {
+ return mBrightnessController->isDbmSupported();
+}
+
+int32_t ExynosPrimaryDisplay::setDbmState(bool enabled) {
+ mBrightnessController->processDimBrightness(enabled);
+ return NO_ERROR;
+}
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
index 2aa0325..323eb5a 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
@@ -20,10 +20,12 @@
#include "../libdevice/ExynosDisplay.h"
+using namespace displaycolor;
+
class ExynosPrimaryDisplay : public ExynosDisplay {
public:
/* Methods */
- ExynosPrimaryDisplay(uint32_t index, ExynosDevice *device);
+ ExynosPrimaryDisplay(uint32_t index, ExynosDevice* device, const std::string& displayName);
~ExynosPrimaryDisplay();
virtual void setDDIScalerEnable(int width, int height);
virtual int getDDIScalerMode(int width, int height);
@@ -33,6 +35,7 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
return currentPanelGammaSource;
}
+ virtual bool isLhbmSupported();
virtual int32_t setLhbmState(bool enabled);
virtual bool getLhbmState();
@@ -48,7 +51,10 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
virtual int setMinIdleRefreshRate(const int fps) override;
virtual int setRefreshRateThrottleNanos(const int64_t delayNs,
- const DispIdleTimerRequester requester) override;
+ const VrrThrottleRequester requester) override;
+ virtual bool isDbmSupported() override;
+ virtual int32_t setDbmState(bool enabled) override;
+
virtual void dump(String8& result) override;
virtual void updateAppliedActiveConfig(const hwc2_config_t newConfig,
const int64_t ts) override;
@@ -57,7 +63,9 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
virtual int32_t setBootDisplayConfig(int32_t config) override;
virtual int32_t clearBootDisplayConfig() override;
- virtual int32_t getPreferredDisplayConfigInternal(int32_t *outConfig) override;
+ virtual int32_t getPreferredDisplayConfigInternal(int32_t* outConfig) override;
+ virtual bool isConfigSettingEnabled() override;
+ virtual void enableConfigSetting(bool en) override;
protected:
/* setPowerMode(int32_t mode)
@@ -72,20 +80,30 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
virtual bool getHDRException(ExynosLayer* __unused layer);
virtual int32_t setActiveConfigInternal(hwc2_config_t config, bool force) override;
virtual int32_t getActiveConfigInternal(hwc2_config_t* outConfig) override;
+ DisplayType getDisplayTypeFromIndex(uint32_t index) {
+ return (index >= DisplayType::DISPLAY_MAX) ? DisplayType::DISPLAY_PRIMARY
+ : DisplayType(mIndex);
+ };
+
public:
// Prepare multi resolution
ResolutionInfo mResolutionInfo;
std::string getPanelSysfsPath(const displaycolor::DisplayType& type);
+ uint32_t mRcdId = -1;
+
private:
static constexpr const char* kDisplayCalFilePath = "/mnt/vendor/persist/display/";
static constexpr const char* kPanelGammaCalFilePrefix = "gamma_calib_data";
enum PanelGammaSource currentPanelGammaSource = PanelGammaSource::GAMMA_DEFAULT;
bool checkLhbmMode(bool status, nsecs_t timoutNs);
+ void setLHBMRefreshRateThrottle(const uint32_t delayMs);
- hwc2_config_t mPendActiveConfig = UINT_MAX;
bool mFirstPowerOn = true;
+ bool mNotifyPowerOn = false;
+ std::mutex mPowerModeMutex;
+ std::condition_variable mPowerOnCondition;
int32_t applyPendingConfig();
int32_t setPowerOn();
@@ -95,14 +113,28 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
int32_t setDisplayIdleTimerEnabled(const bool enabled);
int32_t getDisplayIdleTimerEnabled(bool& enabled);
void setDisplayNeedHandleIdleExit(const bool needed, const bool force);
+ int32_t setDisplayIdleDelayNanos(int32_t delayNanos,
+ const DispIdleTimerRequester requester);
void initDisplayHandleIdleExit();
+ int32_t setLhbmDisplayConfigLocked(uint32_t peakRate);
+ void restoreLhbmDisplayConfigLocked();
// LHBM
FILE* mLhbmFd;
std::atomic<bool> mLhbmOn;
int32_t mFramesToReachLhbmPeakBrightness;
- // wait num of vsync periods for peak refresh rate
- static constexpr uint32_t kLhbmWaitForPeakRefreshRate = 10;
+ bool mConfigSettingDisabled = false;
+ int64_t mConfigSettingDisabledTimestamp = 0;
+ // timeout value of waiting for peak refresh rate
+ static constexpr uint32_t kLhbmWaitForPeakRefreshRateMs = 100U;
+ static constexpr uint32_t kLhbmRefreshRateThrottleMs = 1000U;
+ static constexpr uint32_t kConfigDisablingMaxDurationMs = 1000U;
+ static constexpr uint32_t kSysfsCheckTimeoutMs = 500U;
+
+ int32_t getTimestampDeltaMs(int64_t endNs, int64_t beginNs) {
+ if (endNs == 0) endNs = systemTime(SYSTEM_TIME_MONOTONIC);
+ return (endNs - beginNs) / 1000000;
+ }
FILE* mEarlyWakeupDispFd;
static constexpr const char* kWakeupDispFilePath =
@@ -115,13 +147,16 @@ class ExynosPrimaryDisplay : public ExynosDisplay {
hwc_vsync_period_change_timeline_t* outTimeline) override;
std::mutex mIdleRefreshRateThrottleMutex;
int mMinIdleRefreshRate;
+ int64_t mVrrThrottleNanos[toUnderlying(VrrThrottleRequester::MAX)];
int64_t mRefreshRateDelayNanos;
int64_t mLastRefreshRateAppliedNanos;
hwc2_config_t mAppliedActiveConfig;
+ std::mutex mDisplayIdleDelayMutex;
bool mDisplayIdleTimerEnabled;
int64_t mDisplayIdleTimerNanos[toUnderlying(DispIdleTimerRequester::MAX)];
std::ofstream mDisplayNeedHandleIdleExitOfs;
+ int64_t mDisplayIdleDelayNanos;
bool mDisplayNeedHandleIdleExit;
};
diff --git a/libhwc2.1/libresource/ExynosMPP.cpp b/libhwc2.1/libresource/ExynosMPP.cpp
index 740cec7..119420e 100644
--- a/libhwc2.1/libresource/ExynosMPP.cpp
+++ b/libhwc2.1/libresource/ExynosMPP.cpp
@@ -43,13 +43,11 @@
using namespace android;
using namespace vendor::graphics;
+using namespace SOC_VERSION;
int ExynosMPP::mainDisplayWidth = 0;
int ExynosMPP::mainDisplayHeight = 0;
extern struct exynos_hwc_control exynosHWCControl;
-#ifndef USE_MODULE_ATTR
-extern feature_support_t feature_table[];
-#endif
void dumpExynosMPPImgInfo(uint32_t type, exynos_mpp_img_info &imgInfo)
{
@@ -100,6 +98,8 @@ ExynosMPPSource::ExynosMPPSource()
memset(&mMidImg, 0, sizeof(mMidImg));
mMidImg.acquireFenceFd = -1;
mMidImg.releaseFenceFd = -1;
+
+ mHWResourceAmount.clear();
}
ExynosMPPSource::ExynosMPPSource(uint32_t sourceType, void *source)
@@ -130,6 +130,40 @@ void ExynosMPPSource::setExynosMidImage(exynos_image mid_img)
mMidImg = mid_img;
}
+uint32_t ExynosMPPSource::needHWResource(tdm_attr_t attr) {
+ uint32_t ret = 0;
+
+ switch (attr) {
+ case TDM_ATTR_SBWC:
+ ret = (isFormatSBWC(mSrcImg.format)) ? 1 : 0;
+ break;
+ case TDM_ATTR_AFBC:
+ ret = (mSrcImg.compressed == 1) ? 1 : 0;
+ break;
+ case TDM_ATTR_ITP: // CSC
+ ret = (isFormatYUV(mSrcImg.format)) ? 1 : 0;
+ break;
+ case TDM_ATTR_ROT_90:
+ ret = ((mSrcImg.transform & HAL_TRANSFORM_ROT_90) == 0) ? 0 : 1;
+ break;
+ case TDM_ATTR_SCALE:
+ {
+ bool isPerpendicular = !!(mSrcImg.transform & HAL_TRANSFORM_ROT_90);
+ if (isPerpendicular) {
+ ret = ((mSrcImg.w != mDstImg.h) || (mSrcImg.h != mDstImg.w)) ? 1 : 0;
+ } else {
+ ret = ((mSrcImg.w != mDstImg.w) || (mSrcImg.h != mDstImg.h)) ? 1 : 0;
+ }
+ }
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
ExynosMPP::ExynosMPP(ExynosResourceManager* resourceManager,
uint32_t physicalType, uint32_t logicalType, const char *name,
uint32_t physicalIndex, uint32_t logicalIndex, uint32_t preAssignInfo)
@@ -162,6 +196,9 @@ ExynosMPP::ExynosMPP(ExynosResourceManager* resourceManager,
mDstAllocatedSize(DST_SIZE_UNKNOWN),
mUseM2MSrcFence(false),
mAttr(0),
+ mAssignOrder(0),
+ mAXIPortId(0),
+ mHWBlockId(0),
mNeedSolidColorLayer(false)
{
if (mPhysicalType < MPP_DPP_NUM) {
@@ -314,7 +351,7 @@ bool ExynosMPP::isDataspaceSupportedByMPP(struct exynos_image &src, struct exyno
return checkCSCRestriction(src, dst);
}
-bool ExynosMPP::isSupportedHDR10Plus(struct exynos_image &src, struct exynos_image &dst)
+bool ExynosMPP::isSupportedHDR(struct exynos_image &src, struct exynos_image &dst)
{
uint32_t srcStandard = (src.dataSpace & HAL_DATASPACE_STANDARD_MASK);
@@ -322,7 +359,7 @@ bool ExynosMPP::isSupportedHDR10Plus(struct exynos_image &src, struct exynos_ima
uint32_t srcTransfer = (src.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
uint32_t dstTransfer = (dst.dataSpace & HAL_DATASPACE_TRANSFER_MASK);
- if (hasHdr10Plus(src)) {
+ if (hasHdr10Plus(src) || hasHdrInfo(src) ) {
if (mAttr & MPP_ATTR_HDR10PLUS)
return true;
else if ((srcStandard == dstStandard) && (srcTransfer == dstTransfer))
@@ -964,9 +1001,10 @@ int32_t ExynosMPP::allocOutBuf(uint32_t w, uint32_t h, uint32_t format, uint64_t
mDstImgs[index].format = format;
MPP_LOGD(eDebugMPP|eDebugBuf, "free outbuf[%d] %p", index, freeDstBuf.bufferHandle);
- if (freeDstBuf.bufferHandle != NULL)
+
+ if (freeDstBuf.bufferHandle != NULL) {
freeOutBuf(freeDstBuf);
- else {
+ } else {
if (mAssignedDisplay != NULL) {
freeDstBuf.acrylicAcquireFenceFd = fence_close(freeDstBuf.acrylicAcquireFenceFd,
mAssignedDisplay, FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_G2D);
@@ -1081,16 +1119,23 @@ bool ExynosMPP::needDstBufRealloc(struct exynos_image &dst, uint32_t index)
VendorGraphicBufferMeta gmeta(dst_handle);
+ uint32_t prevAssignedBufferNum =
+ getBufferNumOfFormat(gmeta.format, getCompressionType(dst_handle));
+ uint32_t assignedBufferNum = getBufferNumOfFormat(dst.format, getCompressionType(dst_handle));
+
MPP_LOGD(eDebugMPP | eDebugBuf, "\tdst_handle(%p) afbc (%u) sbwc (%u) lossy (%u)", dst_handle,
isAFBCCompressed(dst_handle), isFormatSBWC(gmeta.format), isFormatLossy(gmeta.format));
MPP_LOGD(eDebugMPP | eDebugBuf,
- "\tAssignedDisplay[%d, %d] format[0x%8x, 0x%8x], bufferType[%d, %d], usageFlags: "
- "0x%" PRIx64 ", need afbc %u sbwc %u lossy %u",
+ "\tAssignedDisplay[%d, %d] format[0x%8x, 0x%8x], bufferType[%d, %d], bufferNum[%d, "
+ "%d] "
+ "usageFlags: 0x%" PRIx64 ", need afbc %u sbwc %u lossy %u",
mPrevAssignedDisplayType, assignedDisplay, gmeta.format, dst.format,
- mDstImgs[index].bufferType, getBufferType(dst.usageFlags), dst.usageFlags,
- dst.compressed, isFormatSBWC(dst.format), isFormatLossy(dst.format));
+ mDstImgs[index].bufferType, getBufferType(dst.usageFlags), prevAssignedBufferNum,
+ assignedBufferNum, dst.usageFlags, dst.compressed, isFormatSBWC(dst.format),
+ isFormatLossy(dst.format));
bool realloc = (mPrevAssignedDisplayType != assignedDisplay) ||
+ (prevAssignedBufferNum < assignedBufferNum) ||
(formatToBpp(gmeta.format) < formatToBpp(dst.format)) ||
((gmeta.stride * gmeta.vstride) < (int)(dst.fullWidth * dst.fullHeight)) ||
(mDstImgs[index].bufferType != getBufferType(dst.usageFlags)) ||
@@ -1355,9 +1400,10 @@ int32_t ExynosMPP::setupDst(exynos_mpp_img_info *dstImgInfo)
if (dstImgInfo->bufferType == MPP_BUFFER_SECURE_DRM)
attribute |= AcrylicCanvas::ATTR_PROTECTED;
- if (mAssignedDisplay != NULL)
+ if (mAssignedDisplay != NULL) {
mAcrylicHandle->setCanvasDimension(pixel_align(mAssignedDisplay->mXres, G2D_JUSTIFIED_DST_ALIGN),
pixel_align(mAssignedDisplay->mYres, G2D_JUSTIFIED_DST_ALIGN));
+ }
/* setup dst */
if (needCompressDstBuf()) {
@@ -1879,13 +1925,15 @@ int32_t ExynosMPP::requestHWStateChange(uint32_t state)
return NO_ERROR;
}
- if (state == MPP_HW_STATE_RUNNING)
+ if (state == MPP_HW_STATE_RUNNING) {
mHWState = MPP_HW_STATE_RUNNING;
- else if (state == MPP_HW_STATE_IDLE) {
- if (mLastStateFenceFd >= 0)
+ } else if (state == MPP_HW_STATE_IDLE) {
+ if (mLastStateFenceFd >= 0) {
mResourceManageThread->addStateFence(mLastStateFenceFd);
- else
+ } else {
mHWState = MPP_HW_STATE_IDLE;
+ }
+
mLastStateFenceFd = -1;
if ((mPhysicalType == MPP_G2D) && (mHWBusyFlag == false)) {
@@ -2056,7 +2104,7 @@ int64_t ExynosMPP::isSupported(ExynosDisplay &display, struct exynos_image &src,
return -eMPPUnsupportedFormat;
else if (!isDataspaceSupportedByMPP(src, dst))
return -eMPPUnsupportedCSC;
- else if (!isSupportedHDR10Plus(src, dst))
+ else if (!isSupportedHDR(src, dst))
return -eMPPUnsupportedDynamicMeta;
else if (!isSupportedBlend(src))
return -eMPPUnsupportedBlending;
@@ -2320,41 +2368,50 @@ bool ExynosMPP::isAssignableState(ExynosDisplay *display, struct exynos_image &s
isAssignable, mAssignedSources.size(), getSrcMaxBlendingNum(src, dst));
return isAssignable;
}
-bool ExynosMPP::isAssignable(ExynosDisplay *display,
- struct exynos_image &src, struct exynos_image &dst)
+
+bool ExynosMPP::isAssignable(ExynosDisplay *display, struct exynos_image &src,
+ struct exynos_image &dst, float totalUsedCapacity)
{
bool isAssignable = isAssignableState(display, src, dst);
- return (isAssignable && hasEnoughCapa(display, src, dst));
+ return (isAssignable && hasEnoughCapa(display, src, dst, totalUsedCapacity));
}
-bool ExynosMPP::hasEnoughCapa(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst)
+bool ExynosMPP::hasEnoughCapa(ExynosDisplay *display, struct exynos_image &src,
+ struct exynos_image &dst, float totalUsedCapacity)
{
if (mCapacity == -1)
return true;
- float totalUsedCapacity = ExynosResourceManager::getResourceUsedCapa(*this);
- MPP_LOGD(eDebugCapacity|eDebugMPP, "totalUsedCapacity(%f), mUsedCapacity(%f)",
- totalUsedCapacity, mUsedCapacity);
+ MPP_LOGD(eDebugCapacity | eDebugMPP, "totalUsedCapacity(%f), mUsedCapacity(%f)",
+ totalUsedCapacity, mUsedCapacity);
/* mUsedCapacity should be re-calculated including src, dst passed as parameters*/
totalUsedCapacity -= mUsedCapacity;
float requiredCapacity = getRequiredCapacity(display, src, dst);
- MPP_LOGD(eDebugCapacity|eDebugMPP, "mCapacity(%f), usedCapacity(%f), RequiredCapacity(%f)",
- mCapacity, totalUsedCapacity, requiredCapacity);
+ MPP_LOGD(eDebugCapacity | eDebugMPP, "mCapacity(%f), usedCapacity(%f), RequiredCapacity(%f)",
+ mCapacity, totalUsedCapacity, requiredCapacity);
if (mCapacity >= (totalUsedCapacity + requiredCapacity))
return true;
- else if ((hasHdrInfo(src)) &&
- (totalUsedCapacity == 0) && (requiredCapacity < (mCapacity * 1.2))) {
- /* HDR video will be excepted from G2D capa calculation */
- /* if DRM has assigned before, totalUsedCapacity will be non-zero */
+ else if (isCapacityExceptionCondition(totalUsedCapacity, requiredCapacity, src))
return true;
- } else
+ else
return false;
}
+bool ExynosMPP::isCapacityExceptionCondition(float totalUsedCapacity, float requiredCapacity,
+ struct exynos_image &src)
+{
+ if ((hasHdrInfo(src) && (totalUsedCapacity == 0) &&
+ (requiredCapacity < (mCapacity * MPP_HDR_MARGIN)))) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
void ExynosMPP::getPPCIndex(const struct exynos_image &src,
const struct exynos_image &dst,
uint32_t &formatIndex, uint32_t &rotIndex, uint32_t &scaleIndex,
diff --git a/libhwc2.1/libresource/ExynosMPP.h b/libhwc2.1/libresource/ExynosMPP.h
index 15cdb83..715c9dc 100644
--- a/libhwc2.1/libresource/ExynosMPP.h
+++ b/libhwc2.1/libresource/ExynosMPP.h
@@ -113,6 +113,11 @@ class ExynosResourceManager;
#ifndef MPP_G2D_CAPACITY
#define MPP_G2D_CAPACITY 8
#endif
+// G2D or MSC additional margin capacity when HDR layer is passed.
+#ifndef MPP_HDR_MARGIN
+#define MPP_HDR_MARGIN 1.2
+#endif
+
#ifndef MPP_MSC_CAPACITY
#define MPP_MSC_CAPACITY 8
#endif
@@ -166,6 +171,8 @@ enum {
eMPPUnsupportedDIMLayer = 1ULL << 30,
eMPPUnsupportedDRM = 1ULL << 31,
eMPPUnsupportedDynamicMeta = 1ULL << 32,
+ eMPPSatisfiedRestriction = 1ULL << 33,
+ eMPPExeedHWResource = 1ULL << 34,
};
enum {
@@ -219,11 +226,13 @@ typedef enum {
#ifndef DEFAULT_MPP_DST_FORMAT
#define DEFAULT_MPP_DST_FORMAT HAL_PIXEL_FORMAT_RGBA_8888
#endif
+
+/* TODO: Switch back to single-fd format, tracked in b/261356480 */
#ifndef DEFAULT_MPP_DST_YUV_FORMAT
-#define DEFAULT_MPP_DST_YUV_FORMAT HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN
+#define DEFAULT_MPP_DST_YUV_FORMAT HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M
#endif
#ifndef DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT
-#define DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN
+#define DEFAULT_MPP_DST_UNCOMP_YUV_FORMAT HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M
#endif
typedef struct exynos_mpp_img_info {
@@ -453,7 +462,22 @@ class ExynosMPPSource {
ExynosMPP *mOtfMPP;
ExynosMPP *mM2mMPP;
+
+ /**
+ * SRAM/HW resource info
+ */
+ std::unordered_map<tdm_attr_t, int32_t> mHWResourceAmount;
+ uint32_t getHWResourceAmount(tdm_attr_t attr) { return mHWResourceAmount[attr]; }
+
+ uint32_t setHWResourceAmount(tdm_attr_t attr, uint32_t amount) {
+ mHWResourceAmount[attr] = amount;
+ return 0;
+ }
+
+ /* return 1 if it's needed */
+ uint32_t needHWResource(tdm_attr_t attr);
};
+
bool exynosMPPSourceComp(const ExynosMPPSource* l, const ExynosMPPSource* r);
void dump(const restriction_size_t &restrictionSize, String8 &result);
@@ -546,6 +570,10 @@ public:
/* MPP's attribute bit (supported feature bit) */
uint64_t mAttr;
+ uint32_t mAssignOrder;
+ uint32_t mAXIPortId;
+ uint32_t mHWBlockId;
+
bool mNeedSolidColorLayer;
ExynosMPP(ExynosResourceManager* resourceManager,
@@ -569,13 +597,18 @@ public:
virtual int64_t isSupported(ExynosDisplay &display, struct exynos_image &src, struct exynos_image &dst);
bool isDataspaceSupportedByMPP(struct exynos_image &src, struct exynos_image &dst);
- bool isSupportedHDR10Plus(struct exynos_image &src, struct exynos_image &dst);
+ bool isSupportedHDR(struct exynos_image &src, struct exynos_image &dst);
bool isSupportedBlend(struct exynos_image &src);
virtual bool isSupportedTransform(struct exynos_image &src);
bool isSupportedCapability(ExynosDisplay &display, struct exynos_image &src);
bool isSupportedDRM(struct exynos_image &src);
virtual bool isSupportedHStrideCrop(struct exynos_image &src);
bool checkDownscaleCap(const float resolution, const float displayRatio_V) const;
+ virtual bool checkSpecificRestriction(const uint32_t __unused refreshRate,
+ const struct exynos_image __unused &src,
+ const struct exynos_image __unused &dst) {
+ return false;
+ }
virtual uint32_t getDownscaleRestriction(const struct exynos_image &src,
const struct exynos_image &dst) const;
virtual uint32_t getMaxDownscale(const ExynosDisplay &display, const struct exynos_image &src,
@@ -633,11 +666,12 @@ public:
int32_t reserveMPP(int32_t displayType = -1);
bool isAssignableState(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst);
- bool isAssignable(ExynosDisplay *display,
- struct exynos_image &src, struct exynos_image &dst);
+ bool isAssignable(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst,
+ float totalUsedCapacity);
int32_t assignMPP(ExynosDisplay *display, ExynosMPPSource* mppSource);
- bool hasEnoughCapa(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst);
+ bool hasEnoughCapa(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst,
+ float totalUsedCapa);
float getRequiredCapacity(ExynosDisplay *display, struct exynos_image &src, struct exynos_image &dst);
int32_t updateUsedCapacity();
void resetUsedCapacity();
@@ -665,6 +699,13 @@ public:
void setPPC(float ppc) { mPPC = ppc; };
void setClockKhz(uint32_t clock) { mClockKhz = clock; };
+ virtual void initTDMInfo(uint32_t hwBlockIndex, uint32_t axiPortIndex) {
+ mHWBlockId = hwBlockIndex;
+ mAXIPortId = axiPortIndex;
+ }
+ virtual uint32_t getHWBlockId() { return mHWBlockId; }
+ virtual uint32_t getAXIPortId() { return mAXIPortId; }
+
protected:
uint32_t getBufferType(uint64_t usage);
uint32_t getBufferType(const buffer_handle_t handle);
@@ -705,6 +746,12 @@ protected:
*/
virtual bool checkCSCRestriction(struct exynos_image &src, struct exynos_image &dst);
+ /*
+ * Check additional conditions those have a capacity exception.
+ */
+ virtual bool isCapacityExceptionCondition(float totalUsedCapacity, float requiredCapacity,
+ struct exynos_image &src);
+
uint32_t mClockKhz = 0;
float mPPC = 0;
};
diff --git a/libhwc2.1/libresource/ExynosMPPType.h b/libhwc2.1/libresource/ExynosMPPType.h
index a4b3026..83477c9 100644
--- a/libhwc2.1/libresource/ExynosMPPType.h
+++ b/libhwc2.1/libresource/ExynosMPPType.h
@@ -18,8 +18,14 @@
#define _EXYNOSMPPTYPE_H
#include <system/graphics.h>
+#include <utils/String8.h>
+
+#include <unordered_map>
+
#include "DeconHeader.h"
+using namespace android;
+
/*
* physical types
* Resources are sorted by physical type.
@@ -28,16 +34,15 @@
typedef enum {
MPP_DPP_G = 0,
MPP_DPP_GF,
+ MPP_DPP_GFS,
MPP_DPP_VG,
MPP_DPP_VGS,
MPP_DPP_VGF,
MPP_DPP_VGFS,
MPP_DPP_VGRFS,
- /* DPP count */
- /* If you add DPP, You should increase this value */
- MPP_DPP_NUM = 7,
+ MPP_DPP_NUM,
- MPP_MSC = 7,
+ MPP_MSC,
MPP_G2D,
MPP_P_TYPE_MAX
} mpp_phycal_type_t;
@@ -46,6 +51,7 @@ typedef enum {
typedef enum {
MPP_LOGICAL_DPP_G = 0x01,
MPP_LOGICAL_DPP_GF = 0x02,
+ MPP_LOGICAL_DPP_GFS = 0x03,
MPP_LOGICAL_DPP_VG = 0x04,
MPP_LOGICAL_DPP_VGS = 0x08,
MPP_LOGICAL_DPP_VGF = 0x10,
@@ -60,7 +66,7 @@ typedef enum {
* Increase MPP_LOGICAL_TYPE_NUM
* if type is added
*/
- MPP_LOGICAL_TYPE_NUM = 12
+ MPP_LOGICAL_TYPE_NUM = 13
} mpp_logical_type_t;
enum {
@@ -81,6 +87,28 @@ enum {
MPP_ATTR_HDR10PLUS = 0x10000000,
};
+// Resource TDM (Time-Division Muliplexing)
+typedef enum {
+ TDM_ATTR_SRAM_AMOUNT,
+ TDM_ATTR_AFBC,
+ TDM_ATTR_SBWC,
+ TDM_ATTR_ITP, // CSC //
+ TDM_ATTR_ROT_90,
+ TDM_ATTR_SCALE,
+ TDM_ATTR_WCG,
+ TDM_ATTR_MAX,
+} tdm_attr_t;
+
+const std::unordered_map<tdm_attr_t, String8> HWAttrs = {
+ {TDM_ATTR_SRAM_AMOUNT, String8("SRAM")},
+ {TDM_ATTR_AFBC, String8("AFBC")},
+ {TDM_ATTR_SBWC, String8("SBWC")},
+ {TDM_ATTR_ITP, String8("CSC")}, // CSC //
+ {TDM_ATTR_ROT_90, String8("ROT")},
+ {TDM_ATTR_SCALE, String8("SCALE")},
+ {TDM_ATTR_WCG, String8("WCG")},
+};
+
typedef struct feature_support_t {
mpp_phycal_type_t hwType; /* MPP_DPP_VG, MPP_DPP_VGFS, ... */
uint64_t attr;
@@ -110,4 +138,19 @@ typedef struct dpp_channel_map {
decon_idma_type channel;
} dpp_channel_map_t;
+/*
+ * pre_assign_info: all display_descriptors that want to reserve
+ */
+struct exynos_mpp_t {
+ int physicalType;
+ int logicalType;
+ char name[16];
+ uint32_t physical_index;
+ uint32_t logical_index;
+ uint32_t pre_assign_info;
+ // For TDM
+ uint32_t hw_block_index;
+ uint32_t axi_port_index;
+};
+
#endif
diff --git a/libhwc2.1/libresource/ExynosResourceManager.cpp b/libhwc2.1/libresource/ExynosResourceManager.cpp
index 57e8e2c..ec4db5f 100644
--- a/libhwc2.1/libresource/ExynosResourceManager.cpp
+++ b/libhwc2.1/libresource/ExynosResourceManager.cpp
@@ -38,51 +38,6 @@
using namespace std::chrono_literals;
constexpr float msecsPerSec = std::chrono::milliseconds(1s).count();
-#ifndef USE_MODULE_ATTR
-/* Basic supported features */
-feature_support_t feature_table[] =
-{
- {MPP_DPP_G,
- MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
- },
-
- {MPP_DPP_GF,
- MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
- },
-
- {MPP_DPP_VG,
- MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
- },
-
- {MPP_DPP_VGS,
- MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_SCALE | MPP_ATTR_DIM
- },
-
- {MPP_DPP_VGF,
- MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_DIM
- },
-
- {MPP_DPP_VGFS,
- MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_SCALE | MPP_ATTR_DIM
- },
-
- {MPP_DPP_VGRFS,
- MPP_ATTR_AFBC | MPP_ATTR_BLOCK_MODE | MPP_ATTR_WINDOW_UPDATE | MPP_ATTR_SCALE |
- MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V | MPP_ATTR_ROT_90 |
- MPP_ATTR_DIM | MPP_ATTR_HDR10
- },
-
- {MPP_MSC,
- MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V | MPP_ATTR_ROT_90
- },
-
- {MPP_G2D,
- MPP_ATTR_AFBC | MPP_ATTR_FLIP_H | MPP_ATTR_FLIP_V | MPP_ATTR_ROT_90 |
- MPP_ATTR_HDR10 | MPP_ATTR_USE_CAPA
- }
-};
-#endif
-
using namespace android;
using namespace vendor::graphics;
using namespace SOC_VERSION;
@@ -155,9 +110,9 @@ ExynosResourceManager::ExynosResourceManager(ExynosDevice *device)
memset(mFormatRestrictions, 0, sizeof(mFormatRestrictions));
memset(mSizeRestrictions, 0, sizeof(mSizeRestrictions));
- size_t num_mpp_units = sizeof(AVAILABLE_OTF_MPP_UNITS)/sizeof(exynos_mpp_t);
+ size_t num_mpp_units = sizeof(available_otf_mpp_units)/sizeof(exynos_mpp_t);
for (size_t i = 0; i < num_mpp_units; i++) {
- exynos_mpp_t exynos_mpp = AVAILABLE_OTF_MPP_UNITS[i];
+ exynos_mpp_t exynos_mpp = available_otf_mpp_units[i];
ALOGI("otfMPP type(%d, %d), physical_index(%d), logical_index(%d)",
exynos_mpp.physicalType, exynos_mpp.logicalType,
exynos_mpp.physical_index, exynos_mpp.logical_index);
@@ -165,6 +120,7 @@ ExynosResourceManager::ExynosResourceManager(ExynosDevice *device)
exynos_mpp.logicalType, exynos_mpp.name, exynos_mpp.physical_index,
exynos_mpp.logical_index, exynos_mpp.pre_assign_info);
exynosMPP->mMPPType = MPP_TYPE_OTF;
+ exynosMPP->initTDMInfo(exynos_mpp.hw_block_index, exynos_mpp.axi_port_index);
mOtfMPPs.add(exynosMPP);
}
@@ -326,6 +282,8 @@ bool ExynosResourceManager::DstBufMgrThread::threadLoop()
ExynosDevice *device = mExynosResourceManager->mDevice;
if (device == NULL)
return false;
+
+ /* TODO(b/265244856): to clarify which display size to alloc */
ExynosDisplay *display = device->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
if (display == NULL)
return false;
@@ -437,6 +395,11 @@ int32_t ExynosResourceManager::assignResource(ExynosDisplay *display)
return ret;
}
+ HDEBUGLOGD(eDebugTDM, "%s layer's calculation start", __func__);
+ for (uint32_t i = 0; i < display->mLayers.size(); i++) {
+ calculateHWResourceAmount(display, display->mLayers[i]);
+ }
+
if (mDevice->isFirstValidate()) {
HDEBUGLOGD(eDebugResourceManager, "This is first validate");
if (exynosHWCControl.displayMode < DISPLAY_MODE_NUM)
@@ -447,7 +410,7 @@ int32_t ExynosResourceManager::assignResource(ExynosDisplay *display)
__func__, ret);
return ret;
}
- preAssignWindows();
+ preAssignWindows(display);
}
@@ -603,7 +566,7 @@ int32_t ExynosResourceManager::assignResourceInternal(ExynosDisplay *display)
}
do {
- HDEBUGLOGD(eDebugResourceManager, "%s:: retry_count(%d)", __func__, retry_count);
+ HDEBUGLOGD(eDebugResourceAssigning, "%s:: retry_count(%d)", __func__, retry_count);
if ((ret = resetAssignedResources(display)) != NO_ERROR)
return ret;
if ((ret = assignCompositionTarget(display, COMPOSITION_CLIENT)) != NO_ERROR) {
@@ -698,6 +661,7 @@ int32_t ExynosResourceManager::assignResourceInternal(ExynosDisplay *display)
}
return ret;
}
+
int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
{
int ret = NO_ERROR;
@@ -710,8 +674,9 @@ int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
uint32_t firstIndex = display->mExynosCompositionInfo.mFirstIndex;
uint32_t remainNum = m2mMPP->mMaxSrcLayerNum - (lastIndex - firstIndex + 1);
- HDEBUGLOGD(eDebugResourceManager, "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d++++",
- firstIndex, lastIndex, remainNum);
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d++++",
+ firstIndex, lastIndex, remainNum);
ExynosLayer *layer = NULL;
exynos_image src_img;
@@ -723,18 +688,20 @@ int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
layer->setSrcExynosImage(&src_img);
layer->setDstExynosImage(&dst_img);
layer->setExynosImage(src_img, dst_img);
- bool isAssignable = false;
+ bool isAssignableState = false;
if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
- isAssignable = m2mMPP->isAssignable(display, src_img, dst_img);
+ isAssignableState = isAssignable(m2mMPP, display, src_img, dst_img, layer);
bool canChange = (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT) &&
- ((display->mDisplayControl.cursorSupport == false) ||
- (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
- (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignable;
-
- HDEBUGLOGD(eDebugResourceManager, "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, remainNum(%d)",
- i, layer->mValidateCompositionType,
- layer->mSupportedMPPFlag, isAssignable, canChange, remainNum);
+ ((display->mDisplayControl.cursorSupport == false) ||
+ (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
+ (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignableState;
+
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, "
+ "remainNum(%d)",
+ i, layer->mValidateCompositionType, layer->mSupportedMPPFlag,
+ isAssignableState, canChange, remainNum);
if (canChange) {
layer->resetAssignedResource();
layer->mOverlayInfo |= eUpdateExynosComposition;
@@ -745,7 +712,8 @@ int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
return ret;
}
layer->setExynosMidImage(dst_img);
- display->addExynosCompositionLayer(i);
+ float totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
+ display->addExynosCompositionLayer(i, totalUsedCapacity);
layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
remainNum--;
}
@@ -760,18 +728,20 @@ int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
layer->setSrcExynosImage(&src_img);
layer->setDstExynosImage(&dst_img);
layer->setExynosImage(src_img, dst_img);
- bool isAssignable = false;
+ bool isAssignableState = false;
if ((layer->mSupportedMPPFlag & m2mMPP->mLogicalType) != 0)
- isAssignable = m2mMPP->isAssignable(display, src_img, dst_img);
+ isAssignableState = isAssignable(m2mMPP, display, src_img, dst_img, layer);
bool canChange = (layer->mValidateCompositionType != HWC2_COMPOSITION_CLIENT) &&
- ((display->mDisplayControl.cursorSupport == false) ||
- (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
- (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignable;
-
- HDEBUGLOGD(eDebugResourceManager, "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, remainNum(%d)",
- i, layer->mValidateCompositionType,
- layer->mSupportedMPPFlag, isAssignable, canChange, remainNum);
+ ((display->mDisplayControl.cursorSupport == false) ||
+ (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
+ (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignableState;
+
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, "
+ "remainNum(%d)",
+ i, layer->mValidateCompositionType, layer->mSupportedMPPFlag,
+ isAssignableState, canChange, remainNum);
if (canChange) {
layer->resetAssignedResource();
layer->mOverlayInfo |= eUpdateExynosComposition;
@@ -782,7 +752,8 @@ int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
return ret;
}
layer->setExynosMidImage(dst_img);
- display->addExynosCompositionLayer(i);
+ float totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
+ display->addExynosCompositionLayer(i, totalUsedCapacity);
layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
remainNum--;
}
@@ -790,8 +761,10 @@ int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
break;
}
}
- HDEBUGLOGD(eDebugResourceManager, "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d-----",
- display->mExynosCompositionInfo.mFirstIndex, display->mExynosCompositionInfo.mLastIndex, remainNum);
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "Update ExynosComposition firstIndex: %d, lastIndex: %d, remainNum: %d-----",
+ display->mExynosCompositionInfo.mFirstIndex,
+ display->mExynosCompositionInfo.mLastIndex, remainNum);
}
/*
@@ -843,8 +816,8 @@ int32_t ExynosResourceManager::changeLayerFromClientToDevice(ExynosDisplay *disp
__func__, otfMPP->mName.string(), ret);
return ret;
}
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
- layer_index, otfMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", layer_index,
+ otfMPP->mName.string());
}
if (m2mMPP != NULL) {
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
@@ -854,13 +827,13 @@ int32_t ExynosResourceManager::changeLayerFromClientToDevice(ExynosDisplay *disp
return ret;
}
layer->setExynosMidImage(m2m_out_img);
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
- layer_index, m2mMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", layer_index,
+ m2mMPP->mName.string());
}
layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
display->mWindowNumUsed++;
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: mWindowNumUsed(%d)",
- layer_index, display->mWindowNumUsed);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: mWindowNumUsed(%d)", layer_index,
+ display->mWindowNumUsed);
return ret;
}
@@ -1032,23 +1005,31 @@ int32_t ExynosResourceManager::assignCompositionTarget(ExynosDisplay * display,
}
int64_t isSupported = 0;
- bool isAssignable = false;
+ bool isAssignableState = false;
+
+ otfMppReordering(display, mOtfMPPs, src_img, dst_img);
+
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
+ compositionInfo->setExynosImage(src_img, dst_img);
+ compositionInfo->setExynosMidImage(dst_img);
+ HDEBUGLOGD(eDebugTDM, "%s M2M target calculation start", __func__);
+ calculateHWResourceAmount(display, compositionInfo);
+
isSupported = mOtfMPPs[i]->isSupported(*display, src_img, dst_img);
if (isSupported == NO_ERROR)
- isAssignable = mOtfMPPs[i]->isAssignable(display, src_img, dst_img);
+ isAssignableState =
+ isAssignable(mOtfMPPs[i], display, src_img, dst_img, compositionInfo);
- HDEBUGLOGD(eDebugResourceManager, "\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
- mOtfMPPs[i]->mName.string(), -isSupported, isAssignable);
- if ((isSupported == NO_ERROR) && (isAssignable)) {
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
+ mOtfMPPs[i]->mName.string(), -isSupported, isAssignableState);
+ if ((isSupported == NO_ERROR) && (isAssignableState)) {
if ((ret = mOtfMPPs[i]->assignMPP(display, compositionInfo)) != NO_ERROR)
{
HWC_LOGE(display, "%s:: %s MPP assignMPP() error (%d)",
__func__, mOtfMPPs[i]->mName.string(), ret);
return ret;
}
- compositionInfo->setExynosImage(src_img, dst_img);
- compositionInfo->setExynosMidImage(dst_img);
compositionInfo->mOtfMPP = mOtfMPPs[i];
display->mWindowNumUsed++;
@@ -1083,7 +1064,7 @@ int32_t ExynosResourceManager::validateLayer(uint32_t index, ExynosDisplay *disp
return eDynamicRecomposition;
if ((layer->mLayerBuffer != NULL) &&
- (display->mDisplayId == getDisplayId(HWC_DISPLAY_PRIMARY, 0)) &&
+ (display->mType == HWC_DISPLAY_PRIMARY) &&
(mForceReallocState != DST_REALLOC_DONE)) {
ALOGI("Device type assign skipping by dst reallocation...... ");
return eReallocOnGoingForDDI;
@@ -1133,7 +1114,7 @@ int32_t ExynosResourceManager::validateLayer(uint32_t index, ExynosDisplay *disp
}
int32_t ExynosResourceManager::validateRCDLayer(const ExynosDisplay &display,
- const ExynosLayer &layer,
+ const ExynosLayer &layer, const uint32_t layerIndex,
const exynos_image &srcImg,
const exynos_image &dstImg) {
if (CC_UNLIKELY(srcImg.bufferHandle == NULL || srcImg.format != HAL_PIXEL_FORMAT_GOOGLE_R_8)) {
@@ -1154,6 +1135,11 @@ int32_t ExynosResourceManager::validateRCDLayer(const ExynosDisplay &display,
return eMPPUnsupported;
}
+ // only support RCD Layers on the top
+ if (layerIndex != display.mLayers.size() - 1) {
+ return eMPPUnsupported;
+ }
+
// b/215335109: IMG_SIZE must be equal or larger than display output
if (dstImg.x != 0 || dstImg.y != 0 || dstImg.w != display.mXres || dstImg.h != display.mYres) {
return eInvalidDispFrame;
@@ -1247,7 +1233,7 @@ void ExynosResourceManager::getCandidateScalingM2mMPPOutImages(
const float otfSrcWidth = float(srcWidth / m2mMppRatio);
const float scaleRatio_H = otfSrcWidth / float(dst_img.w);
- const float otfSrcHeight = float(srcWidth / m2mMppRatio);
+ const float otfSrcHeight = float(srcHeight / m2mMppRatio);
const float scaleRatio_V = otfSrcHeight / float(dst_img.h);
const float displayRatio_V = float(dst_img.h) / float(display->mYres);
const float resolution = otfSrcWidth * otfSrcHeight * display->getBtsRefreshRate() / 1000;
@@ -1298,7 +1284,7 @@ void ExynosResourceManager::getCandidateScalingM2mMPPOutImages(
dst_scale_img.h = uint32_t(ceilf(float(srcHeight) / float(m2mMppRatio)));
}
}
- HDEBUGLOGD(eDebugResourceManager,
+ HDEBUGLOGD(eDebugResourceAssigning,
"\tsrc[%d, %d, %d,%d], dst[%d, %d, %d,%d], mid[%d, %d, %d, %d]", src_img.x,
src_img.y, src_img.w, src_img.h, dst_img.x, dst_img.y, dst_img.w, dst_img.h,
dst_scale_img.x, dst_scale_img.y, dst_scale_img.w, dst_scale_img.h);
@@ -1479,26 +1465,32 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
HDEBUGLOGD(eDebugResourceManager, "\t[%d] layer: validateFlag(0x%8x), supportedMPPFlag(0x%8x)",
layer_index, validateFlag, layer->mSupportedMPPFlag);
- if (hwcCheckDebugMessages(eDebugResourceManager)) {
+ if (hwcCheckDebugMessages(eDebugResourceAssigning)) {
layer->printLayer();
}
if ((validateFlag == NO_ERROR) || (validateFlag == eInsufficientWindow) ||
(validateFlag == eDimLayer)) {
- bool isAssignable = false;
+ bool isAssignableFlag = false;
uint64_t isSupported = 0;
/* 1. Find available otfMPP */
if (validateFlag != eInsufficientWindow) {
+ otfMppReordering(display, mOtfMPPs, src_img, dst_img);
+
for (uint32_t j = 0; j < mOtfMPPs.size(); j++) {
if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) != 0)
- isAssignable = mOtfMPPs[j]->isAssignable(display, src_img, dst_img);
+ isAssignableFlag = isAssignable(mOtfMPPs[j], display, src_img, dst_img, layer);
+
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t check %s: flag (%d) supportedBit(%d), isAssignable(%d)",
+ mOtfMPPs[j]->mName.string(), layer->mSupportedMPPFlag,
+ (layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType),
+ isAssignableFlag);
- HDEBUGLOGD(eDebugResourceManager, "\t\t check %s: flag (%d) supportedBit(%d), isAssignable(%d)",
- mOtfMPPs[j]->mName.string(),layer->mSupportedMPPFlag,
- (layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType), isAssignable);
- if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) && (isAssignable)) {
+ if ((layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType) && (isAssignableFlag)) {
isSupported = mOtfMPPs[j]->isSupported(*display, src_img, dst_img);
- HDEBUGLOGD(eDebugResourceManager, "\t\t\t isSuported(%" PRIx64 ")", -isSupported);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t\t isSupported(%" PRIx64 ")",
+ -isSupported);
if (isSupported == NO_ERROR) {
*otfMPP = mOtfMPPs[j];
return HWC2_COMPOSITION_DEVICE;
@@ -1509,7 +1501,6 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
/* 2. Find available m2mMPP */
for (uint32_t j = 0; j < mM2mMPPs.size(); j++) {
-
if ((display->mUseDpu == true) &&
(mM2mMPPs[j]->mLogicalType == MPP_LOGICAL_G2D_COMBO))
continue;
@@ -1523,16 +1514,19 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
if ((validateFlag == eInsufficientWindow) &&
(mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_RGB) &&
(mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
- HDEBUGLOGD(eDebugResourceManager, "\t\tInsufficient window but exynosComposition is not assigned");
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\tInsufficient window but exynosComposition is not assigned");
continue;
}
bool isAssignableState = mM2mMPPs[j]->isAssignableState(display, src_img, dst_img);
- HDEBUGLOGD(eDebugResourceManager, "\t\t check %s: supportedBit(%d), isAssignableState(%d)",
- mM2mMPPs[j]->mName.string(),
- (layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType), isAssignableState);
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t check %s: supportedBit(%d), isAssignableState(%d)",
+ mM2mMPPs[j]->mName.string(),
+ (layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType), isAssignableState);
+ float totalUsedCapa = ExynosResourceManager::getResourceUsedCapa(*mM2mMPPs[j]);
if (isAssignableState) {
if ((mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_RGB) &&
(mM2mMPPs[j]->mLogicalType != MPP_LOGICAL_G2D_COMBO)) {
@@ -1546,9 +1540,10 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
HWC_LOGE(display, "Fail getCandidateM2mMPPOutImages (%d)", ret);
return ret;
}
- HDEBUGLOGD(eDebugResourceManager, "candidate M2mMPPOutImage num: %zu", image_lists.size());
+ HDEBUGLOGD(eDebugResourceAssigning, "candidate M2mMPPOutImage num: %zu",
+ image_lists.size());
for (auto &otf_src_img : image_lists) {
- dumpExynosImage(eDebugResourceManager, otf_src_img);
+ dumpExynosImage(eDebugResourceAssigning, otf_src_img);
exynos_image m2m_src_img = src_img;
/* transform is already handled by m2mMPP */
if (CC_UNLIKELY(otf_src_img.transform != 0 || otf_dst_img.transform != 0)) {
@@ -1566,24 +1561,43 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
if (otf_src_img.needColorTransform)
m2m_src_img.needColorTransform = false;
- if (((isSupported = mM2mMPPs[j]->isSupported(*display, m2m_src_img, otf_src_img)) != NO_ERROR) ||
- ((isAssignable = mM2mMPPs[j]->hasEnoughCapa(display, m2m_src_img, otf_src_img)) == false))
- {
- HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: supportedBit(0x%" PRIx64 "), hasEnoughCapa(%d)",
- mM2mMPPs[j]->mName.string(), -isSupported, isAssignable);
+ if (((isSupported = mM2mMPPs[j]->isSupported(*display, m2m_src_img,
+ otf_src_img)) != NO_ERROR) ||
+ ((isAssignableFlag =
+ mM2mMPPs[j]->hasEnoughCapa(display, m2m_src_img, otf_src_img,
+ totalUsedCapa)) == false)) {
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t\t check %s: supportedBit(0x%" PRIx64
+ "), hasEnoughCapa(%d)",
+ mM2mMPPs[j]->mName.string(), -isSupported, isAssignableFlag);
continue;
}
+ otfMppReordering(display, mOtfMPPs, otf_src_img, otf_dst_img);
+
/* 3. Find available OtfMPP for output of m2mMPP */
for (uint32_t k = 0; k < mOtfMPPs.size(); k++) {
isSupported = mOtfMPPs[k]->isSupported(*display, otf_src_img, otf_dst_img);
- isAssignable = false;
- if (isSupported == NO_ERROR)
- isAssignable = mOtfMPPs[k]->isAssignable(display, otf_src_img, otf_dst_img);
+ isAssignableFlag = false;
+ if (isSupported == NO_ERROR) {
+ /* to prevent HW resource execeeded */
+ ExynosCompositionInfo dpuSrcInfo;
+ dpuSrcInfo.mSrcImg = otf_src_img;
+ dpuSrcInfo.mDstImg = otf_dst_img;
+ HDEBUGLOGD(eDebugTDM,
+ "%s Composition target calculation start (candidates)",
+ __func__);
+ calculateHWResourceAmount(display, &dpuSrcInfo);
+
+ isAssignableFlag = isAssignable(mOtfMPPs[k], display, otf_src_img,
+ otf_dst_img, &dpuSrcInfo);
+ }
- HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
- mOtfMPPs[k]->mName.string(), -isSupported, isAssignable);
- if ((isSupported == NO_ERROR) && isAssignable) {
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t\t check %s: supportedBit(0x%" PRIx64
+ "), isAssignable(%d)",
+ mOtfMPPs[k]->mName.string(), -isSupported, isAssignableFlag);
+ if ((isSupported == NO_ERROR) && isAssignableFlag) {
*m2mMPP = mM2mMPPs[j];
*otfMPP = mOtfMPPs[k];
m2m_out_img = otf_src_img;
@@ -1593,12 +1607,16 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
}
} else {
if ((layer->mSupportedMPPFlag & mM2mMPPs[j]->mLogicalType) &&
- ((isAssignable = mM2mMPPs[j]->hasEnoughCapa(display, src_img, dst_img) == true))) {
+ ((isAssignableFlag = mM2mMPPs[j]->hasEnoughCapa(display, src_img, dst_img,
+ totalUsedCapa) == true))) {
*m2mMPP = mM2mMPPs[j];
return HWC2_COMPOSITION_EXYNOS;
} else {
- HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: layer's mSupportedMPPFlag(0x%8x), hasEnoughCapa(%d)",
- mM2mMPPs[j]->mName.string(), layer->mSupportedMPPFlag, isAssignable);
+ HDEBUGLOGD(eDebugResourceManager,
+ "\t\t\t check %s: layer's mSupportedMPPFlag(0x%8x), "
+ "hasEnoughCapa(%d)",
+ mM2mMPPs[j]->mName.string(), layer->mSupportedMPPFlag,
+ isAssignableFlag);
}
}
}
@@ -1614,8 +1632,8 @@ int32_t ExynosResourceManager::assignLayer(ExynosDisplay *display, ExynosLayer *
int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t priority)
{
- HDEBUGLOGD(eDebugResourceManager, "%s:: display(%d), priority(%d) +++++",
- __func__, display->mType, priority);
+ HDEBUGLOGD(eDebugResourceAssigning, "%s:: display(%d), priority(%d) +++++", __func__,
+ display->mType, priority);
int32_t ret = NO_ERROR;
bool needReAssign = false;
@@ -1642,7 +1660,7 @@ int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t pr
// TODO: call validate function for RCD layer
if (layer->mCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION &&
- validateRCDLayer(*display, *layer, src_img, dst_img) == NO_ERROR) {
+ validateRCDLayer(*display, *layer, i, src_img, dst_img) == NO_ERROR) {
layer->mValidateCompositionType = HWC2_COMPOSITION_DISPLAY_DECORATION;
continue;
}
@@ -1656,8 +1674,8 @@ int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t pr
__func__, otfMPP->mName.string(), ret);
return ret;
}
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
- i, otfMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", i,
+ otfMPP->mName.string());
}
if (m2mMPP != NULL) {
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
@@ -1667,14 +1685,15 @@ int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t pr
return ret;
}
layer->setExynosMidImage(m2m_out_img);
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
- i, m2mMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", i,
+ m2mMPP->mName.string());
}
layer->mValidateCompositionType = compositionType;
display->mWindowNumUsed++;
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: mWindowNumUsed(%d)",
- i, display->mWindowNumUsed);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: mWindowNumUsed(%d)", i,
+ display->mWindowNumUsed);
} else if (compositionType == HWC2_COMPOSITION_EXYNOS) {
+ float totalUsedCapacity = 0;
if (m2mMPP != NULL) {
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
{
@@ -1682,15 +1701,17 @@ int32_t ExynosResourceManager::assignLayers(ExynosDisplay * display, uint32_t pr
__func__, m2mMPP->mName.string(), ret);
return ret;
}
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: %s MPP is assigned",
- i, m2mMPP->mName.string());
+ totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: %s MPP is assigned", i,
+ m2mMPP->mName.string());
}
layer->mValidateCompositionType = compositionType;
- HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] layer: exynosComposition", i);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\t[%d] layer: exynosComposition", i);
/* G2D composition */
- if (((ret = display->addExynosCompositionLayer(i)) == EXYNOS_ERROR_CHANGED) ||
- (ret < 0))
+ if (((ret = display->addExynosCompositionLayer(i, totalUsedCapacity)) ==
+ EXYNOS_ERROR_CHANGED) ||
+ (ret < 0))
return ret;
else {
/*
@@ -1761,7 +1782,8 @@ int32_t ExynosResourceManager::assignWindow(ExynosDisplay *display)
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
ExynosLayer *layer = display->mLayers[i];
- HDEBUGLOGD(eDebugResourceManager, "\t[%d] layer type: %d", i, layer->mValidateCompositionType);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t[%d] layer type: %d", i,
+ layer->mValidateCompositionType);
if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) {
layer->mWindowIndex = windowIndex;
@@ -1811,10 +1833,10 @@ int32_t ExynosResourceManager::assignWindow(ExynosDisplay *display)
int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
{
int64_t ret = 0;
- HDEBUGLOGD(eDebugResourceManager, "%s++++++++++", __func__);
+ HDEBUGLOGD(eDebugResourceAssigning, "%s++++++++++", __func__);
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
ExynosLayer *layer = display->mLayers[i];
- HDEBUGLOGD(eDebugResourceManager, "[%d] layer ", i);
+ HDEBUGLOGD(eDebugResourceAssigning, "[%d] layer ", i);
if (layer->mGeometryChanged == 0)
continue;
@@ -1827,10 +1849,10 @@ int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
layer->setDstExynosImage(&dst_img_yuv);
dst_img.format = DEFAULT_MPP_DST_FORMAT;
dst_img_yuv.format = DEFAULT_MPP_DST_YUV_FORMAT;
- HDEBUGLOGD(eDebugResourceManager, "\tsrc_img");
- dumpExynosImage(eDebugResourceManager, src_img);
- HDEBUGLOGD(eDebugResourceManager, "\tdst_img");
- dumpExynosImage(eDebugResourceManager, dst_img);
+ HDEBUGLOGD(eDebugResourceAssigning, "\tsrc_img");
+ dumpExynosImage(eDebugResourceAssigning, src_img);
+ HDEBUGLOGD(eDebugResourceAssigning, "\tdst_img");
+ dumpExynosImage(eDebugResourceAssigning, dst_img);
/* Initialize flags */
layer->mSupportedMPPFlag = 0;
@@ -1840,16 +1862,18 @@ int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
for (uint32_t j = 0; j < mOtfMPPs.size(); j++) {
if ((ret = mOtfMPPs[j]->isSupported(*display, src_img, dst_img)) == NO_ERROR) {
layer->mSupportedMPPFlag |= mOtfMPPs[j]->mLogicalType;
- HDEBUGLOGD(eDebugResourceManager, "\t%s: supported", mOtfMPPs[j]->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported", mOtfMPPs[j]->mName.string());
} else {
if (((-ret) == eMPPUnsupportedFormat) &&
((ret = mOtfMPPs[j]->isSupported(*display, src_img, dst_img_yuv)) == NO_ERROR)) {
layer->mSupportedMPPFlag |= mOtfMPPs[j]->mLogicalType;
- HDEBUGLOGD(eDebugResourceManager, "\t%s: supported with yuv dst", mOtfMPPs[j]->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported with yuv dst",
+ mOtfMPPs[j]->mName.string());
}
}
if (ret < 0) {
- HDEBUGLOGD(eDebugResourceManager, "\t%s: unsupported flag(0x%" PRIx64 ")", mOtfMPPs[j]->mName.string(), -ret);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s: unsupported flag(0x%" PRIx64 ")",
+ mOtfMPPs[j]->mName.string(), -ret);
uint64_t checkFlag = 0x0;
if (layer->mCheckMPPFlag.find(mOtfMPPs[j]->mLogicalType) !=
layer->mCheckMPPFlag.end()) {
@@ -1864,16 +1888,18 @@ int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
for (uint32_t j = 0; j < mM2mMPPs.size(); j++) {
if ((ret = mM2mMPPs[j]->isSupported(*display, src_img, dst_img)) == NO_ERROR) {
layer->mSupportedMPPFlag |= mM2mMPPs[j]->mLogicalType;
- HDEBUGLOGD(eDebugResourceManager, "\t%s: supported", mM2mMPPs[j]->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported", mM2mMPPs[j]->mName.string());
} else {
if (((-ret) == eMPPUnsupportedFormat) &&
((ret = mM2mMPPs[j]->isSupported(*display, src_img, dst_img_yuv)) == NO_ERROR)) {
layer->mSupportedMPPFlag |= mM2mMPPs[j]->mLogicalType;
- HDEBUGLOGD(eDebugResourceManager, "\t%s: supported with yuv dst", mM2mMPPs[j]->mName.string());
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s: supported with yuv dst",
+ mM2mMPPs[j]->mName.string());
}
}
if (ret < 0) {
- HDEBUGLOGD(eDebugResourceManager, "\t%s: unsupported flag(0x%" PRIx64 ")", mM2mMPPs[j]->mName.string(), -ret);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s: unsupported flag(0x%" PRIx64 ")",
+ mM2mMPPs[j]->mName.string(), -ret);
uint64_t checkFlag = 0x0;
if (layer->mCheckMPPFlag.find(mM2mMPPs[j]->mLogicalType) !=
layer->mCheckMPPFlag.end()) {
@@ -1883,9 +1909,10 @@ int32_t ExynosResourceManager::updateSupportedMPPFlag(ExynosDisplay * display)
layer->mCheckMPPFlag[mM2mMPPs[j]->mLogicalType] = checkFlag;
}
}
- HDEBUGLOGD(eDebugResourceManager, "[%d] layer mSupportedMPPFlag(0x%8x)", i, layer->mSupportedMPPFlag);
+ HDEBUGLOGD(eDebugResourceAssigning, "[%d] layer mSupportedMPPFlag(0x%8x)", i,
+ layer->mSupportedMPPFlag);
}
- HDEBUGLOGD(eDebugResourceManager, "%s-------------", __func__);
+ HDEBUGLOGD(eDebugResourceAssigning, "%s-------------", __func__);
return NO_ERROR;
}
@@ -1927,7 +1954,9 @@ int32_t ExynosResourceManager::preAssignResources()
}
if (mOtfMPPs[i]->mPreAssignDisplayList[displayMode] != 0) {
- HDEBUGLOGD(eDebugResourceManager, "\t%s check, dispMode(%d), 0x%8x", mOtfMPPs[i]->mName.string(), displayMode, mOtfMPPs[i]->mPreAssignDisplayList[displayMode]);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s check, dispMode(%d), 0x%8x",
+ mOtfMPPs[i]->mName.string(), displayMode,
+ mOtfMPPs[i]->mPreAssignDisplayList[displayMode]);
ExynosDisplay *display = NULL;
for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
@@ -1935,14 +1964,19 @@ int32_t ExynosResourceManager::preAssignResources()
if (display == nullptr)
continue;
int checkBit = mOtfMPPs[i]->mPreAssignDisplayList[displayMode] & display->getDisplayPreAssignBit();
- HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), checkBit(%d)", j, checkBit);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\tdisplay index(%zu), checkBit(%d)", j,
+ checkBit);
if (checkBit) {
- HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), displayId(%d), display(%p)", j, display->mDisplayId, display);
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\tdisplay index(%zu), displayId(%d), display(%p)", j,
+ display->mDisplayId, display);
if (display->mDisplayControl.forceReserveMPP ||
(display->mPlugState &&
((display->mType != HWC_DISPLAY_PRIMARY) ||
- (display->mPowerModeState != HWC2_POWER_MODE_OFF)))) {
- HDEBUGLOGD(eDebugResourceManager, "\t\treserve to display %d", display->mDisplayId);
+ (display->mPowerModeState.has_value() &&
+ (display->mPowerModeState.value() != HWC2_POWER_MODE_OFF))))) {
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve to display %d",
+ display->mDisplayId);
mOtfMPPs[i]->reserveMPP(display->mDisplayId);
break;
}
@@ -1962,21 +1996,26 @@ int32_t ExynosResourceManager::preAssignResources()
mM2mMPPs[i]->reserveMPP();
continue;
}
- HDEBUGLOGD(eDebugResourceManager, "\t%s check, 0x%8x", mM2mMPPs[i]->mName.string(), mM2mMPPs[i]->mPreAssignDisplayList[displayMode]);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t%s check, 0x%8x", mM2mMPPs[i]->mName.string(),
+ mM2mMPPs[i]->mPreAssignDisplayList[displayMode]);
if (mM2mMPPs[i]->mPreAssignDisplayList[displayMode] != 0) {
ExynosDisplay *display = NULL;
for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
display = mDevice->mDisplays[j];
int checkBit = mM2mMPPs[i]->mPreAssignDisplayList[displayMode] & display->getDisplayPreAssignBit();
- HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), checkBit(%d)", j, checkBit);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\tdisplay index(%zu), checkBit(%d)", j,
+ checkBit);
if (checkBit) {
- HDEBUGLOGD(eDebugResourceManager, "\t\tdisplay index(%zu), displayId(%d), display(%p)", j, display->mDisplayId, display);
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\tdisplay index(%zu), displayId(%d), display(%p)", j,
+ display->mDisplayId, display);
if ((display != NULL) && (display->mPlugState == true)) {
- HDEBUGLOGD(eDebugResourceManager, "\t\treserve to display %d", display->mDisplayId);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve to display %d",
+ display->mDisplayId);
mM2mMPPs[i]->reserveMPP(display->mDisplayId);
break;
} else {
- HDEBUGLOGD(eDebugResourceManager, "\t\treserve without display");
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve without display");
mM2mMPPs[i]->reserveMPP();
}
}
@@ -2001,18 +2040,22 @@ int32_t ExynosResourceManager::preAssignResources()
return NO_ERROR;
}
-void ExynosResourceManager::preAssignWindows()
-{
- ExynosDisplay *display = NULL;
- ExynosPrimaryDisplayModule *primaryDisplay =
- (ExynosPrimaryDisplayModule *)mDevice->getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+void ExynosResourceManager::preAssignWindows(ExynosDisplay *display) {
+ ExynosPrimaryDisplayModule *primaryDisplay = NULL;
+
+ if (display->mType == HWC_DISPLAY_PRIMARY) {
+ primaryDisplay = (ExynosPrimaryDisplayModule *)display;
+ } else {
+ primaryDisplay = (ExynosPrimaryDisplayModule *)mDevice->getDisplay(
+ getDisplayId(HWC_DISPLAY_PRIMARY, 0));
+ }
+
primaryDisplay->usePreDefinedWindow(false);
for (size_t i = 1; i < mDevice->mDisplays.size(); i++) {
- display = mDevice->mDisplays[i];
- if ((display == NULL) || (display->mType != HWC_DISPLAY_EXTERNAL))
- continue;
- if (display->mPlugState == true) {
+ ExynosDisplay *disp = mDevice->mDisplays[i];
+ if ((disp == NULL) || (display->mType != HWC_DISPLAY_EXTERNAL)) continue;
+ if (disp->mPlugState == true) {
primaryDisplay->usePreDefinedWindow(true);
}
}
@@ -2231,9 +2274,8 @@ float ExynosResourceManager::getResourceUsedCapa(ExynosMPP &mpp)
if (mpp.mCapacity < 0)
return usedCapa;
- HDEBUGLOGD(eDebugResourceManager, "%s:: [%s][%d] mpp[%d, %d]",
- __func__, mpp.mName.string(), mpp.mLogicalIndex,
- mpp.mPhysicalType, mpp.mPhysicalIndex);
+ HDEBUGLOGD(eDebugResourceAssigning, "%s:: [%s][%d] mpp[%d, %d]", __func__, mpp.mName.string(),
+ mpp.mLogicalIndex, mpp.mPhysicalType, mpp.mPhysicalIndex);
if (mpp.mMPPType == MPP_TYPE_OTF) {
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
@@ -2251,8 +2293,8 @@ float ExynosResourceManager::getResourceUsedCapa(ExynosMPP &mpp)
}
}
- HDEBUGLOGD(eDebugResourceManager, "\t[%s][%d] mpp usedCapa: %f",
- mpp.mName.string(), mpp.mLogicalIndex, usedCapa);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t[%s][%d] mpp usedCapa: %f", mpp.mName.string(),
+ mpp.mLogicalIndex, usedCapa);
return usedCapa;
}
@@ -2308,7 +2350,7 @@ void ExynosResourceManager::setScaleDownRatio(uint32_t physicalType,
}
}
-int32_t ExynosResourceManager::prepareResources()
+int32_t ExynosResourceManager::prepareResources()
{
int ret = NO_ERROR;
HDEBUGLOGD(eDebugResourceManager, "This is first validate");
@@ -2323,7 +2365,9 @@ int32_t ExynosResourceManager::prepareResources()
return ret;
}
- return ret;
+ setDisplaysTDMInfo();
+
+ return ret;
}
int32_t ExynosResourceManager::finishAssignResourceWork()
@@ -2353,7 +2397,7 @@ int32_t ExynosResourceManager::initResourcesState(ExynosDisplay *display)
__func__, ret);
return ret;
}
- preAssignWindows();
+ preAssignWindows(display);
}
@@ -2483,8 +2527,8 @@ void ExynosResourceManager::makeAcrylRestrictions(mpp_phycal_type_t type){
mpp_phycal_type_t ExynosResourceManager::getPhysicalType(int ch) const {
for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
- if(IDMA_CHANNEL_MAP[i].channel == ch)
- return IDMA_CHANNEL_MAP[i].type;
+ if(idma_channel_map[i].channel == ch)
+ return idma_channel_map[i].type;
}
return MPP_P_TYPE_MAX;
@@ -2495,8 +2539,8 @@ ExynosMPP* ExynosResourceManager::getOtfMPPWithChannel(int ch)
ExynosMPP *otfMPP = NULL;
for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
- if(IDMA_CHANNEL_MAP[i].channel == ch) {
- otfMPP = getExynosMPP(IDMA_CHANNEL_MAP[i].type, IDMA_CHANNEL_MAP[i].index);
+ if(idma_channel_map[i].channel == ch) {
+ otfMPP = getExynosMPP(idma_channel_map[i].type, idma_channel_map[i].index);
break;
}
}
@@ -2624,3 +2668,84 @@ void ExynosResourceManager::setM2MCapa(uint32_t physicalType, uint32_t capa)
mM2mMPPs[i]->mCapacity = capa;
}
}
+
+bool ExynosResourceManager::isAssignable(ExynosMPP *candidateMPP, ExynosDisplay *display,
+ struct exynos_image &src, struct exynos_image &dst,
+ ExynosMPPSource *mppSrc)
+{
+ bool ret = true;
+
+ float totalUsedCapacity = getResourceUsedCapa(*candidateMPP);
+ ret = candidateMPP->isAssignable(display, src, dst, totalUsedCapacity);
+
+ if ((ret) && (mppSrc != nullptr)) {
+ if ((candidateMPP->mMPPType == MPP_TYPE_OTF) &&
+ (!isHWResourceAvailable(display, candidateMPP, mppSrc))) {
+ if (mppSrc->mSourceType == MPP_SOURCE_LAYER) {
+ ExynosLayer *layer = (ExynosLayer *)mppSrc;
+ layer->mCheckMPPFlag[candidateMPP->mLogicalType] = eMPPExeedHWResource;
+ }
+ ret = false;
+ }
+ }
+
+ return ret;
+}
+
+void ExynosResourceManager::updateSupportWCG()
+{
+ for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
+ if (mOtfMPPs[i] == NULL) continue;
+ if (mOtfMPPs[i]->mAttr & (MPP_ATTR_WCG | MPP_ATTR_HDR10)) mDeviceSupportWCG = true;
+ }
+ for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
+ if (mM2mMPPs[i] == NULL) continue;
+ if (mM2mMPPs[i]->mAttr & (MPP_ATTR_WCG | MPP_ATTR_HDR10)) mDeviceSupportWCG = true;
+ }
+}
+
+bool ExynosResourceManager::needHdrProcessing(ExynosDisplay *display, exynos_image &srcImg,
+ exynos_image &dstImg)
+{
+ if (!deviceSupportWCG()) return false;
+
+ return true;
+}
+
+uint32_t ExynosResourceManager::needHWResource(ExynosDisplay *display, exynos_image &srcImg,
+ exynos_image &dstImg, tdm_attr_t attr)
+{
+ uint32_t ret = 0;
+
+ switch (attr) {
+ case TDM_ATTR_SBWC:
+ ret = (isFormatSBWC(srcImg.format)) ? 1 : 0;
+ break;
+ case TDM_ATTR_AFBC:
+ ret = (srcImg.compressed) ? 1 : 0;
+ break;
+ case TDM_ATTR_ITP:
+ ret = (isFormatYUV(srcImg.format)) ? 1 : 0;
+ break;
+ case TDM_ATTR_WCG:
+ ret = (needHdrProcessing(display, srcImg, dstImg)) ? 1 : 0;
+ HDEBUGLOGD(eDebugTDM, "needHdrProcessing : %d", ret);
+ break;
+ case TDM_ATTR_ROT_90:
+ ret = ((srcImg.transform & HAL_TRANSFORM_ROT_90) == 0) ? 0 : 1;
+ break;
+ case TDM_ATTR_SCALE: {
+ bool isPerpendicular = !!(srcImg.transform & HAL_TRANSFORM_ROT_90);
+ if (isPerpendicular) {
+ ret = ((srcImg.w != dstImg.h) || (srcImg.h != dstImg.w)) ? 1 : 0;
+ } else {
+ ret = ((srcImg.w != dstImg.w) || (srcImg.h != dstImg.h)) ? 1 : 0;
+ }
+ } break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
diff --git a/libhwc2.1/libresource/ExynosResourceManager.h b/libhwc2.1/libresource/ExynosResourceManager.h
index 11b24f6..e996554 100644
--- a/libhwc2.1/libresource/ExynosResourceManager.h
+++ b/libhwc2.1/libresource/ExynosResourceManager.h
@@ -38,18 +38,17 @@ class ExynosMPP;
#define MAX_OVERLAY_LAYER_NUM 20
-#ifndef USE_MODULE_SW_FEATURE
const std::map<mpp_phycal_type_t, uint64_t> sw_feature_table =
{
{MPP_DPP_G, MPP_ATTR_DIM},
{MPP_DPP_GF, MPP_ATTR_DIM},
+ {MPP_DPP_GFS, MPP_ATTR_DIM},
{MPP_DPP_VG, MPP_ATTR_DIM},
{MPP_DPP_VGS, MPP_ATTR_DIM},
{MPP_DPP_VGF, MPP_ATTR_DIM},
{MPP_DPP_VGFS, MPP_ATTR_DIM},
{MPP_DPP_VGRFS, MPP_ATTR_DIM},
};
-#endif
#ifndef USE_MODULE_DPU_ATTR_MAP
const dpu_attr_map_t dpu_attr_map_table [] =
@@ -133,12 +132,18 @@ class ExynosResourceManager {
int32_t updateSupportedMPPFlag(ExynosDisplay * display);
int32_t resetResources();
int32_t preAssignResources();
- void preAssignWindows();
+ void preAssignWindows(ExynosDisplay *display);
int32_t preProcessLayer(ExynosDisplay *display);
int32_t resetAssignedResources(ExynosDisplay *display, bool forceReset = false);
virtual int32_t assignCompositionTarget(ExynosDisplay *display, uint32_t targetType);
int32_t validateLayer(uint32_t index, ExynosDisplay *display, ExynosLayer *layer);
int32_t assignLayers(ExynosDisplay *display, uint32_t priority);
+ virtual int32_t otfMppReordering(ExynosDisplay *__unused display,
+ ExynosMPPVector __unused &otfMPPs,
+ struct exynos_image __unused &src,
+ struct exynos_image __unused &dst) {
+ return 0;
+ }
virtual int32_t assignLayer(ExynosDisplay *display, ExynosLayer *layer, uint32_t layer_index,
exynos_image &m2m_out_img, ExynosMPP **m2mMPP, ExynosMPP **otfMPP, uint32_t &overlayInfo);
virtual int32_t assignWindow(ExynosDisplay *display);
@@ -178,6 +183,8 @@ class ExynosResourceManager {
void dump(String8 &result) const;
void setM2MCapa(uint32_t physicalType, uint32_t capa);
+ bool isAssignable(ExynosMPP *candidateMPP, ExynosDisplay *display, struct exynos_image &src,
+ struct exynos_image &dst, ExynosMPPSource *mppSrc);
private:
int32_t changeLayerFromClientToDevice(ExynosDisplay *display, ExynosLayer *layer,
@@ -195,11 +202,47 @@ class ExynosResourceManager {
exynos_image getAlignedImage(exynos_image image, const ExynosMPP *m2mMpp,
const ExynosMPP *otfMpp) const;
int32_t validateRCDLayer(const ExynosDisplay &display, const ExynosLayer &layer,
- const exynos_image &srcImg, const exynos_image &dstImg);
+ const uint32_t layerIndex, const exynos_image &srcImg,
+ const exynos_image &dstImg);
static ExynosMPPVector mOtfMPPs;
static ExynosMPPVector mM2mMPPs;
uint32_t mResourceReserved; /* Set MPP logical type for bit operation */
float mMinimumSdrDimRatio;
+
+ android::Vector<ExynosDisplay *> mDisplays;
+ std::map<uint32_t, ExynosDisplay *> mDisplayMap;
+
+ protected:
+ bool mDeviceSupportWCG = false;
+
+ public:
+ void initDisplays(android::Vector<ExynosDisplay *> displays,
+ std::map<uint32_t, ExynosDisplay *> displayMap) {
+ mDisplays = displays;
+ mDisplayMap = displayMap;
+ }
+ ExynosDisplay *getDisplay(uint32_t displayId) { return mDisplayMap[displayId]; }
+
+ virtual void updateSupportWCG();
+ virtual bool deviceSupportWCG() { return mDeviceSupportWCG; }
+
+ /* return 1 if it's needed */
+ bool needHdrProcessing(ExynosDisplay *display, exynos_image &srcImg, exynos_image &dstImg);
+ uint32_t needHWResource(ExynosDisplay *display, exynos_image &srcImg, exynos_image &dstImg,
+ tdm_attr_t attr);
+
+ /* TDM (Time-Division Multiplexing) based Resource Management */
+ virtual bool isHWResourceAvailable(ExynosDisplay __unused *display,
+ ExynosMPP __unused *currentMPP,
+ ExynosMPPSource __unused *mppSrc) {
+ return true;
+ }
+ virtual uint32_t setDisplaysTDMInfo() { return 0; }
+ virtual uint32_t initDisplaysTDMInfo() { return 0; }
+ virtual uint32_t calculateHWResourceAmount(ExynosDisplay __unused *display,
+ ExynosMPPSource __unused *mppSrc) {
+ return 0;
+ }
};
#endif //_EXYNOSRESOURCEMANAGER_H
diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp
index d6ce85f..1f16ec8 100644
--- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp
+++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.cpp
@@ -15,7 +15,7 @@
*/
#undef LOG_TAG
-#define LOG_TAG "virtualdisplay"
+#define LOG_TAG "hwc-virt-display"
#include "ExynosVirtualDisplay.h"
#include "../libdevice/ExynosDevice.h"
#include "../libdevice/ExynosLayer.h"
@@ -28,13 +28,10 @@ using vendor::graphics::VendorGraphicBufferUsage;
extern struct exynos_hwc_control exynosHWCControl;
-ExynosVirtualDisplay::ExynosVirtualDisplay(uint32_t index, ExynosDevice *device)
- : ExynosDisplay(index, device)
-{
+ExynosVirtualDisplay::ExynosVirtualDisplay(uint32_t index, ExynosDevice* device,
+ const std::string& displayName)
+ : ExynosDisplay(HWC_DISPLAY_VIRTUAL, index, device, displayName) {
/* Initialization */
- mType = HWC_DISPLAY_VIRTUAL;
- mIndex = index;
- mDisplayId = getDisplayId(mType, mIndex);
mDisplayControl.earlyStartMPP = false;
diff --git a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h
index 9e5daa8..786ff50 100644
--- a/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h
+++ b/libhwc2.1/libvirtualdisplay/ExynosVirtualDisplay.h
@@ -44,7 +44,7 @@ public:
COMPOSITION_MIXED = COMPOSITION_GLES | COMPOSITION_HWC
};
- ExynosVirtualDisplay(uint32_t index, ExynosDevice *device);
+ ExynosVirtualDisplay(uint32_t index, ExynosDevice* device, const std::string& displayName);
~ExynosVirtualDisplay();
void createVirtualDisplay(uint32_t width, uint32_t height, int32_t* format);
diff --git a/libhwc2.1/pixel-display-default.xml b/libhwc2.1/pixel-display-default.xml
index fc10d6a..7f2e4ba 100644
--- a/libhwc2.1/pixel-display-default.xml
+++ b/libhwc2.1/pixel-display-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>com.google.hardware.pixel.display</name>
- <version>6</version>
+ <version>8</version>
<fqname>IDisplay/default</fqname>
</hal>
</manifest>
diff --git a/libhwc2.1/pixel-display-secondary.xml b/libhwc2.1/pixel-display-secondary.xml
new file mode 100644
index 0000000..ff313be
--- /dev/null
+++ b/libhwc2.1/pixel-display-secondary.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>com.google.hardware.pixel.display</name>
+ <version>8</version>
+ <fqname>IDisplay/secondary</fqname>
+ </hal>
+</manifest>
diff --git a/libhwc2.1/pixel-display.cpp b/libhwc2.1/pixel-display.cpp
index 629a137..366945a 100644
--- a/libhwc2.1/pixel-display.cpp
+++ b/libhwc2.1/pixel-display.cpp
@@ -24,19 +24,20 @@
#include <utils/Errors.h>
#include "ExynosDisplay.h"
+#include "ExynosPrimaryDisplay.h"
extern int32_t load_png_image(const char *filepath, buffer_handle_t buffer);
using ::aidl::com::google::hardware::pixel::display::Display;
-void PixelDisplayInit(ExynosDevice *device) {
+void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str) {
ABinderProcess_setThreadPoolMaxThreadCount(0);
- std::shared_ptr<Display> display = ndk::SharedRefBase::make<Display>(device);
- LOG(INFO) << "pixel display service start...";
- const std::string instance = std::string() + Display::descriptor + "/default";
+ std::shared_ptr<Display> display = ndk::SharedRefBase::make<Display>(exynos_display);
+ const std::string instance = std::string() + Display::descriptor + "/" + std::string(instance_str).c_str();
binder_status_t status =
AServiceManager_addService(display->asBinder().get(), instance.c_str());
+ LOG(INFO) << instance.c_str() << " service start...";
CHECK(status == STATUS_OK);
ABinderProcess_startThreadPool();
@@ -77,8 +78,8 @@ ndk::ScopedAStatus Display::getHbmState(HbmState *_aidl_return) {
}
ndk::ScopedAStatus Display::isLbeSupported(bool *_aidl_return) {
- if (mDevice) {
- *_aidl_return = mDevice->isLbeSupported();
+ if (mDisplay) {
+ *_aidl_return = mDisplay->isLbeSupported();
return ndk::ScopedAStatus::ok();
}
*_aidl_return = false;
@@ -86,40 +87,40 @@ ndk::ScopedAStatus Display::isLbeSupported(bool *_aidl_return) {
}
ndk::ScopedAStatus Display::setLbeState(LbeState state) {
- if (mDevice) {
- mDevice->setLbeState(state);
+ if (mDisplay) {
+ mDisplay->setLbeState(state);
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus Display::setLbeAmbientLight(int ambientLux) {
- if (mDevice) {
- mDevice->setLbeAmbientLight(ambientLux);
+ if (mDisplay) {
+ mDisplay->setLbeAmbientLight(ambientLux);
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus Display::getLbeState(LbeState *_aidl_return) {
- if (mDevice) {
- *_aidl_return = mDevice->getLbeState();
+ if (mDisplay) {
+ *_aidl_return = mDisplay->getLbeState();
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus Display::isLhbmSupported(bool *_aidl_return) {
- if (mDevice) {
- *_aidl_return = mDevice->isLhbmSupported();
+ if (mDisplay) {
+ *_aidl_return = mDisplay->isLhbmSupported();
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus Display::setLhbmState(bool enabled) {
- if (mDevice && mDevice->isLhbmSupported()) {
- int32_t ret = mDevice->setLhbmState(enabled);
+ if (mDisplay && mDisplay->isLhbmSupported()) {
+ int32_t ret = mDisplay->setLhbmState(enabled);
if (!ret)
return ndk::ScopedAStatus::ok();
else if (ret == TIMED_OUT)
@@ -129,8 +130,32 @@ ndk::ScopedAStatus Display::setLhbmState(bool enabled) {
}
ndk::ScopedAStatus Display::getLhbmState(bool *_aidl_return) {
- if (mDevice && mDevice->isLhbmSupported()) {
- *_aidl_return = mDevice->getLhbmState();
+ if (mDisplay && mDisplay->isLhbmSupported()) {
+ *_aidl_return = mDisplay->getLhbmState();
+ return ndk::ScopedAStatus::ok();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Display::setPeakRefreshRate(int rate) {
+ if (mDisplay && mDisplay->mOperationRateManager) {
+ mDisplay->mOperationRateManager->onPeakRefreshRate(rate);
+ return ndk::ScopedAStatus::ok();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Display::setLowPowerMode(bool enabled) {
+ if (mDisplay && mDisplay->mOperationRateManager) {
+ mDisplay->mOperationRateManager->onLowPowerMode(enabled);
+ return ndk::ScopedAStatus::ok();
+ }
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Display::isOperationRateSupported(bool *_aidl_return) {
+ if (mDisplay) {
+ *_aidl_return = mDisplay->isOperationRateSupported();
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -139,7 +164,7 @@ ndk::ScopedAStatus Display::getLhbmState(bool *_aidl_return) {
ndk::ScopedAStatus Display::setCompensationImageHandle(const NativeHandle &native_handle,
const std::string &imageName,
int *_aidl_return) {
- if (mDevice && mDevice->isColorCalibratedByDevice()) {
+ if (mDisplay && mDisplay->isColorCalibratedByDevice()) {
*_aidl_return = readCompensationImage(native_handle, imageName);
} else {
*_aidl_return = -1;
@@ -148,35 +173,153 @@ ndk::ScopedAStatus Display::setCompensationImageHandle(const NativeHandle &nativ
}
ndk::ScopedAStatus Display::setMinIdleRefreshRate(int fps, int *_aidl_return) {
- if (mDevice) {
- *_aidl_return = mDevice->setMinIdleRefreshRate(fps);
+ if (mDisplay) {
+ *_aidl_return = mDisplay->setMinIdleRefreshRate(fps);
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
ndk::ScopedAStatus Display::setRefreshRateThrottle(int delayMs, int *_aidl_return) {
- if (mDevice) {
- *_aidl_return = mDevice->setRefreshRateThrottle(delayMs);
+ if (mDisplay) {
+ if (delayMs < 0) {
+ *_aidl_return = BAD_VALUE;
+ ALOGW("%s fail: delayMs(%d) is less than 0", __func__, delayMs);
+ return ndk::ScopedAStatus::ok();
+ }
+
+ *_aidl_return =
+ mDisplay->setRefreshRateThrottleNanos(std::chrono::duration_cast<
+ std::chrono::nanoseconds>(
+ std::chrono::milliseconds(delayMs))
+ .count(),
+ VrrThrottleRequester::PIXEL_DISP);
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+bool Display::runMediator(const RoiRect &roi, const Weight &weight, const HistogramPos &pos,
+ std::vector<char16_t> *histogrambuffer) {
+ bool isConfigChanged;
+ histogram::HistogramMediator::HistogramConfig pendingConfig(roi, weight, pos);
+
+ {
+ std::unique_lock<std::mutex> lk(mMediator.mConfigMutex);
+ isConfigChanged = mMediator.mConfig != pendingConfig;
+
+ if (isConfigChanged &&
+ mMediator.setRoiWeightThreshold(roi, weight, pos) != HistogramErrorCode::NONE) {
+ ALOGE("histogram error, SET_ROI_WEIGHT_THRESHOLD ERROR\n");
+ return false;
+ }
+
+ mMediator.mConfig = pendingConfig;
+ }
+
+ if (!mMediator.histRequested() &&
+ mMediator.requestHist() == HistogramErrorCode::ENABLE_HIST_ERROR) {
+ ALOGE("histogram error, ENABLE_HIST ERROR\n");
+ }
+
+ /*
+ * DPU driver maintains always-on histogram engine state with up to date histogram data.
+ * Therefore we don't have explicitly to trigger onRefresh in case histogram configuration
+ * does not change.
+ */
+ if (isConfigChanged) {
+ mDisplay->mDevice->onRefresh(mDisplay->mDisplayId);
+ }
+
+ if (mMediator.collectRoiLuma(histogrambuffer) != HistogramErrorCode::NONE) {
+ ALOGE("histogram error, COLLECT_ROI_LUMA ERROR\n");
+ return false;
+ }
+ return true;
+}
+
ndk::ScopedAStatus Display::histogramSample(const RoiRect &roi, const Weight &weight,
HistogramPos pos, Priority pri,
std::vector<char16_t> *histogrambuffer,
HistogramErrorCode *_aidl_return) {
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ if (!mDisplay) {
+ ALOGI("mDisplay is NULL \n");
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ if (histogrambuffer == nullptr) {
+ ALOGE("histogrambuffer is null");
+ *_aidl_return = HistogramErrorCode::BAD_HIST_DATA;
+ return ndk::ScopedAStatus::ok();
+ }
+ if (mMediator.isDisplayPowerOff() == true) {
+ *_aidl_return = HistogramErrorCode::DISPLAY_POWEROFF; // panel is off
+ return ndk::ScopedAStatus::ok();
+ }
+ if (mMediator.isSecureContentPresenting() == true) {
+ *_aidl_return = HistogramErrorCode::DRM_PLAYING; // panel is playing DRM content
+ return ndk::ScopedAStatus::ok();
+ }
+ if ((roi.left < 0) || (roi.top < 0) || ((roi.right - roi.left) <= 0) ||
+ ((roi.bottom - roi.top) <= 0)) {
+ *_aidl_return = HistogramErrorCode::BAD_ROI;
+ ALOGE("histogram error, BAD_ROI (%d, %d, %d, %d) \n", roi.left, roi.top, roi.right,
+ roi.bottom);
+ return ndk::ScopedAStatus::ok();
+ }
+ if ((weight.weightR + weight.weightG + weight.weightB) != (histogram::WEIGHT_SUM)) {
+ *_aidl_return = HistogramErrorCode::BAD_WEIGHT;
+ ALOGE("histogram error, BAD_WEIGHT(%d, %d, %d)\n", weight.weightR, weight.weightG,
+ weight.weightB);
+ return ndk::ScopedAStatus::ok();
+ }
+ if (pos != HistogramPos::POST && pos != HistogramPos::PRE) {
+ *_aidl_return = HistogramErrorCode::BAD_POSITION;
+ ALOGE("histogram error, BAD_POSITION(%d)\n", (int)pos);
+ return ndk::ScopedAStatus::ok();
+ }
+ if (pri != Priority::NORMAL && pri != Priority::PRIORITY) {
+ *_aidl_return = HistogramErrorCode::BAD_PRIORITY;
+ ALOGE("histogram error, BAD_PRIORITY(%d)\n", (int)pri);
+ return ndk::ScopedAStatus::ok();
+ }
+ RoiRect roiCaled = mMediator.calRoi(roi); // fit roi coordinates to RRS
+ runMediator(roiCaled, weight, pos, histogrambuffer);
+ if (mMediator.isSecureContentPresenting() == true) {
+ /* clear data to avoid leakage */
+ std::fill(histogrambuffer->begin(), histogrambuffer->end(), 0);
+ histogrambuffer->clear();
+ *_aidl_return = HistogramErrorCode::DRM_PLAYING; // panel is playing DRM content
+ return ndk::ScopedAStatus::ok();
+ }
+
+ *_aidl_return = HistogramErrorCode::NONE;
+ return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Display::getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return){
- if (mDevice) {
- *_aidl_return = mDevice->getPanelCalibrationStatus();
+ if (mDisplay) {
+ *_aidl_return = mDisplay->getPanelCalibrationStatus();
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+
+ndk::ScopedAStatus Display::isDbmSupported(bool *_aidl_return) {
+ if (!mDisplay) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ *_aidl_return = mDisplay->isDbmSupported();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Display::setDbmState(bool enabled) {
+ if (!mDisplay) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ mDisplay->setDbmState(enabled);
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace display
} // namespace pixel
} // namespace hardware
diff --git a/libhwc2.1/pixel-display.h b/libhwc2.1/pixel-display.h
index 4ca69d7..df437af 100644
--- a/libhwc2.1/pixel-display.h
+++ b/libhwc2.1/pixel-display.h
@@ -18,6 +18,7 @@
#include <aidl/com/google/hardware/pixel/display/BnDisplay.h>
+#include "./histogram_mediator.h"
#include "ExynosDevice.h"
namespace aidl {
@@ -28,16 +29,16 @@ namespace pixel {
namespace display {
using aidl::android::hardware::common::NativeHandle;
-using RoiRect = ::aidl::android::hardware::graphics::common::Rect;
-using Weight = ::aidl::com::google::hardware::pixel::display::Weight;
-using HistogramPos = ::aidl::com::google::hardware::pixel::display::HistogramPos;
-using Priority = ::aidl::com::google::hardware::pixel::display::Priority;
-using HistogramErrorCode = ::aidl::com::google::hardware::pixel::display::HistogramErrorCode;
+using RoiRect = histogram::RoiRect;
+using Weight = histogram::Weight;
+using HistogramPos = histogram::HistogramPos;
+using Priority = histogram::Priority;
+using HistogramErrorCode = histogram::HistogramErrorCode;
// Default implementation
class Display : public BnDisplay {
public:
- Display(ExynosDevice *device) : mDevice(device){};
+ Display(ExynosDisplay *display) : mDisplay(display), mMediator(display) {}
ndk::ScopedAStatus isHbmSupported(bool *_aidl_return) override;
ndk::ScopedAStatus setHbmState(HbmState state) override;
@@ -58,9 +59,17 @@ public:
Priority pri, std::vector<char16_t> *histogrambuffer,
HistogramErrorCode *_aidl_return) override;
ndk::ScopedAStatus getPanelCalibrationStatus(PanelCalibrationStatus *_aidl_return) override;
+ ndk::ScopedAStatus isDbmSupported(bool *_aidl_return) override;
+ ndk::ScopedAStatus setDbmState(bool enabled) override;
+ ndk::ScopedAStatus setPeakRefreshRate(int rate) override;
+ ndk::ScopedAStatus setLowPowerMode(bool enabled) override;
+ ndk::ScopedAStatus isOperationRateSupported(bool *_aidl_return) override;
private:
- ExynosDevice *mDevice = nullptr;
+ bool runMediator(const RoiRect &roi, const Weight &weight, const HistogramPos &pos,
+ std::vector<char16_t> *histogrambuffer);
+ ExynosDisplay *mDisplay = nullptr;
+ histogram::HistogramMediator mMediator;
};
} // namespace display
} // namespace pixel
diff --git a/libhwjpeg/Android.bp b/libhwjpeg/Android.bp
index 3ac4d6e..86dc84d 100644
--- a/libhwjpeg/Android.bp
+++ b/libhwjpeg/Android.bp
@@ -10,6 +10,7 @@ cc_library_shared {
"AppMarkerWriter.cpp",
"ExynosJpegEncoder.cpp",
"ExynosJpegEncoderForCamera.cpp",
+ "FileLock.cpp",
"hwjpeg-base.cpp",
"hwjpeg-v4l2.cpp",
"libhwjpeg-exynos.cpp",
@@ -24,6 +25,9 @@ cc_library_shared {
"libhardware_headers",
"libsystem_headers",
],
+ export_header_lib_headers: [
+ "google_hal_headers",
+ ],
shared_libs: [
"liblog",
"libutils",
diff --git a/libhwjpeg/AppMarkerWriter.cpp b/libhwjpeg/AppMarkerWriter.cpp
index 4a5edbb..f9eb12b 100644
--- a/libhwjpeg/AppMarkerWriter.cpp
+++ b/libhwjpeg/AppMarkerWriter.cpp
@@ -15,22 +15,22 @@
* limitations under the License.
*/
-#include "hwjpeg-internal.h"
#include "AppMarkerWriter.h"
+
#include "IFDWriter.h"
+#include "hwjpeg-internal.h"
-static const char ExifAsciiPrefix[] = { 'A', 'S', 'C', 'I', 'I', 0x0, 0x0, 0x0 };
-static const char ExifIdentifierCode[6] = { 'E', 'x', 'i', 'f', 0x00, 0x00 };
-static char TiffHeader[8] = { 'I', 'I', 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 };
-static const unsigned char ComponentsConfiguration[4] = { 1, 2, 3, 0 }; // YCbCr
-static const unsigned char SceneType[4] = { 1, 0, 0, 0 }; // A directly photographed image
+static const char ExifAsciiPrefix[] = {'A', 'S', 'C', 'I', 'I', 0x0, 0x0, 0x0};
+static const char ExifIdentifierCode[6] = {'E', 'x', 'i', 'f', 0x00, 0x00};
+static char TiffHeader[8] = {'I', 'I', 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00};
+static const unsigned char ComponentsConfiguration[4] = {1, 2, 3, 0}; // YCbCr
+static const unsigned char SceneType[4] = {1, 0, 0, 0}; // A directly photographed image
#ifndef __LITTLE_ENDIAN__
CEndianessChecker __LITTLE_ENDIAN__;
#endif
-CEndianessChecker::CEndianessChecker()
-{
+CEndianessChecker::CEndianessChecker() {
int num = 1;
__little = (*reinterpret_cast<char *>(&num) == 1);
if (__little) {
@@ -42,15 +42,12 @@ CEndianessChecker::CEndianessChecker()
}
}
-
CAppMarkerWriter::CAppMarkerWriter()
- : m_pAppBase(NULL), m_pApp1End(NULL), m_pExif(NULL), m_pExtra(NULL)
-{
+ : m_pAppBase(NULL), m_pApp1End(NULL), m_pExif(NULL), m_pExtra(NULL) {
Init();
}
-CAppMarkerWriter::CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug)
-{
+CAppMarkerWriter::CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug) {
extra_appinfo_t extraInfo;
app_info_t appInfo[15];
@@ -64,8 +61,7 @@ CAppMarkerWriter::CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_att
PrepareAppWriter(base, exif, &extraInfo);
}
-void CAppMarkerWriter::Init()
-{
+void CAppMarkerWriter::Init() {
m_pApp1End = NULL;
m_szApp1 = 0;
@@ -85,8 +81,8 @@ void CAppMarkerWriter::Init()
m_pThumbSizePlaceholder = NULL;
}
-void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extra_appinfo_t *extra)
-{
+void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif,
+ extra_appinfo_t *extra) {
m_pAppBase = base;
m_pExif = exif;
@@ -96,8 +92,7 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
if (exif) {
// APP1
- applen += JPEG_SEGMENT_LENFIELD_SIZE +
- ARRSIZE(ExifIdentifierCode) + ARRSIZE(TiffHeader);
+ applen += JPEG_SEGMENT_LENFIELD_SIZE + ARRSIZE(ExifIdentifierCode) + ARRSIZE(TiffHeader);
// 0th IFD: Make, Model, Orientation, Software,
// DateTime, YCbCrPositioning, X/Y Resolutions, Exif and GPS
@@ -112,24 +107,21 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
if (m_szMake > 0) {
m_n0thIFDFields++;
applen += IFD_FIELD_SIZE;
- if (m_szMake > 3)
- applen += m_szMake + 1;
+ if (m_szMake > 3) applen += m_szMake + 1;
}
m_szSoftware = strlen(m_pExif->software);
if (m_szSoftware > 0) {
m_n0thIFDFields++;
applen += IFD_FIELD_SIZE;
- if (m_szSoftware > 3)
- applen += m_szSoftware + 1;
+ if (m_szSoftware > 3) applen += m_szSoftware + 1;
}
m_szModel = strlen(m_pExif->model);
if (m_szModel > 0) {
m_n0thIFDFields++;
applen += IFD_FIELD_SIZE;
- if (m_szModel > 3)
- applen += m_szModel + 1;
+ if (m_szModel > 3) applen += m_szModel + 1;
}
if (m_pExif->enableGps) {
@@ -144,11 +136,11 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
* - Flash, FlashPixVersion, ColorSpace, PixelXDimension, PixelYDimension,
* - ExposureMode, WhiteBalance, FocalLengthIn35mmFilm, SceneCaptureType,
* - ComponentsConfiguration
- * - SceneType, CustomRendered, Contrast, Saturation, Sharpness
+ * - SceneType, CustomRendered, Contrast, Saturation, Sharpness
* (S)Rational Fields: 9
* - ExposureTime, FNumber, ShutterSpeedValue, ApertureValue,
* - BrightnessValue, ExposureBiasValue, MaxApertureValue, FocalLength
- * - DigitalZoomRatio
+ * - DigitalZoomRatio
* ASCII Fields: 6
* - DateTimeOriginal, DateTimeDigitized, SubsecTime, SubsecTimeOriginal,
* - SubsecTimeDigitized, ImageUniqueID
@@ -174,28 +166,24 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
if (m_szUniqueID > 0) {
m_nExifIFDFields++;
applen += IFD_FIELD_SIZE;
- if (m_szUniqueID > 3)
- applen += m_szUniqueID + 1;
+ if (m_szUniqueID > 3) applen += m_szUniqueID + 1;
}
if (m_pExif->maker_note_size > 0) {
m_nExifIFDFields++;
applen += IFD_FIELD_SIZE;
- if (m_pExif->maker_note_size > 4)
- applen += m_pExif->maker_note_size;
+ if (m_pExif->maker_note_size > 4) applen += m_pExif->maker_note_size;
}
if (m_pExif->user_comment_size > 0) {
m_nExifIFDFields++;
applen += IFD_FIELD_SIZE;
- if (m_pExif->user_comment_size > 4)
- applen += m_pExif->user_comment_size;
+ if (m_pExif->user_comment_size > 4) applen += m_pExif->user_comment_size;
}
// Interoperability SubIFD
m_nExifIFDFields++; // Interoperability is sub IFD of Exif sub IFD
- applen += IFD_FIELD_SIZE +
- IFD_FIELDCOUNT_SIZE + IFD_VALOFF_SIZE + IFD_FIELD_SIZE * 2;
+ applen += IFD_FIELD_SIZE + IFD_FIELDCOUNT_SIZE + IFD_VALOFF_SIZE + IFD_FIELD_SIZE * 2;
if (m_pExif->enableGps) {
size_t len;
@@ -233,8 +221,8 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
* - JPEGInterchangeFormat, JPEGInterchangeFormatLength
*/
if ((m_pExif->widthThumb < 16) || (m_pExif->heightThumb < 16)) {
- ALOGE("Insufficient thumbnail information %dx%d",
- m_pExif->widthThumb, m_pExif->heightThumb);
+ ALOGE("Insufficient thumbnail information %dx%d", m_pExif->widthThumb,
+ m_pExif->heightThumb);
return;
}
@@ -251,13 +239,17 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
if (extra) {
for (int idx = 0; idx < extra->num_of_appmarker; idx++) {
- if ((extra->appInfo[idx].appid < EXTRA_APPMARKER_MIN) || (extra->appInfo[idx].appid >= EXTRA_APPMARKER_LIMIT)) {
+ if ((extra->appInfo[idx].appid < EXTRA_APPMARKER_MIN) ||
+ (extra->appInfo[idx].appid >= EXTRA_APPMARKER_LIMIT)) {
ALOGE("Invalid extra APP segment ID %d", extra->appInfo[idx].appid);
return;
}
- if ((extra->appInfo[idx].dataSize == 0) || (extra->appInfo[idx].dataSize > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
- ALOGE("Invalid APP%d segment size, %u bytes", extra->appInfo[idx].appid, extra->appInfo[idx].dataSize);
+ if ((extra->appInfo[idx].dataSize == 0) ||
+ (extra->appInfo[idx].dataSize >
+ (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
+ ALOGE("Invalid APP%d segment size, %u bytes", extra->appInfo[idx].appid,
+ extra->appInfo[idx].dataSize);
return;
}
@@ -268,7 +260,7 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
m_pExtra = extra;
// |<- m_szApp1 ->|<- m_szMaxThumbSize ->|<-m_szAppX->|
- // |<----- size of total APP1 and APP4 segments ----->|<-APP11->|<-- main image
+ // |<----- size of total APP1 and APPX segments ----->|<-APP11->|<-- main image
// m_pAppBase m_pThumbBase | | return
// | | | | ||
// v v | | v|
@@ -283,20 +275,16 @@ void CAppMarkerWriter::PrepareAppWriter(char *base, exif_attribute_t *exif, extr
}
#define APPMARKLEN (JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE)
-char *CAppMarkerWriter::WriteAPP11(char *current, size_t dummy, size_t align)
-{
+char *CAppMarkerWriter::WriteAPP11(char *current, size_t dummy, size_t align) {
ALOG_ASSERT((align & ~align) == 0);
- if ((dummy == 0) && (align == 1))
- return current;
+ if ((dummy == 0) && (align == 1)) return current;
- if (!m_pExif && !m_pExtra)
- return current;
+ if (!m_pExif && !m_pExtra) return current;
uint16_t len = PTR_TO_ULONG(current + APPMARKLEN) & (align - 1);
- if (len)
- len = align - len;
+ if (len) len = align - len;
len += dummy + JPEG_SEGMENT_LENFIELD_SIZE;
@@ -307,10 +295,8 @@ char *CAppMarkerWriter::WriteAPP11(char *current, size_t dummy, size_t align)
return current + len;
}
-char *CAppMarkerWriter::WriteAPPX(char *current, bool just_reserve)
-{
- if (!m_pExtra)
- return current;
+char *CAppMarkerWriter::WriteAPPX(char *current, bool just_reserve) {
+ if (!m_pExtra) return current;
for (int idx = 0; idx < m_pExtra->num_of_appmarker; idx++) {
int appid = m_pExtra->appInfo[idx].appid;
@@ -330,10 +316,8 @@ char *CAppMarkerWriter::WriteAPPX(char *current, bool just_reserve)
return current;
}
-char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, bool updating)
-{
- if (!m_pExif)
- return current;
+char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, bool updating) {
+ if (!m_pExif) return current;
// APP1 Marker
*current++ = 0xFF;
@@ -344,18 +328,15 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
current += JPEG_SEGMENT_LENFIELD_SIZE;
} else {
uint16_t len = m_szApp1;
- if (reserve_thumbnail_space)
- len += m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED;
+ if (reserve_thumbnail_space) len += m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED;
current = WriteDataInBig(current, len);
}
// Exif Identifier
- for (size_t i = 0; i < ARRSIZE(ExifIdentifierCode); i++)
- *current++ = ExifIdentifierCode[i];
+ for (size_t i = 0; i < ARRSIZE(ExifIdentifierCode); i++) *current++ = ExifIdentifierCode[i];
char *tiffheader = current;
- for (size_t i = 0; i < ARRSIZE(TiffHeader); i++)
- *current++ = TiffHeader[i];
+ for (size_t i = 0; i < ARRSIZE(TiffHeader); i++) *current++ = TiffHeader[i];
CIFDWriter writer(tiffheader, current, m_n0thIFDFields);
@@ -364,12 +345,9 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
writer.WriteRational(EXIF_TAG_X_RESOLUTION, 1, &m_pExif->x_resolution);
writer.WriteRational(EXIF_TAG_Y_RESOLUTION, 1, &m_pExif->y_resolution);
writer.WriteShort(EXIF_TAG_RESOLUTION_UNIT, 1, &m_pExif->resolution_unit);
- if (m_szMake > 0)
- writer.WriteASCII(EXIF_TAG_MAKE, m_szMake + 1, m_pExif->maker);
- if (m_szModel > 0)
- writer.WriteASCII(EXIF_TAG_MODEL, m_szModel + 1, m_pExif->model);
- if (m_szSoftware > 0)
- writer.WriteASCII(EXIF_TAG_SOFTWARE, m_szSoftware + 1, m_pExif->software);
+ if (m_szMake > 0) writer.WriteASCII(EXIF_TAG_MAKE, m_szMake + 1, m_pExif->maker);
+ if (m_szModel > 0) writer.WriteASCII(EXIF_TAG_MODEL, m_szModel + 1, m_pExif->model);
+ if (m_szSoftware > 0) writer.WriteASCII(EXIF_TAG_SOFTWARE, m_szSoftware + 1, m_pExif->software);
writer.WriteCString(EXIF_TAG_DATE_TIME, EXIF_DATETIME_LENGTH, m_pExif->date_time);
char *pSubIFDBase = writer.BeginSubIFD(EXIF_TAG_EXIF_IFD_POINTER);
@@ -379,9 +357,11 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
exifwriter.WriteRational(EXIF_TAG_FNUMBER, 1, &m_pExif->fnumber);
exifwriter.WriteShort(EXIF_TAG_EXPOSURE_PROGRAM, 1, &m_pExif->exposure_program);
exifwriter.WriteShort(EXIF_TAG_ISO_SPEED_RATING, 1, &m_pExif->iso_speed_rating);
- exifwriter.WriteUndef(EXIF_TAG_EXIF_VERSION, 4, reinterpret_cast<unsigned char *>(m_pExif->exif_version));
+ exifwriter.WriteUndef(EXIF_TAG_EXIF_VERSION, 4,
+ reinterpret_cast<unsigned char *>(m_pExif->exif_version));
exifwriter.WriteCString(EXIF_TAG_DATE_TIME_ORG, EXIF_DATETIME_LENGTH, m_pExif->date_time);
- exifwriter.WriteCString(EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_DATETIME_LENGTH, m_pExif->date_time);
+ exifwriter.WriteCString(EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_DATETIME_LENGTH,
+ m_pExif->date_time);
exifwriter.WriteSRational(EXIF_TAG_SHUTTER_SPEED, 1, &m_pExif->shutter_speed);
exifwriter.WriteRational(EXIF_TAG_APERTURE, 1, &m_pExif->aperture);
exifwriter.WriteSRational(EXIF_TAG_BRIGHTNESS, 1, &m_pExif->brightness);
@@ -389,16 +369,21 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
exifwriter.WriteRational(EXIF_TAG_MAX_APERTURE, 1, &m_pExif->max_aperture);
exifwriter.WriteShort(EXIF_TAG_METERING_MODE, 1, &m_pExif->metering_mode);
exifwriter.WriteShort(EXIF_TAG_FLASH, 1, &m_pExif->flash);
- exifwriter.WriteUndef(EXIF_TAG_FLASHPIX_VERSION, 4, reinterpret_cast<const unsigned char *>("0100"));
+ exifwriter.WriteUndef(EXIF_TAG_FLASHPIX_VERSION, 4,
+ reinterpret_cast<const unsigned char *>("0100"));
exifwriter.WriteUndef(EXIF_TAG_COMPONENTS_CONFIGURATION, 4, ComponentsConfiguration);
exifwriter.WriteRational(EXIF_TAG_FOCAL_LENGTH, 1, &m_pExif->focal_length);
exifwriter.WriteCString(EXIF_TAG_SUBSEC_TIME, EXIF_SUBSECTIME_LENGTH, m_pExif->sec_time);
- exifwriter.WriteCString(EXIF_TAG_SUBSEC_TIME_ORIG, EXIF_SUBSECTIME_LENGTH, m_pExif->sec_time);
- exifwriter.WriteCString(EXIF_TAG_SUBSEC_TIME_DIG, EXIF_SUBSECTIME_LENGTH, m_pExif->sec_time);
+ exifwriter.WriteCString(EXIF_TAG_SUBSEC_TIME_ORIG, EXIF_SUBSECTIME_LENGTH,
+ m_pExif->sec_time);
+ exifwriter.WriteCString(EXIF_TAG_SUBSEC_TIME_DIG, EXIF_SUBSECTIME_LENGTH,
+ m_pExif->sec_time);
if (m_pExif->maker_note_size > 0)
- exifwriter.WriteUndef(EXIF_TAG_MAKER_NOTE, m_pExif->maker_note_size, m_pExif->maker_note);
+ exifwriter.WriteUndef(EXIF_TAG_MAKER_NOTE, m_pExif->maker_note_size,
+ m_pExif->maker_note);
if (m_pExif->user_comment_size > 0)
- exifwriter.WriteUndef(EXIF_TAG_USER_COMMENT, m_pExif->user_comment_size, m_pExif->user_comment);
+ exifwriter.WriteUndef(EXIF_TAG_USER_COMMENT, m_pExif->user_comment_size,
+ m_pExif->user_comment);
exifwriter.WriteShort(EXIF_TAG_COLOR_SPACE, 1, &m_pExif->color_space);
exifwriter.WriteLong(EXIF_TAG_PIXEL_X_DIMENSION, 1, &m_pExif->width);
exifwriter.WriteLong(EXIF_TAG_PIXEL_Y_DIMENSION, 1, &m_pExif->height);
@@ -407,7 +392,8 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
exifwriter.WriteShort(EXIF_TAG_EXPOSURE_MODE, 1, &m_pExif->exposure_mode);
exifwriter.WriteShort(EXIF_TAG_WHITE_BALANCE, 1, &m_pExif->white_balance);
exifwriter.WriteRational(EXIF_TAG_DIGITAL_ZOOM_RATIO, 1, &m_pExif->digital_zoom_ratio);
- exifwriter.WriteShort(EXIF_TAG_FOCA_LENGTH_IN_35MM_FILM, 1, &m_pExif->focal_length_in_35mm_length);
+ exifwriter.WriteShort(EXIF_TAG_FOCA_LENGTH_IN_35MM_FILM, 1,
+ &m_pExif->focal_length_in_35mm_length);
exifwriter.WriteShort(EXIF_TAG_SCENCE_CAPTURE_TYPE, 1, &m_pExif->scene_capture_type);
exifwriter.WriteShort(EXIF_TAG_CONTRAST, 1, &m_pExif->contrast);
exifwriter.WriteShort(EXIF_TAG_SATURATION, 1, &m_pExif->saturation);
@@ -451,9 +437,9 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
size_t idx;
len = min(len, static_cast<size_t>(99UL));
unsigned char buf[sizeof(ExifAsciiPrefix) + len + 1];
- for (idx = 0; idx < sizeof(ExifAsciiPrefix); idx++)
- buf[idx] = ExifAsciiPrefix[idx];
- strncpy(reinterpret_cast<char *>(buf) + idx, m_pExif->gps_processing_method, len + 1);
+ for (idx = 0; idx < sizeof(ExifAsciiPrefix); idx++) buf[idx] = ExifAsciiPrefix[idx];
+ strncpy(reinterpret_cast<char *>(buf) + idx, m_pExif->gps_processing_method,
+ len + 1);
len += idx;
buf[len] = '\0';
gpswriter.WriteUndef(EXIF_TAG_GPS_PROCESSING_METHOD, len + 1, buf);
@@ -466,8 +452,7 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
}
// thumbnail and the next IFD pointer is never updated.
- if (updating)
- return NULL;
+ if (updating) return NULL;
if (m_pExif->enableThumb) {
writer.Finish(false);
@@ -496,16 +481,14 @@ char *CAppMarkerWriter::WriteAPP1(char *current, bool reserve_thumbnail_space, b
return writer.GetNextIFDBase();
}
-void CAppMarkerWriter::Finalize(size_t thumbsize)
-{
+void CAppMarkerWriter::Finalize(size_t thumbsize) {
if (m_pThumbSizePlaceholder) {
uint32_t len = static_cast<uint32_t>(thumbsize);
WriteData(m_pThumbSizePlaceholder, len);
m_pThumbSizePlaceholder = NULL;
}
}
-void CAppMarkerWriter::UpdateApp1Size(size_t amount)
-{
+void CAppMarkerWriter::UpdateApp1Size(size_t amount) {
if (m_pAppBase) {
uint16_t len = m_szApp1 + amount;
WriteDataInBig(m_pAppBase + JPEG_MARKER_SIZE, len);
@@ -514,24 +497,25 @@ void CAppMarkerWriter::UpdateApp1Size(size_t amount)
static const char *dbgerrmsg = "Updating debug data failed";
-static inline size_t GetSegLen(char *p)
-{
+static inline size_t GetSegLen(char *p) {
size_t len = (*reinterpret_cast<unsigned char *>(p) & 0xFF) << 8;
return len | (*reinterpret_cast<unsigned char *>(p + 1) & 0xFF);
}
-static inline size_t GetExtraAPPSize(extra_appinfo_t *info)
-{
+static inline size_t GetExtraAPPSize(extra_appinfo_t *info) {
size_t len = 0;
for (int idx = 0; idx < info->num_of_appmarker; idx++) {
- if ((info->appInfo[idx].appid < EXTRA_APPMARKER_MIN) || (info->appInfo[idx].appid >= EXTRA_APPMARKER_LIMIT)) {
+ if ((info->appInfo[idx].appid < EXTRA_APPMARKER_MIN) ||
+ (info->appInfo[idx].appid >= EXTRA_APPMARKER_LIMIT)) {
ALOGE("%s: Invalid extra APP segment ID %d", dbgerrmsg, info->appInfo[idx].appid);
return 0;
}
- if ((info->appInfo[idx].dataSize == 0) || (info->appInfo[idx].dataSize > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
- ALOGE("%s: Invalid APP%d segment size, %u bytes.", dbgerrmsg, info->appInfo[idx].appid, info->appInfo[idx].dataSize);
+ if ((info->appInfo[idx].dataSize == 0) ||
+ (info->appInfo[idx].dataSize > (JPEG_MAX_SEGMENT_SIZE - JPEG_SEGMENT_LENFIELD_SIZE))) {
+ ALOGE("%s: Invalid APP%d segment size, %u bytes.", dbgerrmsg, info->appInfo[idx].appid,
+ info->appInfo[idx].dataSize);
return 0;
}
@@ -594,34 +578,33 @@ bool UpdateDebugData(char *jpeg, size_t jpeglen, extra_appinfo_t *extra) // incl
}
appid = marker & 0xF;
- if (((marker & 0xF0) == 0xE0) && ((appid >= EXTRA_APPMARKER_MIN) && (appid <= EXTRA_APPMARKER_LIMIT))) {
+ if (((marker & 0xF0) == 0xE0) &&
+ ((appid >= EXTRA_APPMARKER_MIN) && (appid <= EXTRA_APPMARKER_LIMIT))) {
if (appid != extra->appInfo[idx].appid) {
- ALOGE("%s: stored appid(%d) is different with updated appid(%d)",
- dbgerrmsg, appid, extra->appInfo[idx].appid);
+ ALOGE("%s: stored appid(%d) is different with updated appid(%d)", dbgerrmsg, appid,
+ extra->appInfo[idx].appid);
return false;
}
seglen = GetSegLen(jpeg);
if (seglen < (extra->appInfo[idx].dataSize + JPEG_SEGMENT_LENFIELD_SIZE)) {
- ALOGE("%s: too small APP%d length %zu to store %u bytes",
- dbgerrmsg, appid, seglen, extra->appInfo[idx].dataSize);
+ ALOGE("%s: too small APP%d length %zu to store %u bytes", dbgerrmsg, appid, seglen,
+ extra->appInfo[idx].dataSize);
return false;
}
- memcpy(jpeg + JPEG_SEGMENT_LENFIELD_SIZE,
- extra->appInfo[idx].appData, extra->appInfo[idx].dataSize);
+ memcpy(jpeg + JPEG_SEGMENT_LENFIELD_SIZE, extra->appInfo[idx].appData,
+ extra->appInfo[idx].dataSize);
ALOGD("Successfully updated %u bytes to APP%d", extra->appInfo[idx].dataSize, appid);
- validlen -= extra->appInfo[idx].dataSize + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
+ validlen -=
+ extra->appInfo[idx].dataSize + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
idx++;
} else {
// just skip all other segments
seglen = GetSegLen(jpeg);
- if (seglen == 0)
- seglen++; // fixup for invalid segment lengths
- if (jpeglen < seglen)
- seglen = jpeglen;
-
+ if (seglen == 0) seglen++; // fixup for invalid segment lengths
+ if (jpeglen < seglen) seglen = jpeglen;
}
jpeg += seglen;
@@ -633,8 +616,7 @@ bool UpdateDebugData(char *jpeg, size_t jpeglen, extra_appinfo_t *extra) // incl
static const char *exiferrmsg = "Updating exif failed";
-bool UpdateExif(char *jpeg, size_t jpeglen, exif_attribute_t *exif)
-{
+bool UpdateExif(char *jpeg, size_t jpeglen, exif_attribute_t *exif) {
if (!exif) {
ALOGI("No Exif to update");
return true;
@@ -668,8 +650,7 @@ bool UpdateExif(char *jpeg, size_t jpeglen, exif_attribute_t *exif)
return true;
}
-void ExtractDebugAttributeInfo(debug_attribute_t *debug, extra_appinfo_t *extra)
-{
+void ExtractDebugAttributeInfo(debug_attribute_t *debug, extra_appinfo_t *extra) {
if (!debug) {
extra->num_of_appmarker = 0;
return;
diff --git a/libhwjpeg/AppMarkerWriter.h b/libhwjpeg/AppMarkerWriter.h
index 5232e31..a25d9c0 100644
--- a/libhwjpeg/AppMarkerWriter.h
+++ b/libhwjpeg/AppMarkerWriter.h
@@ -18,6 +18,8 @@
#define __HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
#include <ExynosExif.h>
+
+#include "hwjpeg-internal.h"
#include "include/hardware/exynos/ExynosExif.h"
#define JPEG_MAX_SEGMENT_SIZE ((1 << 16) - 1)
@@ -33,10 +35,9 @@
#define IFD_COUNT_SIZE 4
#define IFD_VALOFF_SIZE 4
-#define IFD_FIELD_SIZE \
- (IFD_TAG_SIZE + IFD_TYPE_SIZE + IFD_COUNT_SIZE + IFD_VALOFF_SIZE)
+#define IFD_FIELD_SIZE (IFD_TAG_SIZE + IFD_TYPE_SIZE + IFD_COUNT_SIZE + IFD_VALOFF_SIZE)
-#define EXTRA_APPMARKER_MIN 4
+#define EXTRA_APPMARKER_MIN 2
#define EXTRA_APPMARKER_LIMIT 10
#define MAX_GPS_PROCESSINGMETHOD_SIZE 108
@@ -49,8 +50,8 @@ class CAppMarkerWriter {
char *m_pAppBase;
char *m_pApp1End;
size_t m_szMaxThumbSize; // Maximum available thumbnail stream size minus JPEG_MARKER_SIZE
- uint16_t m_szApp1; // The size of APP1 segment without marker
- uint16_t m_szApp11; // The size of APP11 segment without marker
+ uint16_t m_szApp1; // The size of APP1 segment without marker
+ uint16_t m_szApp11; // The size of APP11 segment without marker
uint16_t m_n0thIFDFields;
uint16_t m_n1stIFDFields;
uint16_t m_nExifIFDFields;
@@ -76,6 +77,7 @@ class CAppMarkerWriter {
char *WriteAPP1(char *base, bool reserve_thumbnail_space, bool updating = false);
char *WriteAPPX(char *base, bool just_reserve);
char *WriteAPP11(char *current, size_t dummy, size_t align);
+
public:
// dummy: number of dummy bytes written by the compressor of the main image
// this dummy size should be added to the APP1 length. Howerver, this dummy area
@@ -84,7 +86,7 @@ public:
CAppMarkerWriter();
CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug);
- ~CAppMarkerWriter() { }
+ ~CAppMarkerWriter() {}
void PrepareAppWriter(char *base, exif_attribute_t *exif, extra_appinfo_t *info);
@@ -100,15 +102,14 @@ public:
// CalculateAPPSize() is valid after Write() is successful.
size_t CalculateAPPSize(size_t thumblen = JPEG_MAX_SEGMENT_SIZE) {
size_t appsize = 0;
- if (m_szApp1 > 0)
- appsize += m_szApp1 + JPEG_MARKER_SIZE;
+ if (m_szApp1 > 0) appsize += m_szApp1 + JPEG_MARKER_SIZE;
if (m_pExtra) {
for (int idx = 0; idx < m_pExtra->num_of_appmarker; idx++)
- appsize += m_pExtra->appInfo[idx].dataSize +
- + JPEG_MARKER_SIZE + JPEG_SEGMENT_LENFIELD_SIZE;
+ appsize += m_pExtra->appInfo[idx].dataSize + +JPEG_MARKER_SIZE +
+ JPEG_SEGMENT_LENFIELD_SIZE;
}
if (IsThumbSpaceReserved())
- appsize += m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED ;
+ appsize += m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED;
else
appsize += min(m_szMaxThumbSize, thumblen);
@@ -117,7 +118,8 @@ public:
char *GetApp1End() { return m_pApp1End; }
- void Write(bool reserve_thumbnail_space, size_t dummy, size_t align, bool reserve_debug = false) {
+ void Write(bool reserve_thumbnail_space, size_t dummy, size_t align,
+ bool reserve_debug = false) {
m_pApp1End = WriteAPP1(m_pAppBase, reserve_thumbnail_space);
char *appXend = WriteAPPX(m_pApp1End, reserve_debug);
char *app11end = WriteAPP11(appXend, dummy, align);
@@ -129,7 +131,7 @@ public:
bool IsThumbSpaceReserved() {
return PTR_DIFF(m_pAppBase, m_pApp1End) ==
- (m_szApp1 + m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED + JPEG_MARKER_SIZE);
+ (m_szApp1 + m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED + JPEG_MARKER_SIZE);
}
void Finalize(size_t thumbsize);
diff --git a/libhwjpeg/ExynosJpegEncoder.cpp b/libhwjpeg/ExynosJpegEncoder.cpp
index 39e7a2e..d833ca7 100644
--- a/libhwjpeg/ExynosJpegEncoder.cpp
+++ b/libhwjpeg/ExynosJpegEncoder.cpp
@@ -15,24 +15,27 @@
* limitations under the License.
*/
-#include <linux/videodev2.h>
-
#include <ExynosJpegApi.h>
+#include <linux/videodev2.h>
#include "hwjpeg-internal.h"
-int ExynosJpegEncoder::setJpegConfig(void* pConfig)
-{
+int ExynosJpegEncoder::lock() {
+ return m_hwjpeg.lock();
+}
+
+int ExynosJpegEncoder::unlock() {
+ return m_hwjpeg.unlock();
+}
+
+int ExynosJpegEncoder::setJpegConfig(void *pConfig) {
ExynosJpegEncoder *that = reinterpret_cast<ExynosJpegEncoder *>(pConfig);
- if (!setColorFormat(that->m_v4l2Format))
- return -1;
+ if (!setColorFormat(that->m_v4l2Format)) return -1;
- if (!setJpegFormat(that->m_jpegFormat))
- return -1;
+ if (!setJpegFormat(that->m_jpegFormat)) return -1;
- if (!setSize(that->m_nWidth, that->m_nHeight))
- return -1;
+ if (!setSize(that->m_nWidth, that->m_nHeight)) return -1;
m_iInBufType = that->m_iInBufType;
m_iOutBufType = that->m_iOutBufType;
@@ -40,127 +43,101 @@ int ExynosJpegEncoder::setJpegConfig(void* pConfig)
return 0;
}
-int ExynosJpegEncoder::getInBuf(int *piBuf, int *piInputSize, int iSize)
-{
+int ExynosJpegEncoder::getInBuf(int *piBuf, int *piInputSize, int iSize) {
if (iSize < 1) {
ALOGE("Invalid array size %d for getInBuf()", iSize);
return -1;
}
size_t len_buffers[iSize];
- if (!m_hwjpeg.GetImageBuffers(piBuf, len_buffers, static_cast<unsigned int>(iSize)))
- return -1;
+ if (!m_hwjpeg.GetImageBuffers(piBuf, len_buffers, static_cast<unsigned int>(iSize))) return -1;
- for (int i = 0; i < iSize; i++)
- piInputSize[i] = static_cast<int>(len_buffers[i]);
+ for (int i = 0; i < iSize; i++) piInputSize[i] = static_cast<int>(len_buffers[i]);
return 0;
}
-int ExynosJpegEncoder::getOutBuf(int *piBuf, int *piOutputSize)
-{
+int ExynosJpegEncoder::getOutBuf(int *piBuf, int *piOutputSize) {
size_t len;
- if (!m_hwjpeg.GetJpegBuffer(piBuf, &len))
- return -1;
+ if (!m_hwjpeg.GetJpegBuffer(piBuf, &len)) return -1;
*piOutputSize = static_cast<int>(len);
return 0;
}
-int ExynosJpegEncoder::setInBuf(int *piBuf, int *iSize)
-{
+int ExynosJpegEncoder::setInBuf(int *piBuf, int *iSize) {
size_t buflen[3];
unsigned int bufnum = 3;
- if (!EnsureFormatIsApplied())
- return -1;
+ if (!EnsureFormatIsApplied()) return -1;
- if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum))
- return -1;
+ if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum)) return -1;
- for (unsigned int i = 0; i < bufnum; i++)
- buflen[i] = static_cast<size_t>(iSize[i]);
+ for (unsigned int i = 0; i < bufnum; i++) buflen[i] = static_cast<size_t>(iSize[i]);
- if (!m_hwjpeg.SetImageBuffer(piBuf, buflen, bufnum))
- return -1;
+ if (!m_hwjpeg.SetImageBuffer(piBuf, buflen, bufnum)) return -1;
m_iInBufType = JPEG_BUF_TYPE_DMA_BUF;
return 0;
}
-int ExynosJpegEncoder::setOutBuf(int iBuf, int iSize, int offset)
-{
- if (!m_hwjpeg.SetJpegBuffer(iBuf, static_cast<size_t>(iSize), offset))
- return -1;
+int ExynosJpegEncoder::setOutBuf(int iBuf, int iSize, int offset) {
+ if (!m_hwjpeg.SetJpegBuffer(iBuf, static_cast<size_t>(iSize), offset)) return -1;
m_iOutBufType = JPEG_BUF_TYPE_DMA_BUF;
return 0;
}
-int ExynosJpegEncoder::getInBuf(char **pcBuf, int *piInputSize, int iSize)
-{
+int ExynosJpegEncoder::getInBuf(char **pcBuf, int *piInputSize, int iSize) {
if (iSize < 1) {
ALOGE("Invalid array size %d for getInBuf()", iSize);
return -1;
}
size_t len_buffers[iSize];
- if (!m_hwjpeg.GetImageBuffers(pcBuf, len_buffers, static_cast<unsigned int>(iSize)))
- return -1;
+ if (!m_hwjpeg.GetImageBuffers(pcBuf, len_buffers, static_cast<unsigned int>(iSize))) return -1;
- for (int i = 0; i < iSize; i++)
- piInputSize[i] = static_cast<int>(len_buffers[i]);
+ for (int i = 0; i < iSize; i++) piInputSize[i] = static_cast<int>(len_buffers[i]);
return 0;
}
-int ExynosJpegEncoder::getOutBuf(char **pcBuf, int *piOutputSize)
-{
+int ExynosJpegEncoder::getOutBuf(char **pcBuf, int *piOutputSize) {
size_t len;
- if (!m_hwjpeg.GetJpegBuffer(pcBuf, &len))
- return -1;
+ if (!m_hwjpeg.GetJpegBuffer(pcBuf, &len)) return -1;
*piOutputSize = static_cast<int>(len);
return 0;
}
-int ExynosJpegEncoder::setInBuf(char **pcBuf, int *iSize)
-{
+int ExynosJpegEncoder::setInBuf(char **pcBuf, int *iSize) {
size_t buflen[3];
unsigned int bufnum = 3;
- if (!EnsureFormatIsApplied())
- return -1;
+ if (!EnsureFormatIsApplied()) return -1;
- if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum))
- return -1;
+ if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum)) return -1;
- for (unsigned int i = 0; i < bufnum; i++)
- buflen[i] = static_cast<size_t>(iSize[i]);
+ for (unsigned int i = 0; i < bufnum; i++) buflen[i] = static_cast<size_t>(iSize[i]);
- if (!m_hwjpeg.SetImageBuffer(pcBuf, buflen, bufnum))
- return -1;
+ if (!m_hwjpeg.SetImageBuffer(pcBuf, buflen, bufnum)) return -1;
m_iInBufType = JPEG_BUF_TYPE_USER_PTR;
return 0;
}
-int ExynosJpegEncoder::setOutBuf(char *pcBuf, int iSize)
-{
- if (!m_hwjpeg.SetJpegBuffer(pcBuf, static_cast<size_t>(iSize)))
- return -1;
+int ExynosJpegEncoder::setOutBuf(char *pcBuf, int iSize) {
+ if (!m_hwjpeg.SetJpegBuffer(pcBuf, static_cast<size_t>(iSize))) return -1;
m_iOutBufType = JPEG_BUF_TYPE_USER_PTR;
return 0;
}
-int ExynosJpegEncoder::setJpegFormat(int iV4l2JpegFormat)
-{
- if (m_jpegFormat == iV4l2JpegFormat)
- return 0;
+int ExynosJpegEncoder::setJpegFormat(int iV4l2JpegFormat) {
+ if (m_jpegFormat == iV4l2JpegFormat) return 0;
unsigned int hfactor, vfactor;
switch (iV4l2JpegFormat) {
@@ -193,31 +170,27 @@ int ExynosJpegEncoder::setJpegFormat(int iV4l2JpegFormat)
return -1;
}
- if (!m_hwjpeg.SetChromaSampFactor(hfactor, vfactor))
- return -1;
+ if (!m_hwjpeg.SetChromaSampFactor(hfactor, vfactor)) return -1;
m_jpegFormat = iV4l2JpegFormat;
return 0;
}
-int ExynosJpegEncoder::setColorBufSize(int *piBufSize, int iSize)
-{
+int ExynosJpegEncoder::setColorBufSize(int *piBufSize, int iSize) {
size_t len[3];
unsigned int num = static_cast<unsigned int>(iSize);
- if (!m_hwjpeg.GetImageBufferSizes(len, &num))
- return -1;
+ if (!m_hwjpeg.GetImageBufferSizes(len, &num)) return -1;
- for (unsigned int i = 0; i < num; i++)
- piBufSize[i] = static_cast<int>(len[i]);
+ for (unsigned int i = 0; i < num; i++) piBufSize[i] = static_cast<int>(len[i]);
return 0;
}
bool ExynosJpegEncoder::__EnsureFormatIsApplied() {
if (TestStateEither(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED) &&
- !m_hwjpeg.SetImageFormat(m_v4l2Format, m_nWidth, m_nHeight))
+ !m_hwjpeg.SetImageFormat(m_v4l2Format, m_nWidth, m_nHeight))
return false;
ClearState(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED);
@@ -227,3 +200,7 @@ bool ExynosJpegEncoder::__EnsureFormatIsApplied() {
int ExynosJpegEncoder::setQuality(const unsigned char q_table[]) {
return m_hwjpeg.SetQuality(q_table) ? 0 : -1;
}
+
+int ExynosJpegEncoder::setPadding(unsigned char *padding, unsigned int num_planes) {
+ return m_hwjpeg.SetPadding(padding, num_planes) ? 0 : -1;
+}
diff --git a/libhwjpeg/ExynosJpegEncoderForCamera.cpp b/libhwjpeg/ExynosJpegEncoderForCamera.cpp
index 741e05e..5e003aa 100644
--- a/libhwjpeg/ExynosJpegEncoderForCamera.cpp
+++ b/libhwjpeg/ExynosJpegEncoderForCamera.cpp
@@ -15,29 +15,24 @@
* limitations under the License.
*/
+#include <ExynosJpegEncoderForCamera.h>
+#include <hardware/exynos/ion.h>
+#include <linux/videodev2.h>
#include <sys/mman.h>
#include <sys/types.h>
-
-#include <linux/videodev2.h>
-
-#include <hardware/exynos/ion.h>
#include <system/graphics.h>
-#include <ExynosJpegEncoderForCamera.h>
-
-#include "hwjpeg-internal.h"
#include "AppMarkerWriter.h"
#include "ThumbnailScaler.h"
-#include "IFDWriter.h"
+#include "hwjpeg-internal.h"
// Data length written by H/W without the scan data.
-#define NECESSARY_JPEG_LENGTH (0x24B + 2 * JPEG_MARKER_SIZE)
+#define NECESSARY_JPEG_LENGTH (0x24B + 2 * JPEG_MARKER_SIZE)
-static size_t GetImageLength(unsigned int width, unsigned int height, int v4l2Format)
-{
+static size_t GetImageLength(unsigned int width, unsigned int height, int v4l2Format) {
size_t size = width * height;
- switch(v4l2Format) {
+ switch (v4l2Format) {
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_UYVY:
@@ -57,22 +52,29 @@ static size_t GetImageLength(unsigned int width, unsigned int height, int v4l2Fo
return 0;
}
-static int GetThumbnailFormat(int v4l2Format)
-{
- if (v4l2Format == V4L2_PIX_FMT_NV12M)
- return V4L2_PIX_FMT_NV12;
- else if (v4l2Format == V4L2_PIX_FMT_NV21M)
- return V4L2_PIX_FMT_NV21;
- else
- return v4l2Format;
+static int GetThumbnailFormat(int v4l2Format) {
+ if (v4l2Format == V4L2_PIX_FMT_NV12M)
+ return V4L2_PIX_FMT_NV12;
+ else if (v4l2Format == V4L2_PIX_FMT_NV21M)
+ return V4L2_PIX_FMT_NV21;
+ else
+ return v4l2Format;
}
ExynosJpegEncoderForCamera::ExynosJpegEncoderForCamera(bool bBTBComp)
- : m_phwjpeg4thumb(NULL), m_fdIONClient(-1), m_fdIONThumbImgBuffer(-1), m_pIONThumbImgBuffer(NULL),
- m_szIONThumbImgBuffer(0), m_pIONThumbJpegBuffer(NULL), m_fdIONThumbJpegBuffer(-1), m_szIONThumbJpegBuffer(0),
- m_nThumbWidth(0), m_nThumbHeight(0), m_nThumbQuality(0),
- m_pStreamBase(NULL), m_fThumbBufferType(0)
-{
+ : m_phwjpeg4thumb(NULL),
+ m_fdIONClient(-1),
+ m_fdIONThumbImgBuffer(-1),
+ m_pIONThumbImgBuffer(NULL),
+ m_szIONThumbImgBuffer(0),
+ m_pIONThumbJpegBuffer(NULL),
+ m_fdIONThumbJpegBuffer(-1),
+ m_szIONThumbJpegBuffer(0),
+ m_nThumbWidth(0),
+ m_nThumbHeight(0),
+ m_nThumbQuality(0),
+ m_pStreamBase(NULL),
+ m_fThumbBufferType(0) {
m_pAppWriter = new CAppMarkerWriter();
if (!m_pAppWriter) {
ALOGE("Failed to allocated an instance of CAppMarkerWriter");
@@ -94,52 +96,41 @@ ExynosJpegEncoderForCamera::ExynosJpegEncoderForCamera(bool bBTBComp)
ALOGERR("Failed to create ION client for thumbnail conversion");
}
- if (!bBTBComp)
- SetState(STATE_NO_BTBCOMP);
+ if (!bBTBComp) SetState(STATE_NO_BTBCOMP);
// STATE_THUMBSIZE_CHANGED is to know if thumbnail image size need to be
// configured to HWJPEG. If HWJPEG does not support for back-to-back
// compression, it should not be configured.
- if (IsBTBCompressionSupported())
- SetState(STATE_THUMBSIZE_CHANGED);
+ if (IsBTBCompressionSupported()) SetState(STATE_THUMBSIZE_CHANGED);
m_extraInfo.appInfo = m_appInfo;
mThumbnailScaler.reset(ThumbnailScaler::createInstance());
- if (!mThumbnailScaler->available())
- ALOGW("Thumbnail scaler is not available.");
+ if (!mThumbnailScaler->available()) ALOGW("Thumbnail scaler is not available.");
ALOGD("ExynosJpegEncoderForCamera Created: %p, ION %d", this, m_fdIONClient);
}
-ExynosJpegEncoderForCamera::~ExynosJpegEncoderForCamera()
-{
+ExynosJpegEncoderForCamera::~ExynosJpegEncoderForCamera() {
delete m_pAppWriter;
delete m_phwjpeg4thumb;
- if (m_pIONThumbImgBuffer != NULL)
- munmap(m_pIONThumbImgBuffer, m_szIONThumbImgBuffer);
+ if (m_pIONThumbImgBuffer != NULL) munmap(m_pIONThumbImgBuffer, m_szIONThumbImgBuffer);
- if (m_fdIONThumbImgBuffer >= 0)
- close(m_fdIONThumbImgBuffer);
+ if (m_fdIONThumbImgBuffer >= 0) close(m_fdIONThumbImgBuffer);
- if (m_pIONThumbJpegBuffer)
- munmap(m_pIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
+ if (m_pIONThumbJpegBuffer) munmap(m_pIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
- if (m_fdIONThumbJpegBuffer >= 0)
- close(m_fdIONThumbJpegBuffer);
+ if (m_fdIONThumbJpegBuffer >= 0) close(m_fdIONThumbJpegBuffer);
- if (m_fdIONClient >= 0)
- exynos_ion_close(m_fdIONClient);
+ if (m_fdIONClient >= 0) exynos_ion_close(m_fdIONClient);
- ALOGD("ExynosJpegEncoderForCamera Destroyed: %p, ION %d, ThumIMG %d",
- this, m_fdIONClient, m_fdIONThumbImgBuffer);
+ ALOGD("ExynosJpegEncoderForCamera Destroyed: %p, ION %d, ThumIMG %d", this, m_fdIONClient,
+ m_fdIONThumbImgBuffer);
}
-int ExynosJpegEncoderForCamera::setThumbnailSize(int w, int h)
-{
- if ((m_nThumbWidth == w) && (m_nThumbHeight == h))
- return 0;
+int ExynosJpegEncoderForCamera::setThumbnailSize(int w, int h) {
+ if ((m_nThumbWidth == w) && (m_nThumbHeight == h)) return 0;
// w == 0 and h == 0 resets thumbnail configuration
if (((w | h) != 0) && ((w < 16) || (h < 16))) {
@@ -150,16 +141,13 @@ int ExynosJpegEncoderForCamera::setThumbnailSize(int w, int h)
m_nThumbWidth = w;
m_nThumbHeight = h;
- if (IsBTBCompressionSupported())
- SetState(STATE_THUMBSIZE_CHANGED);
+ if (IsBTBCompressionSupported()) SetState(STATE_THUMBSIZE_CHANGED);
return 0;
}
-int ExynosJpegEncoderForCamera::setThumbnailQuality(int quality)
-{
- if (m_nThumbQuality == quality)
- return 0;
+int ExynosJpegEncoderForCamera::setThumbnailQuality(int quality) {
+ if (m_nThumbQuality == quality) return 0;
if ((quality > 100) || (quality < 1)) {
ALOGE("Invalid quality factor %d for thumbnail image", quality);
@@ -171,6 +159,11 @@ int ExynosJpegEncoderForCamera::setThumbnailQuality(int quality)
return GetCompressor().SetQuality(0, m_nThumbQuality) ? 0 : -1;
}
+int ExynosJpegEncoderForCamera::setThumbnailPadding(unsigned char *padding,
+ unsigned int num_planes) {
+ return GetCompressor().SetPadding2(padding, num_planes) ? 0 : -1;
+}
+
bool ExynosJpegEncoderForCamera::EnsureFormatIsApplied() {
if (TestStateEither(STATE_PIXFMT_CHANGED | STATE_SIZE_CHANGED | STATE_THUMBSIZE_CHANGED)) {
int thumb_width = m_nThumbWidth;
@@ -184,8 +177,8 @@ bool ExynosJpegEncoderForCamera::EnsureFormatIsApplied() {
}
getSize(&width, &height);
- if (!GetCompressor().SetImageFormat(
- getColorFormat(), width, height, thumb_width, thumb_height))
+ if (!GetCompressor().SetImageFormat(getColorFormat(), width, height, thumb_width,
+ thumb_height))
return false;
ClearState(STATE_PIXFMT_CHANGED | STATE_SIZE_CHANGED | STATE_THUMBSIZE_CHANGED);
@@ -194,8 +187,7 @@ bool ExynosJpegEncoderForCamera::EnsureFormatIsApplied() {
return true;
}
-size_t ExynosJpegEncoderForCamera::RemoveTrailingDummies(char *base, size_t len)
-{
+size_t ExynosJpegEncoderForCamera::RemoveTrailingDummies(char *base, size_t len) {
ALOG_ASSERT(len > 4);
ALOG_ASSERT((base[0] == 0xFF) && (base[1] == 0xD8)); // SOI marker
@@ -215,18 +207,15 @@ size_t ExynosJpegEncoderForCamera::RemoveTrailingDummies(char *base, size_t len)
return 0;
}
-void *ExynosJpegEncoderForCamera::tCompressThumbnail(void *p)
-{
+void *ExynosJpegEncoderForCamera::tCompressThumbnail(void *p) {
ExynosJpegEncoderForCamera *encoder = reinterpret_cast<ExynosJpegEncoderForCamera *>(p);
size_t thumblen = encoder->CompressThumbnail();
return reinterpret_cast<void *>(thumblen);
}
-bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit,
- exif_attribute_t *exifInfo,
- extra_appinfo_t *extra)
-{
+bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit, exif_attribute_t *exifInfo,
+ extra_appinfo_t *extra) {
// PREREQUISITES: The main and the thumbnail image size should be configured before.
// Sanity chck
@@ -237,16 +226,16 @@ bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit,
if (exifInfo) {
if ((exifInfo->width != width) || (exifInfo->height != height)) {
- ALOGE("Inconsistant image dimension: Exif %dx%d, Thumb %dx%d",
- exifInfo->width, exifInfo->height, width, height);
+ ALOGE("Inconsistent image dimension: Exif %dx%d, Thumb %dx%d", exifInfo->width,
+ exifInfo->height, width, height);
return false;
}
if (exifInfo->enableThumb) {
if ((exifInfo->widthThumb != static_cast<uint32_t>(m_nThumbWidth)) ||
- (exifInfo->heightThumb != static_cast<uint32_t>(m_nThumbHeight))) {
- ALOGE("Inconsistant thumbnail information: Exif %dx%d, Thumb %dx%d",
- exifInfo->widthThumb, exifInfo->heightThumb, m_nThumbWidth, m_nThumbHeight);
+ (exifInfo->heightThumb != static_cast<uint32_t>(m_nThumbHeight))) {
+ ALOGE("Inconsistent thumbnail information: Exif %dx%d, Thumb %dx%d",
+ exifInfo->widthThumb, exifInfo->heightThumb, m_nThumbWidth, m_nThumbHeight);
return false;
}
}
@@ -255,8 +244,7 @@ bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit,
// Giving appwriter the address beyond SOS marker
// because it is handled by this class
size_t align = 16;
- if (!!(GetDeviceCapabilities() & V4L2_CAP_EXYNOS_JPEG_NO_STREAMBASE_ALIGN))
- align = 1;
+ if (!!(GetDeviceCapabilities() & V4L2_CAP_EXYNOS_JPEG_NO_STREAMBASE_ALIGN)) align = 1;
m_pAppWriter->PrepareAppWriter(base + JPEG_MARKER_SIZE, exifInfo, extra);
@@ -280,24 +268,21 @@ bool ExynosJpegEncoderForCamera::ProcessExif(char *base, size_t limit,
if (!exifInfo || !exifInfo->enableThumb || (limit < (JPEG_MAX_SEGMENT_SIZE * 10)))
reserve_thumbspace = false;
- m_pAppWriter->Write(reserve_thumbspace, JPEG_MARKER_SIZE, align,
- TestState(STATE_HWFC_ENABLED));
+ m_pAppWriter->Write(reserve_thumbspace, JPEG_MARKER_SIZE, align, TestState(STATE_HWFC_ENABLED));
ALOGD("Image compression starts from offset %zu (APPx size %zu, HWFC? %d, NBTB? %d)",
- PTR_DIFF(base, m_pAppWriter->GetMainStreamBase()), m_pAppWriter->CalculateAPPSize(),
- TestState(STATE_HWFC_ENABLED),TestState(STATE_NO_BTBCOMP));
+ PTR_DIFF(base, m_pAppWriter->GetMainStreamBase()), m_pAppWriter->CalculateAPPSize(),
+ TestState(STATE_HWFC_ENABLED), TestState(STATE_NO_BTBCOMP));
return true;
}
-bool ExynosJpegEncoderForCamera::PrepareCompression(bool thumbnail)
-{
- if (!thumbnail)
- return true;
+bool ExynosJpegEncoderForCamera::PrepareCompression(bool thumbnail) {
+ if (!thumbnail) return true;
if (IsThumbGenerationNeeded()) {
- if (pthread_create(&m_threadWorker, NULL,
- tCompressThumbnail, reinterpret_cast<void *>(this)) != 0) {
+ if (pthread_create(&m_threadWorker, NULL, tCompressThumbnail,
+ reinterpret_cast<void *>(this)) != 0) {
ALOGERR("Failed to create thumbnail generation thread");
return false;
}
@@ -312,14 +297,14 @@ bool ExynosJpegEncoderForCamera::PrepareCompression(bool thumbnail)
if (!TestState(STATE_NO_BTBCOMP) && IsBTBCompressionSupported()) {
if (checkOutBufType() == JPEG_BUF_TYPE_USER_PTR) {
if (!GetCompressor().SetJpegBuffer2(m_pIONThumbJpegBuffer, m_szIONThumbJpegBuffer)) {
- ALOGE("Failed to configure thumbnail buffer @ %p(size %zu)",
- m_pIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
+ ALOGE("Failed to configure thumbnail buffer @ %p(size %zu)", m_pIONThumbJpegBuffer,
+ m_szIONThumbJpegBuffer);
return false;
}
} else {
if (!GetCompressor().SetJpegBuffer2(m_fdIONThumbJpegBuffer, m_szIONThumbJpegBuffer)) {
- ALOGE("Failed to configure thumbnail buffer @ %d(size %zu)",
- m_fdIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
+ ALOGE("Failed to configure thumbnail buffer @ %d(size %zu)", m_fdIONThumbJpegBuffer,
+ m_szIONThumbJpegBuffer);
return false;
}
}
@@ -328,16 +313,13 @@ bool ExynosJpegEncoderForCamera::PrepareCompression(bool thumbnail)
return true;
}
-int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
- char** pcJpegBuffer, debug_attribute_t *debugInfo)
-{
+int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo, char **pcJpegBuffer,
+ debug_attribute_t *debugInfo) {
return encode(size, exifInfo, -1, pcJpegBuffer, debugInfo);
}
-int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
- int fdJpegBuffer, char** pcJpegBuffer,
- debug_attribute_t *debugInfo)
-{
+int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer,
+ char **pcJpegBuffer, debug_attribute_t *debugInfo) {
if ((!debugInfo) || (debugInfo->num_of_appmarker == 0)) {
extra_appinfo_t *extra = NULL;
return encode(size, exifInfo, fdJpegBuffer, pcJpegBuffer, extra);
@@ -351,10 +333,8 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
return encode(size, exifInfo, fdJpegBuffer, pcJpegBuffer, &m_extraInfo);
}
-int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
- int fdJpegBuffer, char** pcJpegBuffer,
- extra_appinfo_t *appInfo)
-{
+int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer,
+ char **pcJpegBuffer, extra_appinfo_t *appInfo) {
if (!(*pcJpegBuffer)) {
ALOGE("Target stream buffer is not specified");
return -1;
@@ -371,27 +351,26 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
char *jpeg_base = m_pStreamBase;
ALOGI_IF(!exifInfo, "Exif is not specified. Skipping writing APP1 marker");
- ALOGI_IF(!appInfo,
- "Debugging information is not specified. Skipping writing APP4 marker");
+ ALOGI_IF(!appInfo, "Debugging information is not specified. Skipping writing APP4 marker");
ALOGD("Given stream buffer size: %d bytes", *size);
CStopWatch stopwatch(true);
- if (!ProcessExif(jpeg_base, m_nStreamSize, exifInfo, appInfo))
- return -1;
+ if (!ProcessExif(jpeg_base, m_nStreamSize, exifInfo, appInfo)) return -1;
int offset = PTR_DIFF(m_pStreamBase, m_pAppWriter->GetMainStreamBase());
int buffsize = static_cast<int>(m_nStreamSize - offset);
- if ((fdJpegBuffer < 0) || !(GetDeviceCapabilities() & V4L2_CAP_EXYNOS_JPEG_DMABUF_OFFSET)) { // JPEG_BUF_TYPE_USER_PTR
+ if ((fdJpegBuffer < 0) ||
+ !(GetDeviceCapabilities() & V4L2_CAP_EXYNOS_JPEG_DMABUF_OFFSET)) { // JPEG_BUF_TYPE_USER_PTR
if (setOutBuf(m_pAppWriter->GetMainStreamBase(), buffsize) < 0) {
- ALOGE("Failed to configure stream buffer : fd %d, addr %p, streamSize %d",
- fdJpegBuffer, m_pAppWriter->GetMainStreamBase(), buffsize);
+ ALOGE("Failed to configure stream buffer : fd %d, addr %p, streamSize %d", fdJpegBuffer,
+ m_pAppWriter->GetMainStreamBase(), buffsize);
return -1;
}
} else { // JPEG_BUF_TYPE_DMA_BUF
if (setOutBuf(fdJpegBuffer, buffsize, offset) < 0) {
- ALOGE("Failed to configure stream buffer : fd %d, addr %p, streamSize %d",
- fdJpegBuffer, m_pAppWriter->GetMainStreamBase(), buffsize);
+ ALOGE("Failed to configure stream buffer : fd %d, addr %p, streamSize %d", fdJpegBuffer,
+ m_pAppWriter->GetMainStreamBase(), buffsize);
return -1;
}
}
@@ -412,10 +391,10 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
// CASE1 = thumbenc && IsThumbGenerationNeeded() && block_mode
// CASE2 = thumbenc && IsThumbGenerationNeeded() && !block_mode
// CASE3 = thumbenc && !IsThumbGenerationNeeded() && !IsBTBCompressionSupported() && !block_mode
- // CASE4 = thumbenc && !IsThumbGenerationNeeded() && !STATE_NO_BTBCOMP && IsBTBCompressionSupported() && !block_mode
- // CASE5 = thumbenc && !IsThumbGenerationNeeded() && !STATE_NO_BTBCOMP && IsBTBCompressionSupported() && block_mode
- // CASE6 = !thumbenc
- // CASE7 = thumbenc && !IsThumbGenerationNeeded() && STATE_NO_BTBCOMP && block_mode
+ // CASE4 = thumbenc && !IsThumbGenerationNeeded() && !STATE_NO_BTBCOMP &&
+ // IsBTBCompressionSupported() && !block_mode CASE5 = thumbenc && !IsThumbGenerationNeeded() &&
+ // !STATE_NO_BTBCOMP && IsBTBCompressionSupported() && block_mode CASE6 = !thumbenc CASE7 =
+ // thumbenc && !IsThumbGenerationNeeded() && STATE_NO_BTBCOMP && block_mode
if (!thumbenc) {
// Confirm that no thumbnail information is transferred to HWJPEG
@@ -423,7 +402,7 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
} else if (!IsThumbGenerationNeeded() && IsBTBCompressionSupported() &&
(m_fThumbBufferType != checkInBufType())) {
ALOGE("Buffer types of thumbnail(%d) and main(%d) images should be the same",
- m_fThumbBufferType, checkInBufType());
+ m_fThumbBufferType, checkInBufType());
return -1;
} else if (!IsThumbGenerationNeeded() && (m_fThumbBufferType == 0)) {
// Thumbnail buffer configuration failed but the client forces to compress with thumbnail
@@ -453,17 +432,14 @@ int ExynosJpegEncoderForCamera::encode(int *size, exif_attribute_t *exifInfo,
}
*size = static_cast<int>(FinishCompression(mainlen, thumblen));
- if (*size < 0)
- return -1;
+ if (*size < 0) return -1;
- ALOGD("....compression delay(usec.): HW %u, Total %lu)",
- GetHWDelay(), stopwatch.GetElapsed());
+ ALOGD("....compression delay(usec.): HW %u, Total %lu)", GetHWDelay(), stopwatch.GetElapsed());
return 0;
}
-ssize_t ExynosJpegEncoderForCamera::FinishCompression(size_t mainlen, size_t thumblen)
-{
+ssize_t ExynosJpegEncoderForCamera::FinishCompression(size_t mainlen, size_t thumblen) {
bool btb = false;
size_t max_streamsize = m_nStreamSize;
char *mainbase = m_pAppWriter->GetMainStreamBase();
@@ -491,33 +467,37 @@ ssize_t ExynosJpegEncoderForCamera::FinishCompression(size_t mainlen, size_t thu
thumblen = reinterpret_cast<size_t>(len);
} else if (TestState(STATE_NO_BTBCOMP) || !IsBTBCompressionSupported()) {
- thumblen = CompressThumbnailOnly(m_pAppWriter->GetMaxThumbnailSize(), m_nThumbQuality, getColorFormat(), checkInBufType());
+ thumblen = CompressThumbnailOnly(m_pAppWriter->GetMaxThumbnailSize(), m_nThumbQuality,
+ getColorFormat(), checkInBufType());
} else {
btb = true;
}
- size_t max_thumb = min(m_pAppWriter->GetMaxThumbnailSize(), max_streamsize - m_pAppWriter->CalculateAPPSize(0) - mainlen);
+ size_t max_thumb = min(m_pAppWriter->GetMaxThumbnailSize(),
+ max_streamsize - m_pAppWriter->CalculateAPPSize(0) - mainlen);
if (thumblen > max_thumb) {
ALOGI("Too large thumbnail (%dx%d) stream size %zu (max: %zu, quality factor %d)",
m_nThumbWidth, m_nThumbHeight, thumblen, max_thumb, m_nThumbQuality);
ALOGI("Retrying thumbnail compression with quality factor 50");
thumblen = CompressThumbnailOnly(max_thumb, 50, getColorFormat(), checkInBufType());
- if (thumblen == 0)
- return -1;
+ if (thumblen == 0) return -1;
}
if (!m_pAppWriter->IsThumbSpaceReserved()) {
if (PTR_TO_ULONG(m_pStreamBase + max_streamsize) <
- PTR_TO_ULONG(mainbase + mainlen + thumblen - JPEG_MARKER_SIZE)) {
+ PTR_TO_ULONG(mainbase + mainlen + thumblen - JPEG_MARKER_SIZE)) {
ALOGE("Too small JPEG buffer length %zu (APP %zu, Main %zu, Thumb %zu)",
max_streamsize, m_pAppWriter->CalculateAPPSize(thumblen), mainlen, thumblen);
return -1;
}
- // the SOI of the stream of the main image is stored after the APP4 or APP11 segment if they exist.
+ // the SOI of the stream of the main image is stored after the APP4 or APP11 segment if
+ // they exist.
memmove(m_pAppWriter->GetApp1End() + thumblen, m_pAppWriter->GetApp1End(),
- mainlen + PTR_DIFF(m_pAppWriter->GetApp1End(), m_pAppWriter->GetMainStreamBase()));
+ mainlen +
+ PTR_DIFF(m_pAppWriter->GetApp1End(),
+ m_pAppWriter->GetMainStreamBase()));
m_pAppWriter->UpdateApp1Size(thumblen);
// m_nAppLength has the value of appwriter.GetExactAPPSize()
@@ -532,7 +512,8 @@ ssize_t ExynosJpegEncoderForCamera::FinishCompression(size_t mainlen, size_t thu
if (m_pAppWriter->IsThumbSpaceReserved()) {
// clear the possible stale data in the dummy area after the thumbnail stream
memset(m_pAppWriter->GetThumbStreamBase() + thumblen, 0,
- m_pAppWriter->GetMaxThumbnailSize() - thumblen + m_pAppWriter->GetAPP1ResrevedSize());
+ m_pAppWriter->GetMaxThumbnailSize() - thumblen +
+ m_pAppWriter->GetAPP1ResrevedSize());
}
} else {
thumblen = 0;
@@ -546,8 +527,8 @@ ssize_t ExynosJpegEncoderForCamera::FinishCompression(size_t mainlen, size_t thu
* Note that 2 byte(size of SOI marker) is included in APP1 segment size.
* Thus the size of SOI marker in front of the stream is not added.
*/
- ALOGD("Completed image compression (%zd(thumb %zu) bytes, HWFC? %d, BTB? %d)",
- mainlen, thumblen, TestState(STATE_HWFC_ENABLED), btb);
+ ALOGD("Completed image compression (%zd(thumb %zu) bytes, HWFC? %d, BTB? %d)", mainlen,
+ thumblen, TestState(STATE_HWFC_ENABLED), btb);
m_pStreamBase[0] = 0xFF;
m_pStreamBase[1] = 0xD8;
@@ -556,21 +537,17 @@ ssize_t ExynosJpegEncoderForCamera::FinishCompression(size_t mainlen, size_t thu
}
/* The logic in WaitForHWFC() is the same with encode() */
-ssize_t ExynosJpegEncoderForCamera::WaitForCompression()
-{
- if (!TestState(STATE_HWFC_ENABLED))
- return m_nStreamSize;
+ssize_t ExynosJpegEncoderForCamera::WaitForCompression() {
+ if (!TestState(STATE_HWFC_ENABLED)) return m_nStreamSize;
size_t thumblen = 0;
ssize_t streamlen = GetCompressor().WaitForCompression(&thumblen);
- if (streamlen < 0)
- return streamlen;
+ if (streamlen < 0) return streamlen;
return FinishCompression(streamlen, thumblen);
}
-bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
-{
+bool ExynosJpegEncoderForCamera::GenerateThumbnailImage() {
int main_width, main_height;
if (getSize(&main_width, &main_height) < 0) {
ALOGE("Failed to get main image size");
@@ -579,11 +556,10 @@ bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
int v4l2Format = getColorFormat();
- if (!AllocThumbBuffer(v4l2Format))
- return false;
+ if (!AllocThumbBuffer(v4l2Format)) return false;
- ALOGD("Generating thumbnail image: %dx%d -> %dx%d",
- main_width, main_height, m_nThumbWidth, m_nThumbHeight);
+ ALOGD("Generating thumbnail image: %dx%d -> %dx%d", main_width, main_height, m_nThumbWidth,
+ m_nThumbHeight);
if (!mThumbnailScaler) {
ALOGE("Thumbnail scaler is not prepared");
@@ -595,8 +571,8 @@ bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
return false;
}
-
- if (!mThumbnailScaler->SetDstImage(m_nThumbWidth, m_nThumbHeight, GetThumbnailFormat(v4l2Format))) {
+ if (!mThumbnailScaler->SetDstImage(m_nThumbWidth, m_nThumbHeight,
+ GetThumbnailFormat(v4l2Format))) {
ALOGE("Failed to configure the target image to the thumbnail scaler");
return false;
}
@@ -612,7 +588,8 @@ bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
return false;
}
- okay = mThumbnailScaler->RunStream(bufs, len_srcbufs, m_fdIONThumbImgBuffer, m_szIONThumbImgBuffer);
+ okay = mThumbnailScaler->RunStream(bufs, len_srcbufs, m_fdIONThumbImgBuffer,
+ m_szIONThumbImgBuffer);
} else { // mainbuftype == JPEG_BUF_TYPE_DMA_BUF
int bufs[ThumbnailScaler::SCALER_MAX_PLANES];
int len_srcbufs[ThumbnailScaler::SCALER_MAX_PLANES];
@@ -621,7 +598,8 @@ bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
ALOGE("Failed to retrieve the main image buffers");
return false;
}
- okay = mThumbnailScaler->RunStream(bufs, len_srcbufs, m_fdIONThumbImgBuffer, m_szIONThumbImgBuffer);
+ okay = mThumbnailScaler->RunStream(bufs, len_srcbufs, m_fdIONThumbImgBuffer,
+ m_szIONThumbImgBuffer);
}
if (!okay) {
@@ -632,14 +610,12 @@ bool ExynosJpegEncoderForCamera::GenerateThumbnailImage()
return true;
}
-size_t ExynosJpegEncoderForCamera::CompressThumbnail()
-{
+size_t ExynosJpegEncoderForCamera::CompressThumbnail() {
unsigned int v4l2Format = getColorFormat();
int buftype = checkInBufType();
if (IsThumbGenerationNeeded()) {
- if (!GenerateThumbnailImage())
- return 0;
+ if (!GenerateThumbnailImage()) return 0;
// libcsc output configured by this class is always NV21.
v4l2Format = GetThumbnailFormat(getColorFormat());
@@ -650,11 +626,11 @@ size_t ExynosJpegEncoderForCamera::CompressThumbnail()
m_szThumbnailImageLen[0] = m_szIONThumbImgBuffer;
}
- return CompressThumbnailOnly(m_pAppWriter->GetMaxThumbnailSize(), m_nThumbQuality, v4l2Format, buftype);
+ return CompressThumbnailOnly(m_pAppWriter->GetMaxThumbnailSize(), m_nThumbQuality, v4l2Format,
+ buftype);
}
-bool ExynosJpegEncoderForCamera::AllocThumbBuffer(int v4l2Format)
-{
+bool ExynosJpegEncoderForCamera::AllocThumbBuffer(int v4l2Format) {
if (m_fdIONClient < 0) {
ALOGE("ION client is not created");
return false;
@@ -667,11 +643,9 @@ bool ExynosJpegEncoderForCamera::AllocThumbBuffer(int v4l2Format)
}
if (m_fdIONThumbImgBuffer >= 0) {
- if (m_szIONThumbImgBuffer >= thumbbufsize)
- return true;
+ if (m_szIONThumbImgBuffer >= thumbbufsize) return true;
- if (m_pIONThumbImgBuffer != NULL)
- munmap(m_pIONThumbImgBuffer, m_szIONThumbImgBuffer);
+ if (m_pIONThumbImgBuffer != NULL) munmap(m_pIONThumbImgBuffer, m_szIONThumbImgBuffer);
close(m_fdIONThumbImgBuffer);
@@ -680,9 +654,11 @@ bool ExynosJpegEncoderForCamera::AllocThumbBuffer(int v4l2Format)
m_szIONThumbImgBuffer = 0;
}
- m_fdIONThumbImgBuffer = exynos_ion_alloc(m_fdIONClient, thumbbufsize, EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
+ m_fdIONThumbImgBuffer =
+ exynos_ion_alloc(m_fdIONClient, thumbbufsize, EXYNOS_ION_HEAP_SYSTEM_MASK, 0);
if (m_fdIONThumbImgBuffer < 0) {
- ALOGERR("Failed to allocate %zu bytes for NV12 %ux%u", thumbbufsize, m_nThumbHeight, m_nThumbWidth);
+ ALOGERR("Failed to allocate %zu bytes for NV12 %ux%u", thumbbufsize, m_nThumbHeight,
+ m_nThumbWidth);
m_fdIONThumbImgBuffer = -1;
return false;
}
@@ -692,8 +668,7 @@ bool ExynosJpegEncoderForCamera::AllocThumbBuffer(int v4l2Format)
return AllocThumbJpegBuffer();
}
-bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer()
-{
+bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer() {
if (m_fdIONClient < 0) {
ALOGE("ION client is not created");
return false;
@@ -702,8 +677,7 @@ bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer()
size_t thumbbufsize = m_nThumbHeight * m_nThumbWidth * 3;
if (m_pIONThumbJpegBuffer) {
- if (m_szIONThumbJpegBuffer >= thumbbufsize)
- return true;
+ if (m_szIONThumbJpegBuffer >= thumbbufsize) return true;
munmap(m_pIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
close(m_fdIONThumbJpegBuffer);
@@ -713,16 +687,18 @@ bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer()
m_fdIONThumbJpegBuffer = -1;
}
- m_fdIONThumbJpegBuffer = exynos_ion_alloc(m_fdIONClient, thumbbufsize, EXYNOS_ION_HEAP_SYSTEM_MASK,
- ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC);
+ m_fdIONThumbJpegBuffer =
+ exynos_ion_alloc(m_fdIONClient, thumbbufsize, EXYNOS_ION_HEAP_SYSTEM_MASK,
+ ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC);
if (m_fdIONThumbJpegBuffer < 0) {
- ALOGERR("Failed to allocate %zu bytes for thumbnail stream buffer of %ux%u",
- thumbbufsize, m_nThumbHeight, m_nThumbWidth);
+ ALOGERR("Failed to allocate %zu bytes for thumbnail stream buffer of %ux%u", thumbbufsize,
+ m_nThumbHeight, m_nThumbWidth);
return false;
}
- m_pIONThumbJpegBuffer = reinterpret_cast<char *>(
- mmap(NULL, thumbbufsize, PROT_READ | PROT_WRITE, MAP_SHARED, m_fdIONThumbJpegBuffer, 0));
+ m_pIONThumbJpegBuffer =
+ reinterpret_cast<char *>(mmap(NULL, thumbbufsize, PROT_READ | PROT_WRITE, MAP_SHARED,
+ m_fdIONThumbJpegBuffer, 0));
if (m_pIONThumbJpegBuffer == MAP_FAILED) {
ALOGERR("Failed to map thumbnail stream buffer (%zu bytes)", thumbbufsize);
@@ -735,11 +711,10 @@ bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer()
}
size_t ExynosJpegEncoderForCamera::CompressThumbnailOnly(size_t limit, int quality,
- unsigned int v4l2Format, int src_buftype)
-{
+ unsigned int v4l2Format, int src_buftype) {
if (!m_phwjpeg4thumb->SetImageFormat(v4l2Format, m_nThumbWidth, m_nThumbHeight)) {
- ALOGE("Failed to configure thumbnail source image format to %#010x, %ux%u",
- v4l2Format, m_nThumbWidth, m_nThumbHeight);
+ ALOGE("Failed to configure thumbnail source image format to %#010x, %ux%u", v4l2Format,
+ m_nThumbWidth, m_nThumbHeight);
return 0;
}
@@ -754,18 +729,18 @@ size_t ExynosJpegEncoderForCamera::CompressThumbnailOnly(size_t limit, int quali
[[fallthrough]];
case V4L2_PIX_FMT_NV21M:
num_buffers++;
- break;
+ break;
}
if (src_buftype == JPEG_BUF_TYPE_USER_PTR) {
- if (!m_phwjpeg4thumb->SetImageBuffer(m_pThumbnailImageBuffer,
- m_szThumbnailImageLen, num_buffers)) {
+ if (!m_phwjpeg4thumb->SetImageBuffer(m_pThumbnailImageBuffer, m_szThumbnailImageLen,
+ num_buffers)) {
ALOGE("Failed to configure thumbnail buffers(userptr) for thumbnail");
return 0;
}
} else { // JPEG_BUF_TYPE_DMA_BUF
- if (!m_phwjpeg4thumb->SetImageBuffer(m_fdThumbnailImageBuffer,
- m_szThumbnailImageLen, num_buffers)) {
+ if (!m_phwjpeg4thumb->SetImageBuffer(m_fdThumbnailImageBuffer, m_szThumbnailImageLen,
+ num_buffers)) {
ALOGE("Failed to configure thumbnail buffers(dmabuf) for thumbnail");
return 0;
}
@@ -773,7 +748,7 @@ size_t ExynosJpegEncoderForCamera::CompressThumbnailOnly(size_t limit, int quali
if (!m_phwjpeg4thumb->SetJpegBuffer(m_fdIONThumbJpegBuffer, m_szIONThumbJpegBuffer)) {
ALOGE("Failed to configure thumbnail stream buffer (fd %d, size %zu)",
- m_fdIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
+ m_fdIONThumbJpegBuffer, m_szIONThumbJpegBuffer);
return 0;
}
@@ -811,12 +786,10 @@ size_t ExynosJpegEncoderForCamera::CompressThumbnailOnly(size_t limit, int quali
return 0;
}
-int ExynosJpegEncoderForCamera::setInBuf2(int *piBuf, int *iSize)
-{
+int ExynosJpegEncoderForCamera::setInBuf2(int *piBuf, int *iSize) {
NoThumbGenerationNeeded();
- if (!EnsureFormatIsApplied())
- return -1;
+ if (!EnsureFormatIsApplied()) return -1;
CHWJpegCompressor &hwjpeg = GetCompressor();
unsigned int num_buffers = 3;
@@ -831,7 +804,7 @@ int ExynosJpegEncoderForCamera::setInBuf2(int *piBuf, int *iSize)
}
if (IsBTBCompressionSupported() &&
- !hwjpeg.SetImageBuffer2(m_fdThumbnailImageBuffer, m_szThumbnailImageLen, num_buffers)) {
+ !hwjpeg.SetImageBuffer2(m_fdThumbnailImageBuffer, m_szThumbnailImageLen, num_buffers)) {
ALOGE("Failed to configure thumbnail buffers");
return -1;
}
@@ -841,12 +814,10 @@ int ExynosJpegEncoderForCamera::setInBuf2(int *piBuf, int *iSize)
return 0;
}
-int ExynosJpegEncoderForCamera::setInBuf2(char **pcBuf, int *iSize)
-{
+int ExynosJpegEncoderForCamera::setInBuf2(char **pcBuf, int *iSize) {
NoThumbGenerationNeeded();
- if (!EnsureFormatIsApplied())
- return -1;
+ if (!EnsureFormatIsApplied()) return -1;
CHWJpegCompressor &hwjpeg = GetCompressor();
unsigned int num_buffers = 3;
@@ -861,7 +832,7 @@ int ExynosJpegEncoderForCamera::setInBuf2(char **pcBuf, int *iSize)
}
if (IsBTBCompressionSupported() &&
- !hwjpeg.SetImageBuffer2(m_pThumbnailImageBuffer, m_szThumbnailImageLen, num_buffers)) {
+ !hwjpeg.SetImageBuffer2(m_pThumbnailImageBuffer, m_szThumbnailImageLen, num_buffers)) {
ALOGE("Failed to configure thumbnail buffers");
return -1;
}
@@ -871,8 +842,7 @@ int ExynosJpegEncoderForCamera::setInBuf2(char **pcBuf, int *iSize)
return 0;
}
-size_t ExynosJpegEncoderForCamera::GetThumbnailImage(char *buffer, size_t buflen)
-{
+size_t ExynosJpegEncoderForCamera::GetThumbnailImage(char *buffer, size_t buflen) {
if (m_fdIONThumbImgBuffer < 0) {
ALOGE("No internal thumbnail buffer is allocated");
return 0;
@@ -888,8 +858,8 @@ size_t ExynosJpegEncoderForCamera::GetThumbnailImage(char *buffer, size_t buflen
"m_szIONThumbImgBuffer(%zu) is smaller than the thumbnail (%zu)",
m_szIONThumbImgBuffer, thumbbufsize);
if (m_pIONThumbImgBuffer == NULL) {
- m_pIONThumbImgBuffer = reinterpret_cast<char *>(mmap(
- NULL, m_szIONThumbImgBuffer, PROT_READ, MAP_SHARED, m_fdIONThumbImgBuffer, 0));
+ m_pIONThumbImgBuffer = reinterpret_cast<char *>(
+ mmap(NULL, m_szIONThumbImgBuffer, PROT_READ, MAP_SHARED, m_fdIONThumbImgBuffer, 0));
if (m_pIONThumbImgBuffer == MAP_FAILED) {
m_pIONThumbImgBuffer = NULL;
ALOGERR("Failed to map thumbnail image buffer (%zu bytes)", m_szIONThumbImgBuffer);
@@ -904,8 +874,7 @@ size_t ExynosJpegEncoderForCamera::GetThumbnailImage(char *buffer, size_t buflen
return m_szIONThumbImgBuffer;
}
-int ExynosJpegEncoderForCamera::destroy()
-{
+int ExynosJpegEncoderForCamera::destroy() {
GetCompressor().Release();
return 0;
}
diff --git a/libhwjpeg/FileLock.cpp b/libhwjpeg/FileLock.cpp
new file mode 100644
index 0000000..6e8ecbd
--- /dev/null
+++ b/libhwjpeg/FileLock.cpp
@@ -0,0 +1,13 @@
+#include "FileLock.h"
+
+#include <bits/lockf.h>
+
+FileLock::FileLock(int fd) : fd_(fd) {}
+
+int FileLock::lock() {
+ return lockf(fd_, F_LOCK, 0);
+}
+
+int FileLock::unlock() {
+ return lockf(fd_, F_ULOCK, 0);
+}
diff --git a/libhwjpeg/IFDWriter.h b/libhwjpeg/IFDWriter.h
index 33f7ff8..61e6d17 100644
--- a/libhwjpeg/IFDWriter.h
+++ b/libhwjpeg/IFDWriter.h
@@ -21,6 +21,7 @@
class CEndianessChecker {
bool __little;
+
public:
CEndianessChecker();
operator bool() { return __little; }
@@ -30,8 +31,7 @@ extern CEndianessChecker __LITTLE_ENDIAN__;
#endif
template <typename T>
-char *WriteDataInBig(char *p, T val)
-{
+char *WriteDataInBig(char *p, T val) {
if (sizeof(val) == 1) {
*p++ = val;
} else if (__LITTLE_ENDIAN__) {
@@ -50,7 +50,7 @@ char *WriteDataInBig(char *p, T val)
} else {
switch (sizeof(val)) {
case 2:
- *p++ = static_cast<char>(val & 0xFF);
+ *p++ = static_cast<char>(val & 0xFF);
*p++ = static_cast<char>((val >> 8) & 0xFF);
break;
case 4:
@@ -66,11 +66,9 @@ char *WriteDataInBig(char *p, T val)
}
template <typename T>
-char *WriteData(char *p, T val)
-{
+char *WriteData(char *p, T val) {
const char *pt = reinterpret_cast<char *>(&val);
- for (size_t i = 0; i < sizeof(val); i++)
- *p++ = *pt++;
+ for (size_t i = 0; i < sizeof(val); i++) *p++ = *pt++;
return p;
}
@@ -107,13 +105,14 @@ class CIFDWriter {
m_nTags--;
}
+
public:
CIFDWriter(char *offset_base, char *ifdbase, uint16_t tagcount) {
m_nTags = tagcount;
m_pBase = offset_base;
m_pIFDBase = ifdbase;
- m_pValue = m_pIFDBase + IFD_FIELDCOUNT_SIZE +
- IFD_FIELD_SIZE * tagcount + IFD_NEXTIFDOFFSET_SIZE;
+ m_pValue = m_pIFDBase + IFD_FIELDCOUNT_SIZE + IFD_FIELD_SIZE * tagcount +
+ IFD_NEXTIFDOFFSET_SIZE;
// COUNT field of IFD
const char *pval = reinterpret_cast<char *>(&m_nTags);
@@ -136,8 +135,7 @@ public:
*m_pValue++ = static_cast<char>(value[i]);
}
} else {
- for (uint32_t i = 0; i < count; i++)
- *m_pIFDBase++ = static_cast<char>(value[i]);
+ for (uint32_t i = 0; i < count; i++) *m_pIFDBase++ = static_cast<char>(value[i]);
m_pIFDBase += IFD_VALOFF_SIZE - count;
}
}
@@ -192,8 +190,7 @@ public:
m_pValue[count - 1] = '\0';
m_pValue += count;
} else {
- for (uint32_t i = 0; i < count; i++)
- *m_pIFDBase++ = value[i];
+ for (uint32_t i = 0; i < count; i++) *m_pIFDBase++ = value[i];
*(m_pIFDBase - 1) = '\0';
m_pIFDBase += IFD_VALOFF_SIZE - count;
}
@@ -212,11 +209,9 @@ public:
} else {
uint32_t i;
- for (i = 0; (i < (count - 1)) && (string[i] != '\0'); i++)
- *m_pIFDBase++ = string[i];
+ for (i = 0; (i < (count - 1)) && (string[i] != '\0'); i++) *m_pIFDBase++ = string[i];
- while (i++ < count)
- *m_pIFDBase++ = '\0';
+ while (i++ < count) *m_pIFDBase++ = '\0';
m_pIFDBase += IFD_VALOFF_SIZE - count;
}
@@ -250,8 +245,7 @@ public:
m_pIFDBase = WriteOffset(m_pIFDBase, m_pValue);
const char *pt = reinterpret_cast<const char *>(value);
- for (uint32_t i = 0; i < sizeof(srational_t) * count; i++)
- *m_pValue++ = *pt++;
+ for (uint32_t i = 0; i < sizeof(srational_t) * count; i++) *m_pValue++ = *pt++;
}
void WriteUndef(uint16_t tag, uint32_t count, const unsigned char *value) {
@@ -263,8 +257,7 @@ public:
memcpy(m_pValue, value, count);
m_pValue += count;
} else {
- for (uint32_t i = 0; i < count; i++)
- *m_pIFDBase++ = static_cast<char>(value[i]);
+ for (uint32_t i = 0; i < count; i++) *m_pIFDBase++ = static_cast<char>(value[i]);
m_pIFDBase += IFD_VALOFF_SIZE - count;
}
}
diff --git a/libhwjpeg/LibScalerForJpeg.cpp b/libhwjpeg/LibScalerForJpeg.cpp
index 1165495..1886d49 100644
--- a/libhwjpeg/LibScalerForJpeg.cpp
+++ b/libhwjpeg/LibScalerForJpeg.cpp
@@ -15,67 +15,57 @@
* limitations under the License.
*/
-#include "hwjpeg-internal.h"
#include "LibScalerForJpeg.h"
+#include "hwjpeg-internal.h"
+
#define SCALER_DEV_NODE "/dev/video50"
-static const char *getBufTypeString(unsigned int buftype)
-{
- if (buftype == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
- return "destination";
- if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
- return "source";
+static const char *getBufTypeString(unsigned int buftype) {
+ if (buftype == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return "destination";
+ if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) return "source";
return "unknown";
}
-bool LibScalerForJpeg::RunStream(int srcBuf[SCALER_MAX_PLANES], int __unused srcLen[SCALER_MAX_PLANES], int dstBuf, size_t __unused dstLen)
-{
- if (!mSrcImage.begin(V4L2_MEMORY_DMABUF) || !mDstImage.begin(V4L2_MEMORY_DMABUF))
- return false;
+bool LibScalerForJpeg::RunStream(int srcBuf[SCALER_MAX_PLANES],
+ int __unused srcLen[SCALER_MAX_PLANES], int dstBuf,
+ size_t __unused dstLen) {
+ if (!mSrcImage.begin(V4L2_MEMORY_DMABUF) || !mDstImage.begin(V4L2_MEMORY_DMABUF)) return false;
return queue(srcBuf, dstBuf);
}
-bool LibScalerForJpeg::RunStream(char *srcBuf[SCALER_MAX_PLANES], int __unused srcLen[SCALER_MAX_PLANES], int dstBuf, size_t __unused dstLen)
-{
- if (!mSrcImage.begin(V4L2_MEMORY_USERPTR) || !mDstImage.begin(V4L2_MEMORY_DMABUF))
- return false;
+bool LibScalerForJpeg::RunStream(char *srcBuf[SCALER_MAX_PLANES],
+ int __unused srcLen[SCALER_MAX_PLANES], int dstBuf,
+ size_t __unused dstLen) {
+ if (!mSrcImage.begin(V4L2_MEMORY_USERPTR) || !mDstImage.begin(V4L2_MEMORY_DMABUF)) return false;
return queue(srcBuf, dstBuf);
}
-bool LibScalerForJpeg::Image::set(unsigned int width, unsigned int height, unsigned int format)
-{
- if (same(width, height, format))
- return true;
+bool LibScalerForJpeg::Image::set(unsigned int width, unsigned int height, unsigned int format) {
+ if (same(width, height, format)) return true;
if (memoryType != 0) {
- if (!mDevice.requestBuffers(bufferType, memoryType, 0))
- return false;
+ if (!mDevice.requestBuffers(bufferType, memoryType, 0)) return false;
}
- if (!mDevice.setFormat(bufferType, format, width, height, planeLen))
- return false;
+ if (!mDevice.setFormat(bufferType, format, width, height, planeLen)) return false;
memoryType = 0; // new reqbufs is required.
return true;
}
-bool LibScalerForJpeg::Image::begin(unsigned int memtype)
-{
+bool LibScalerForJpeg::Image::begin(unsigned int memtype) {
if (memoryType != memtype) {
if (memoryType != 0) {
- if (!mDevice.requestBuffers(bufferType, memoryType, 0))
- return false;
+ if (!mDevice.requestBuffers(bufferType, memoryType, 0)) return false;
}
- if (!mDevice.requestBuffers(bufferType, memtype, 1))
- return false;
+ if (!mDevice.requestBuffers(bufferType, memtype, 1)) return false;
- if (!mDevice.streamOn(bufferType))
- return false;
+ if (!mDevice.streamOn(bufferType)) return false;
memoryType = memtype;
}
@@ -83,41 +73,34 @@ bool LibScalerForJpeg::Image::begin(unsigned int memtype)
return true;
}
-bool LibScalerForJpeg::Image::cancelBuffer()
-{
- if (!mDevice.streamOff(bufferType))
- return false;
+bool LibScalerForJpeg::Image::cancelBuffer() {
+ if (!mDevice.streamOff(bufferType)) return false;
- if (!mDevice.streamOn(bufferType))
- return false;
+ if (!mDevice.streamOn(bufferType)) return false;
return true;
}
-LibScalerForJpeg::Device::Device()
-{
+LibScalerForJpeg::Device::Device() {
mFd = ::open(SCALER_DEV_NODE, O_RDWR);
- if (mFd < 0)
- ALOGERR("failed to open %s", SCALER_DEV_NODE);
+ if (mFd < 0) ALOGERR("failed to open %s", SCALER_DEV_NODE);
}
-LibScalerForJpeg::Device::~Device()
-{
- if (mFd >= 0)
- ::close(mFd);
+LibScalerForJpeg::Device::~Device() {
+ if (mFd >= 0) ::close(mFd);
}
-bool LibScalerForJpeg::Device::requestBuffers(unsigned int buftype, unsigned int memtype, unsigned int count)
-{
- // count==0 means this port should be reconfigured and it is successful under streaming is finished.
- if (!count)
- streamOff(buftype);
+bool LibScalerForJpeg::Device::requestBuffers(unsigned int buftype, unsigned int memtype,
+ unsigned int count) {
+ // count==0 means this port should be reconfigured and it is successful under streaming is
+ // finished.
+ if (!count) streamOff(buftype);
v4l2_requestbuffers reqbufs{};
- reqbufs.type = buftype;
- reqbufs.memory = memtype;
- reqbufs.count = count;
+ reqbufs.type = buftype;
+ reqbufs.memory = memtype;
+ reqbufs.count = count;
if (ioctl(mFd, VIDIOC_REQBUFS, &reqbufs) < 0) {
ALOGERR("failed REQBUFS(%s, mem=%d, count=%d)", getBufTypeString(buftype), memtype, count);
@@ -127,29 +110,30 @@ bool LibScalerForJpeg::Device::requestBuffers(unsigned int buftype, unsigned int
return true;
}
-bool LibScalerForJpeg::Device::setFormat(unsigned int buftype, unsigned int format, unsigned int width, unsigned int height, unsigned int planelen[SCALER_MAX_PLANES])
-{
+bool LibScalerForJpeg::Device::setFormat(unsigned int buftype, unsigned int format,
+ unsigned int width, unsigned int height,
+ unsigned int planelen[SCALER_MAX_PLANES]) {
v4l2_format fmt{};
fmt.type = buftype;
fmt.fmt.pix_mp.pixelformat = format;
- fmt.fmt.pix_mp.width = width;
+ fmt.fmt.pix_mp.width = width;
fmt.fmt.pix_mp.height = height;
if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) {
- ALOGERR("failed S_FMT(%s, fmt=h'%x, %ux%u)", getBufTypeString(buftype), format, width, height);
+ ALOGERR("failed S_FMT(%s, fmt=h'%x, %ux%u)", getBufTypeString(buftype), format, width,
+ height);
return false;
}
- for (uint32_t i = 0; i < fmt.fmt.pix_mp.num_planes ; i++) {
+ for (uint32_t i = 0; i < fmt.fmt.pix_mp.num_planes; i++) {
planelen[i] = fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
}
return true;
}
-bool LibScalerForJpeg::Device::streamOn(unsigned int buftype)
-{
+bool LibScalerForJpeg::Device::streamOn(unsigned int buftype) {
if (ioctl(mFd, VIDIOC_STREAMON, &buftype) < 0) {
ALOGERR("failed STREAMON for %s", getBufTypeString(buftype));
return false;
@@ -158,8 +142,7 @@ bool LibScalerForJpeg::Device::streamOn(unsigned int buftype)
return true;
}
-bool LibScalerForJpeg::Device::streamOff(unsigned int buftype)
-{
+bool LibScalerForJpeg::Device::streamOff(unsigned int buftype) {
if (ioctl(mFd, VIDIOC_STREAMOFF, &buftype) < 0) {
ALOGERR("failed STREAMOFF for %s", getBufTypeString(buftype));
return false;
@@ -168,8 +151,8 @@ bool LibScalerForJpeg::Device::streamOff(unsigned int buftype)
return true;
}
-bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, std::function<void(v4l2_buffer &)> bufferFiller)
-{
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype,
+ std::function<void(v4l2_buffer &)> bufferFiller) {
v4l2_buffer buffer{};
v4l2_plane plane[SCALER_MAX_PLANES];
@@ -183,47 +166,50 @@ bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, std::function<v
return ioctl(mFd, VIDIOC_QBUF, &buffer) >= 0;
}
-bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES])
-{
- if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer) {
- buffer.memory = V4L2_MEMORY_DMABUF;
- buffer.length = SCALER_MAX_PLANES;
- for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
- buffer.m.planes[i].m.fd = buf[i];
- buffer.m.planes[i].length = len[i];
- } })) {
- ALOGERR("failed QBUF(%s, fd[]=%d %d, len[0]=%d %d)", getBufTypeString(buftype), buf[0], buf[1], len[0], len[1]);
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES],
+ unsigned int len[SCALER_MAX_PLANES]) {
+ if (!queueBuffer(buftype, [buf, len](v4l2_buffer &buffer) {
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.length = SCALER_MAX_PLANES;
+ for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
+ buffer.m.planes[i].m.fd = buf[i];
+ buffer.m.planes[i].length = len[i];
+ }
+ })) {
+ ALOGERR("failed QBUF(%s, fd[]=%d %d, len[0]=%d %d)", getBufTypeString(buftype), buf[0],
+ buf[1], len[0], len[1]);
return false;
}
return true;
}
-bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES])
-{
- if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer) {
- buffer.memory = V4L2_MEMORY_USERPTR;
- buffer.length = SCALER_MAX_PLANES;
- for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
- buffer.m.planes[i].m.userptr = reinterpret_cast<unsigned long>(buf[i]);
- buffer.m.planes[i].length = len[i];
- } })) {
- ALOGERR("failed QBUF(%s, ptr[]=%p %p, len[0]=%d %d)", getBufTypeString(buftype), buf[0], buf[1], len[0], len[1]);
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES],
+ unsigned int len[SCALER_MAX_PLANES]) {
+ if (!queueBuffer(buftype, [buf, len](v4l2_buffer &buffer) {
+ buffer.memory = V4L2_MEMORY_USERPTR;
+ buffer.length = SCALER_MAX_PLANES;
+ for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
+ buffer.m.planes[i].m.userptr = reinterpret_cast<unsigned long>(buf[i]);
+ buffer.m.planes[i].length = len[i];
+ }
+ })) {
+ ALOGERR("failed QBUF(%s, ptr[]=%p %p, len[0]=%d %d)", getBufTypeString(buftype), buf[0],
+ buf[1], len[0], len[1]);
return false;
}
return true;
}
-bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf, unsigned int len[SCALER_MAX_PLANES])
-{
- if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer)
- {
- buffer.memory = V4L2_MEMORY_DMABUF;
- buffer.length = 1;
- buffer.m.planes[0].m.fd = buf;
- buffer.m.planes[0].length = len[0];
- })) {
+bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf,
+ unsigned int len[SCALER_MAX_PLANES]) {
+ if (!queueBuffer(buftype, [buf, len](v4l2_buffer &buffer) {
+ buffer.memory = V4L2_MEMORY_DMABUF;
+ buffer.length = 1;
+ buffer.m.planes[0].m.fd = buf;
+ buffer.m.planes[0].length = len[0];
+ })) {
ALOGERR("failed QBUF(%s, fd=%d, len=%d", getBufTypeString(buftype), buf, len[0]);
return false;
}
@@ -231,8 +217,7 @@ bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf, unsign
return true;
}
-bool LibScalerForJpeg::Device::dequeueBuffer(unsigned int buftype, unsigned int memtype)
-{
+bool LibScalerForJpeg::Device::dequeueBuffer(unsigned int buftype, unsigned int memtype) {
v4l2_buffer buffer{};
v4l2_plane plane[SCALER_MAX_PLANES];
@@ -244,7 +229,7 @@ bool LibScalerForJpeg::Device::dequeueBuffer(unsigned int buftype, unsigned int
buffer.m.planes = plane;
- if (ioctl(mFd, VIDIOC_DQBUF, &buffer) < 0 ) {
+ if (ioctl(mFd, VIDIOC_DQBUF, &buffer) < 0) {
ALOGERR("failed DQBUF(%s)", getBufTypeString(buftype));
return false;
}
diff --git a/libhwjpeg/LibScalerForJpeg.h b/libhwjpeg/LibScalerForJpeg.h
index f8914d7..4c90e43 100644
--- a/libhwjpeg/LibScalerForJpeg.h
+++ b/libhwjpeg/LibScalerForJpeg.h
@@ -16,16 +16,16 @@
#ifndef __HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
#define __HARDWARE_EXYNOS_LIBSCALERFORJPEG_H__
-#include <functional>
-
#include <linux/videodev2.h>
+#include <functional>
+
#include "ThumbnailScaler.h"
class LibScalerForJpeg : public ThumbnailScaler {
public:
- LibScalerForJpeg() { }
- ~LibScalerForJpeg() { }
+ LibScalerForJpeg() {}
+ ~LibScalerForJpeg() {}
bool SetSrcImage(unsigned int width, unsigned int height, unsigned int v4l2_format) {
return mSrcImage.set(width, height, v4l2_format);
@@ -35,10 +35,13 @@ public:
return mDstImage.set(width, height, v4l2_format);
}
- bool RunStream(int srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen);
- bool RunStream(char *srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen);
+ bool RunStream(int srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf,
+ size_t dstLen);
+ bool RunStream(char *srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf,
+ size_t dstLen);
bool available() { return mDevice.mFd >= 0; }
+
private:
struct Device {
int mFd;
@@ -46,12 +49,15 @@ private:
Device();
~Device();
bool requestBuffers(unsigned int buftype, unsigned int memtype, unsigned int count);
- bool setFormat(unsigned int buftype, unsigned int format, unsigned int width, unsigned int height, unsigned int planelen[SCALER_MAX_PLANES]);
+ bool setFormat(unsigned int buftype, unsigned int format, unsigned int width,
+ unsigned int height, unsigned int planelen[SCALER_MAX_PLANES]);
bool streamOn(unsigned int buftype);
bool streamOff(unsigned int buftype);
bool queueBuffer(unsigned int buftype, std::function<void(v4l2_buffer &)> bufferFiller);
- bool queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES]);
- bool queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES]);
+ bool queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES],
+ unsigned int len[SCALER_MAX_PLANES]);
+ bool queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES],
+ unsigned int len[SCALER_MAX_PLANES]);
bool queueBuffer(unsigned int buftype, int buf, unsigned int len[SCALER_MAX_PLANES]);
bool dequeueBuffer(unsigned int buftype, unsigned int memtype);
};
@@ -66,24 +72,26 @@ private:
unsigned int planeLen[SCALER_MAX_PLANES];
Image(Device &dev, unsigned int w, unsigned int h, unsigned int f, unsigned int buftype)
- : mDevice(dev), width(w), height(h), format(f), bufferType(buftype)
- { }
+ : mDevice(dev), width(w), height(h), format(f), bufferType(buftype) {}
bool set(unsigned int width, unsigned int height, unsigned int format);
bool begin(unsigned int memtype);
bool cancelBuffer();
template <class tBuf>
- bool queueBuffer(tBuf buf) { return mDevice.queueBuffer(bufferType, buf, planeLen); }
+ bool queueBuffer(tBuf buf) {
+ return mDevice.queueBuffer(bufferType, buf, planeLen);
+ }
bool dequeueBuffer() { return mDevice.dequeueBuffer(bufferType, memoryType); }
- bool same(unsigned int w, unsigned int h, unsigned int f) { return width == w && height == h && format == f; }
+ bool same(unsigned int w, unsigned int h, unsigned int f) {
+ return width == w && height == h && format == f;
+ }
};
- template<class T>
+ template <class T>
bool queue(T srcBuf[SCALER_MAX_PLANES], int dstBuf) {
- if (!mSrcImage.queueBuffer(srcBuf))
- return false;
+ if (!mSrcImage.queueBuffer(srcBuf)) return false;
if (!mDstImage.queueBuffer(dstBuf)) {
mSrcImage.cancelBuffer();
diff --git a/libhwjpeg/ThumbnailScaler.cpp b/libhwjpeg/ThumbnailScaler.cpp
index 4d6e5de..3f4edcf 100644
--- a/libhwjpeg/ThumbnailScaler.cpp
+++ b/libhwjpeg/ThumbnailScaler.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
+#include "ThumbnailScaler.h"
+
#include <log/log.h>
-#include "ThumbnailScaler.h"
#include "LibScalerForJpeg.h"
-ThumbnailScaler *ThumbnailScaler::createInstance()
-{
+ThumbnailScaler *ThumbnailScaler::createInstance() {
ALOGD("Created thumbnail scaler: legacy V4L2 Scaler");
return new LibScalerForJpeg();
}
diff --git a/libhwjpeg/ThumbnailScaler.h b/libhwjpeg/ThumbnailScaler.h
index cb23365..14d6e7d 100644
--- a/libhwjpeg/ThumbnailScaler.h
+++ b/libhwjpeg/ThumbnailScaler.h
@@ -6,14 +6,16 @@
class ThumbnailScaler {
public:
const static unsigned int SCALER_MAX_PLANES = 3;
- ThumbnailScaler() { }
- virtual ~ThumbnailScaler() { }
+ ThumbnailScaler() {}
+ virtual ~ThumbnailScaler() {}
virtual bool SetSrcImage(unsigned int width, unsigned int height, unsigned int v4l2_format) = 0;
virtual bool SetDstImage(unsigned int width, unsigned int height, unsigned int v4l2_format) = 0;
- virtual bool RunStream(int srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen) = 0;
- virtual bool RunStream(char *srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf, size_t dstLen) = 0;
+ virtual bool RunStream(int srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES], int dstBuf,
+ size_t dstLen) = 0;
+ virtual bool RunStream(char *srcBuf[SCALER_MAX_PLANES], int srcLen[SCALER_MAX_PLANES],
+ int dstBuf, size_t dstLen) = 0;
static ThumbnailScaler *createInstance();
diff --git a/libhwjpeg/hwjpeg-base.cpp b/libhwjpeg/hwjpeg-base.cpp
index e593c02..f319d50 100644
--- a/libhwjpeg/hwjpeg-base.cpp
+++ b/libhwjpeg/hwjpeg-base.cpp
@@ -15,52 +15,41 @@
* limitations under the License.
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
+#include <exynos-hwjpeg.h>
#include <fcntl.h>
-
-#include <linux/videodev2.h>
#include <linux/v4l2-controls.h>
+#include <linux/videodev2.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
-#include <exynos-hwjpeg.h>
#include "hwjpeg-internal.h"
-CHWJpegBase::CHWJpegBase(const char *path)
- : m_iFD(-1), m_uiDeviceCaps(0), m_uiAuxFlags(0)
-{
+CHWJpegBase::CHWJpegBase(const char *path) : m_iFD(-1), m_uiDeviceCaps(0), m_uiAuxFlags(0) {
m_iFD = open(path, O_RDWR);
- if (m_iFD < 0)
- ALOGERR("Failed to open '%s'", path);
+ if (m_iFD < 0) ALOGERR("Failed to open '%s'", path);
}
-CHWJpegBase::~CHWJpegBase()
-{
- if (m_iFD >= 0)
- close(m_iFD);
+CHWJpegBase::~CHWJpegBase() {
+ if (m_iFD >= 0) close(m_iFD);
}
-void CHWJpegBase::SetAuxFlags(unsigned int auxflags)
-{
+void CHWJpegBase::SetAuxFlags(unsigned int auxflags) {
ALOGW_IF(!!(m_uiAuxFlags & auxflags),
- "Configuration auxiliary flags %#x overrides previous flags %#x",
- auxflags , m_uiAuxFlags);
+ "Configuration auxiliary flags %#x overrides previous flags %#x", auxflags,
+ m_uiAuxFlags);
m_uiAuxFlags |= auxflags;
}
-void CHWJpegBase::ClearAuxFlags(unsigned int auxflags)
-{
-
+void CHWJpegBase::ClearAuxFlags(unsigned int auxflags) {
ALOGW_IF(!!(m_uiAuxFlags & auxflags) && ((m_uiAuxFlags & auxflags) != auxflags),
- "Clearing auxiliary flags %#x overrides previous flags %#x",
- auxflags, m_uiAuxFlags);
+ "Clearing auxiliary flags %#x overrides previous flags %#x", auxflags, m_uiAuxFlags);
m_uiAuxFlags &= ~auxflags;
}
-bool CStopWatch::Start()
-{
+bool CStopWatch::Start() {
int ret = clock_gettime(CLOCK_MONOTONIC, &m_tBegin);
if (ret) {
ALOGERR("Failed to get current clock");
@@ -71,8 +60,7 @@ bool CStopWatch::Start()
return true;
}
-unsigned long CStopWatch::GetElapsed()
-{
+unsigned long CStopWatch::GetElapsed() {
timespec tp;
int ret = clock_gettime(CLOCK_MONOTONIC, &tp);
if (ret) {
@@ -81,13 +69,11 @@ unsigned long CStopWatch::GetElapsed()
}
unsigned long elapsed = (tp.tv_sec - m_tBegin.tv_sec) * 1000000;
- return (m_tBegin.tv_nsec > tp.tv_nsec)
- ? elapsed - (m_tBegin.tv_nsec - tp.tv_nsec) / 1000
- : elapsed + (tp.tv_nsec - m_tBegin.tv_nsec) / 1000;
+ return (m_tBegin.tv_nsec > tp.tv_nsec) ? elapsed - (m_tBegin.tv_nsec - tp.tv_nsec) / 1000
+ : elapsed + (tp.tv_nsec - m_tBegin.tv_nsec) / 1000;
}
-unsigned long CStopWatch::GetElapsedUpdate()
-{
+unsigned long CStopWatch::GetElapsedUpdate() {
timespec tp;
int ret = clock_gettime(CLOCK_MONOTONIC, &tp);
if (ret) {
@@ -96,17 +82,15 @@ unsigned long CStopWatch::GetElapsedUpdate()
}
unsigned long elapsed = (tp.tv_sec - m_tBegin.tv_sec) * 1000000;
- elapsed = (m_tBegin.tv_nsec > tp.tv_nsec)
- ? elapsed - (m_tBegin.tv_nsec - tp.tv_nsec) / 1000
- : elapsed + (tp.tv_nsec - m_tBegin.tv_nsec) / 1000;
+ elapsed = (m_tBegin.tv_nsec > tp.tv_nsec) ? elapsed - (m_tBegin.tv_nsec - tp.tv_nsec) / 1000
+ : elapsed + (tp.tv_nsec - m_tBegin.tv_nsec) / 1000;
m_tBegin = tp;
return elapsed;
}
-bool WriteToFile(const char *path, const char *data, size_t len)
-{
- int fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWGRP );
+bool WriteToFile(const char *path, const char *data, size_t len) {
+ int fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWGRP);
if (fd < 0) {
ALOGERR("Failed to open '%s' for write/create", path);
return false;
@@ -124,15 +108,15 @@ bool WriteToFile(const char *path, const char *data, size_t len)
return true;
}
-bool WriteToFile(const char *path, int dmabuf, size_t len)
-{
- char *p = reinterpret_cast<char *>(mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf, 0));
+bool WriteToFile(const char *path, int dmabuf, size_t len) {
+ char *p = reinterpret_cast<char *>(
+ mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf, 0));
if (p == MAP_FAILED) {
ALOGERR("Filed to map the given dmabuf fd %d", dmabuf);
return false;
}
- int fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWGRP );
+ int fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | S_IWGRP);
if (fd < 0) {
ALOGERR("Failed to open '%s' for write/create", path);
munmap(p, len);
diff --git a/libhwjpeg/hwjpeg-internal.h b/libhwjpeg/hwjpeg-internal.h
index 8113871..bb14a35 100644
--- a/libhwjpeg/hwjpeg-internal.h
+++ b/libhwjpeg/hwjpeg-internal.h
@@ -22,18 +22,18 @@
#error "LOG_TAG is not defined!"
#endif
-#include <cerrno>
-#include <cstring>
-
-#include <unistd.h>
#include <log/log.h>
-#include <time.h>
#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstring>
#ifdef __GNUC__
-# define __UNUSED__ __attribute__((__unused__))
+#define __UNUSED__ __attribute__((__unused__))
#else
-# define __UNUSED__
+#define __UNUSED__
#endif
#ifndef ALOGERR
@@ -41,14 +41,16 @@
#endif
#define V4L2_CID_JPEG_SEC_COMP_QUALITY (V4L2_CID_JPEG_CLASS_BASE + 20)
-#define V4L2_CID_JPEG_QTABLES2 (V4L2_CID_JPEG_CLASS_BASE + 22)
-#define V4L2_CID_JPEG_HWFC_ENABLE (V4L2_CID_JPEG_CLASS_BASE + 25)
+#define V4L2_CID_JPEG_QTABLES2 (V4L2_CID_JPEG_CLASS_BASE + 22)
+#define V4L2_CID_JPEG_HWFC_ENABLE (V4L2_CID_JPEG_CLASS_BASE + 25)
+#define V4L2_CID_JPEG_PADDING (V4L2_CID_JPEG_CLASS_BASE + 26)
+#define V4L2_CID_JPEG_SEC_PADDING (V4L2_CID_JPEG_CLASS_BASE + 27)
-#define TO_MAIN_SIZE(val) ((val) & 0xFFFF)
-#define TO_THUMB_SIZE(val) (((val) & 0xFFFF) << 16)
+#define TO_MAIN_SIZE(val) ((val)&0xFFFF)
+#define TO_THUMB_SIZE(val) (((val)&0xFFFF) << 16)
#define TO_IMAGE_SIZE(main, thumb) (TO_MAIN_SIZE(main) | TO_THUMB_SIZE(thumb))
-#define PTR_TO_ULONG(ptr) reinterpret_cast<unsigned long>(ptr)
+#define PTR_TO_ULONG(ptr) reinterpret_cast<unsigned long>(ptr)
#define PTR_DIFF(ptr1, ptr2) (reinterpret_cast<size_t>(ptr2) - reinterpret_cast<size_t>(ptr1))
#define ARRSIZE(v) (sizeof(v) / sizeof(v[0]))
@@ -74,10 +76,10 @@ static inline T max(T val1, T val2) {
class CStopWatch {
timespec m_tBegin;
+
public:
CStopWatch(bool start = false) {
- if (start)
- Start();
+ if (start) Start();
}
bool Start();
unsigned long GetElapsed();
diff --git a/libhwjpeg/hwjpeg-v4l2.cpp b/libhwjpeg/hwjpeg-v4l2.cpp
index bfa1a52..c364554 100644
--- a/libhwjpeg/hwjpeg-v4l2.cpp
+++ b/libhwjpeg/hwjpeg-v4l2.cpp
@@ -15,14 +15,15 @@
* limitations under the License.
*/
-#include <linux/videodev2.h>
+#include <exynos-hwjpeg.h>
#include <linux/v4l2-controls.h>
+#include <linux/videodev2.h>
-#include <exynos-hwjpeg.h>
#include "hwjpeg-internal.h"
+#include "log/log_main.h"
-CHWJpegV4L2Compressor::CHWJpegV4L2Compressor(): CHWJpegCompressor("/dev/video12")
-{
+CHWJpegV4L2Compressor::CHWJpegV4L2Compressor()
+ : CHWJpegCompressor("/dev/video12"), file_lock_(FileLock(GetDeviceFD())) {
memset(&m_v4l2Format, 0, sizeof(m_v4l2Format));
memset(&m_v4l2SrcBuffer, 0, sizeof(m_v4l2SrcBuffer));
memset(&m_v4l2DstBuffer, 0, sizeof(m_v4l2DstBuffer));
@@ -63,27 +64,42 @@ CHWJpegV4L2Compressor::CHWJpegV4L2Compressor(): CHWJpegCompressor("/dev/video12"
ALOGD("CHWJpegV4L2Compressor Created: %p, FD %d", this, GetDeviceFD());
}
-CHWJpegV4L2Compressor::~CHWJpegV4L2Compressor()
-{
+CHWJpegV4L2Compressor::~CHWJpegV4L2Compressor() {
StopStreaming();
ALOGD("CHWJpegV4L2Compressor Destroyed: %p, FD %d", this, GetDeviceFD());
}
-bool CHWJpegV4L2Compressor::SetChromaSampFactor(
- unsigned int horizontal, unsigned int vertical)
-{
+int CHWJpegV4L2Compressor::lock() {
+ return file_lock_.lock();
+}
+
+int CHWJpegV4L2Compressor::unlock() {
+ return file_lock_.unlock();
+}
+
+bool CHWJpegV4L2Compressor::SetChromaSampFactor(unsigned int horizontal, unsigned int vertical) {
__s32 value;
switch ((horizontal << 4) | vertical) {
- case 0x00: value = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; break;
- case 0x11: value = V4L2_JPEG_CHROMA_SUBSAMPLING_444; break;
- case 0x21: value = V4L2_JPEG_CHROMA_SUBSAMPLING_422; break;
- case 0x22: value = V4L2_JPEG_CHROMA_SUBSAMPLING_420; break;
- case 0x41: value = V4L2_JPEG_CHROMA_SUBSAMPLING_411; break;
+ case 0x00:
+ value = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
+ break;
+ case 0x11:
+ value = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
+ break;
+ case 0x21:
+ value = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
+ break;
+ case 0x22:
+ value = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
+ break;
+ case 0x41:
+ value = V4L2_JPEG_CHROMA_SUBSAMPLING_411;
+ break;
case 0x12:
default:
- ALOGE("Unsupported chroma subsampling %ux%u", horizontal, vertical);
- return false;
+ ALOGE("Unsupported chroma subsampling %ux%u", horizontal, vertical);
+ return false;
}
m_v4l2Controls[HWJPEG_CTRL_CHROMFACTOR].id = V4L2_CID_JPEG_CHROMA_SUBSAMPLING;
@@ -93,17 +109,14 @@ bool CHWJpegV4L2Compressor::SetChromaSampFactor(
return true;
}
-bool CHWJpegV4L2Compressor::SetQuality(
- unsigned int quality_factor, unsigned int quality_factor2)
-{
+bool CHWJpegV4L2Compressor::SetQuality(unsigned int quality_factor, unsigned int quality_factor2) {
if (quality_factor > 100) {
ALOGE("Unsupported quality factor %u", quality_factor);
return false;
}
if (quality_factor2 > 100) {
- ALOGE("Unsupported quality factor %u for the secondary image",
- quality_factor2);
+ ALOGE("Unsupported quality factor %u for the secondary image", quality_factor2);
return false;
}
@@ -122,8 +135,7 @@ bool CHWJpegV4L2Compressor::SetQuality(
return true;
}
-bool CHWJpegV4L2Compressor::SetQuality(const unsigned char qtable[])
-{
+bool CHWJpegV4L2Compressor::SetQuality(const unsigned char qtable[]) {
v4l2_ext_controls ctrls;
v4l2_ext_control ctrl;
@@ -146,10 +158,54 @@ bool CHWJpegV4L2Compressor::SetQuality(const unsigned char qtable[])
return true;
}
-bool CHWJpegV4L2Compressor::SetImageFormat(unsigned int v4l2_fmt,
- unsigned int width, unsigned int height,
- unsigned int width2, unsigned int height2)
-{
+bool CHWJpegV4L2Compressor::SetPadding(unsigned char padding[], unsigned int num_planes) {
+ if (num_planes > 3 || num_planes < 1) {
+ ALOGE("Attempting to set padding for incorrect number of buffers");
+ return false;
+ }
+
+ unsigned int padding_value = 0;
+
+ for (int i = num_planes - 1; i >= 0; i--) {
+ padding_value <<= 8;
+ padding_value |= padding[i];
+ }
+
+ m_v4l2Controls[HWJPEG_CTRL_PADDING].id = V4L2_CID_JPEG_PADDING;
+ m_v4l2Controls[HWJPEG_CTRL_PADDING].value = static_cast<__s32>(padding_value);
+ m_uiControlsToSet |= 1 << HWJPEG_CTRL_PADDING;
+
+ return true;
+}
+
+bool CHWJpegV4L2Compressor::SetPadding2(unsigned char padding[], unsigned int num_planes) {
+ if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
+ ALOGE("Back-to-back compression is not suppored by H/W");
+ return false;
+ }
+
+ if (num_planes > 3 || num_planes < 1) {
+ ALOGE("Attempting to set padding for incorrect number of buffers");
+ return false;
+ }
+
+ unsigned int padding_value = 0;
+
+ for (int i = num_planes - 1; i >= 0; i--) {
+ padding_value <<= 8;
+ padding_value |= padding[i];
+ }
+
+ m_v4l2Controls[HWJPEG_CTRL_PADDING2].id = V4L2_CID_JPEG_SEC_PADDING;
+ m_v4l2Controls[HWJPEG_CTRL_PADDING2].value = static_cast<__s32>(padding_value);
+ m_uiControlsToSet |= 1 << HWJPEG_CTRL_PADDING2;
+
+ return true;
+}
+
+bool CHWJpegV4L2Compressor::SetImageFormat(unsigned int v4l2_fmt, unsigned int width,
+ unsigned int height, unsigned int width2,
+ unsigned int height2) {
if ((m_v4l2Format.fmt.pix_mp.pixelformat == v4l2_fmt) &&
(m_v4l2Format.fmt.pix_mp.width == TO_IMAGE_SIZE(width, width2)) &&
(m_v4l2Format.fmt.pix_mp.height == TO_IMAGE_SIZE(height, height2)))
@@ -164,8 +220,7 @@ bool CHWJpegV4L2Compressor::SetImageFormat(unsigned int v4l2_fmt,
return TryFormat();
}
-bool CHWJpegV4L2Compressor::GetImageBufferSizes(size_t buf_sizes[], unsigned int *num_buffers)
-{
+bool CHWJpegV4L2Compressor::GetImageBufferSizes(size_t buf_sizes[], unsigned int *num_buffers) {
if (buf_sizes) {
for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++)
buf_sizes[i] = m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage;
@@ -174,7 +229,7 @@ bool CHWJpegV4L2Compressor::GetImageBufferSizes(size_t buf_sizes[], unsigned int
if (num_buffers) {
if (*num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
ALOGE("The size array length %u is smaller than the number of required buffers %u",
- *num_buffers, m_v4l2Format.fmt.pix_mp.num_planes);
+ *num_buffers, m_v4l2Format.fmt.pix_mp.num_planes);
return false;
}
@@ -185,19 +240,18 @@ bool CHWJpegV4L2Compressor::GetImageBufferSizes(size_t buf_sizes[], unsigned int
}
bool CHWJpegV4L2Compressor::SetImageBuffer(char *buffers[], size_t len_buffers[],
- unsigned int num_buffers)
-{
+ unsigned int num_buffers) {
if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
- ALOGE("The number of buffers %u is smaller than the required %u",
- num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
+ ALOGE("The number of buffers %u is smaller than the required %u", num_buffers,
+ m_v4l2Format.fmt.pix_mp.num_planes);
return false;
}
for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
m_v4l2SrcPlanes[i].m.userptr = reinterpret_cast<unsigned long>(buffers[i]);
if (len_buffers[i] < m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage) {
- ALOGE("The size of the buffer[%u] %zu is smaller than required %u",
- i, len_buffers[i], m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage);
+ ALOGE("The size of the buffer[%u] %zu is smaller than required %u", i, len_buffers[i],
+ m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage);
return false;
}
m_v4l2SrcPlanes[i].bytesused = m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage;
@@ -212,19 +266,18 @@ bool CHWJpegV4L2Compressor::SetImageBuffer(char *buffers[], size_t len_buffers[]
}
bool CHWJpegV4L2Compressor::SetImageBuffer(int buffers[], size_t len_buffers[],
- unsigned int num_buffers)
-{
+ unsigned int num_buffers) {
if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
- ALOGE("The number of buffers %u is smaller than the required %u",
- num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
+ ALOGE("The number of buffers %u is smaller than the required %u", num_buffers,
+ m_v4l2Format.fmt.pix_mp.num_planes);
return false;
}
for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
m_v4l2SrcPlanes[i].m.fd = buffers[i];
if (len_buffers[i] < m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage) {
- ALOGE("The size of the buffer[%u] %zu is smaller than required %u",
- i, len_buffers[i], m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage);
+ ALOGE("The size of the buffer[%u] %zu is smaller than required %u", i, len_buffers[i],
+ m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage);
return false;
}
m_v4l2SrcPlanes[i].bytesused = m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage;
@@ -238,23 +291,22 @@ bool CHWJpegV4L2Compressor::SetImageBuffer(int buffers[], size_t len_buffers[],
return true;
}
- bool CHWJpegV4L2Compressor::SetImageBuffer2(char *buffers[], size_t len_buffers[],
- unsigned int num_buffers)
-{
+bool CHWJpegV4L2Compressor::SetImageBuffer2(char *buffers[], size_t len_buffers[],
+ unsigned int num_buffers) {
if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
ALOGE("Back-to-back compression is not suppored by H/W");
return false;
}
if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
- ALOGE("The number of buffers %u is smaller than the required %u (secondary)",
- num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
+ ALOGE("The number of buffers %u is smaller than the required %u (secondary)", num_buffers,
+ m_v4l2Format.fmt.pix_mp.num_planes);
return false;
}
unsigned int ibuf = 0;
for (unsigned int i = m_v4l2Format.fmt.pix_mp.num_planes;
- i < (m_v4l2Format.fmt.pix_mp.num_planes * 2); i++, ibuf++) {
+ i < (m_v4l2Format.fmt.pix_mp.num_planes * 2); i++, ibuf++) {
m_v4l2SrcPlanes[i].m.userptr = reinterpret_cast<unsigned long>(buffers[ibuf]);
// size check is ignored for the secondary image buffers
m_v4l2SrcPlanes[i].bytesused = len_buffers[ibuf];
@@ -267,23 +319,22 @@ bool CHWJpegV4L2Compressor::SetImageBuffer(int buffers[], size_t len_buffers[],
return true;
}
- bool CHWJpegV4L2Compressor::SetImageBuffer2(int buffers[], size_t len_buffers[],
- unsigned int num_buffers)
-{
+bool CHWJpegV4L2Compressor::SetImageBuffer2(int buffers[], size_t len_buffers[],
+ unsigned int num_buffers) {
if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
ALOGE("Back-to-back compression is not suppored by H/W");
return false;
}
if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
- ALOGE("The number of buffers %u is smaller than the required %u (secondary)",
- num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
+ ALOGE("The number of buffers %u is smaller than the required %u (secondary)", num_buffers,
+ m_v4l2Format.fmt.pix_mp.num_planes);
return false;
}
unsigned int ibuf = 0;
for (unsigned int i = m_v4l2Format.fmt.pix_mp.num_planes;
- i < (m_v4l2Format.fmt.pix_mp.num_planes * 2); i++, ibuf++) {
+ i < (m_v4l2Format.fmt.pix_mp.num_planes * 2); i++, ibuf++) {
m_v4l2SrcPlanes[i].m.fd = buffers[ibuf];
// size check is ignored for the secondary image buffers
m_v4l2SrcPlanes[i].bytesused = len_buffers[ibuf];
@@ -297,8 +348,7 @@ bool CHWJpegV4L2Compressor::SetImageBuffer(int buffers[], size_t len_buffers[],
return true;
}
-bool CHWJpegV4L2Compressor::SetJpegBuffer(char *buffer, size_t len_buffer)
-{
+bool CHWJpegV4L2Compressor::SetJpegBuffer(char *buffer, size_t len_buffer) {
m_v4l2DstPlanes[0].m.userptr = reinterpret_cast<unsigned long>(buffer);
m_v4l2DstPlanes[0].length = len_buffer;
m_v4l2DstBuffer.memory = V4L2_MEMORY_USERPTR;
@@ -306,8 +356,7 @@ bool CHWJpegV4L2Compressor::SetJpegBuffer(char *buffer, size_t len_buffer)
return true;
}
-bool CHWJpegV4L2Compressor::SetJpegBuffer(int buffer, size_t len_buffer, int offset)
-{
+bool CHWJpegV4L2Compressor::SetJpegBuffer(int buffer, size_t len_buffer, int offset) {
m_v4l2DstPlanes[0].m.fd = buffer;
m_v4l2DstPlanes[0].length = len_buffer;
m_v4l2DstPlanes[0].data_offset = offset;
@@ -316,8 +365,7 @@ bool CHWJpegV4L2Compressor::SetJpegBuffer(int buffer, size_t len_buffer, int off
return true;
}
-bool CHWJpegV4L2Compressor::SetJpegBuffer2(char *buffer, size_t len_buffer)
-{
+bool CHWJpegV4L2Compressor::SetJpegBuffer2(char *buffer, size_t len_buffer) {
if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
ALOGE("Back-to-back compression is not suppored by H/W");
return false;
@@ -329,8 +377,7 @@ bool CHWJpegV4L2Compressor::SetJpegBuffer2(char *buffer, size_t len_buffer)
return true;
}
-bool CHWJpegV4L2Compressor::SetJpegBuffer2(int buffer, size_t len_buffer)
-{
+bool CHWJpegV4L2Compressor::SetJpegBuffer2(int buffer, size_t len_buffer) {
if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
ALOGE("Back-to-back compression is not suppored by H/W");
return false;
@@ -342,11 +389,9 @@ bool CHWJpegV4L2Compressor::SetJpegBuffer2(int buffer, size_t len_buffer)
return true;
}
-bool CHWJpegV4L2Compressor::StopStreaming()
-{
+bool CHWJpegV4L2Compressor::StopStreaming() {
if (TestFlag(HWJPEG_FLAG_STREAMING)) {
- if (!StreamOff())
- return false;
+ if (!StreamOff()) return false;
ClearFlag(HWJPEG_FLAG_STREAMING);
}
@@ -355,19 +400,16 @@ bool CHWJpegV4L2Compressor::StopStreaming()
// It is OK to skip DQBUF because STREAMOFF dequeues all queued buffers
if (TestFlag(HWJPEG_FLAG_REQBUFS)) {
- if (!ReqBufs(0))
- return false;
+ if (!ReqBufs(0)) return false;
ClearFlag(HWJPEG_FLAG_REQBUFS);
}
return true;
}
-ssize_t CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size, bool block_mode)
-{
+ssize_t CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size, bool block_mode) {
if (TestFlag(HWJPEG_FLAG_PIX_FMT)) {
- if (!StopStreaming() || !SetFormat())
- return -1;
+ if (!StopStreaming() || !SetFormat()) return -1;
}
if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER)) {
@@ -384,7 +426,8 @@ ssize_t CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size, bool bloc
m_v4l2DstBuffer.length = 1;
if (IsB2BCompression()) {
if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER2 | HWJPEG_FLAG_DST_BUFFER2)) {
- ALOGE("Either of source or destination buffer of secondary image is not specified (%#x)",
+ ALOGE("Either of source or destination buffer of secondary image is not specified "
+ "(%#x)",
GetFlags());
return -1;
}
@@ -399,14 +442,12 @@ ssize_t CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size, bool bloc
if (!!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_DST_NOCACHECLEAN))
m_v4l2DstBuffer.flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
- if (!ReqBufs() || !StreamOn() || !UpdateControls() || !QBuf())
- return -1;
+ if (!ReqBufs() || !StreamOn() || !UpdateControls() || !QBuf()) return -1;
return block_mode ? DQBuf(secondary_stream_size) : 0;
}
-bool CHWJpegV4L2Compressor::TryFormat()
-{
+bool CHWJpegV4L2Compressor::TryFormat() {
if (ioctl(GetDeviceFD(), VIDIOC_TRY_FMT, &m_v4l2Format) < 0) {
ALOGERR("Failed to TRY_FMT for compression");
return false;
@@ -415,8 +456,7 @@ bool CHWJpegV4L2Compressor::TryFormat()
return true;
}
-bool CHWJpegV4L2Compressor::SetFormat()
-{
+bool CHWJpegV4L2Compressor::SetFormat() {
if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &m_v4l2Format) < 0) {
ALOGERR("Failed to S_FMT for image to compress");
return false;
@@ -440,12 +480,10 @@ bool CHWJpegV4L2Compressor::SetFormat()
return true;
}
-bool CHWJpegV4L2Compressor::UpdateControls()
-{
+bool CHWJpegV4L2Compressor::UpdateControls() {
bool enable_hwfc = !!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_ENABLE_HWFC);
- if ((m_uiControlsToSet == 0) && (enable_hwfc == m_bEnableHWFC))
- return true;
+ if ((m_uiControlsToSet == 0) && (enable_hwfc == m_bEnableHWFC)) return true;
v4l2_ext_controls ctrls;
v4l2_ext_control ctrl[HWJPEG_CTRL_NUM];
@@ -481,14 +519,12 @@ bool CHWJpegV4L2Compressor::UpdateControls()
return true;
}
-bool CHWJpegV4L2Compressor::ReqBufs(unsigned int count)
-{
+bool CHWJpegV4L2Compressor::ReqBufs(unsigned int count) {
// - count > 0 && REQBUFS is set: Just return true
// - count > 0 && REQBUFS is unset: REQBUFS(count) is required
// - count == 0 && REQBUFS is set: REQBUFS(0) is required
// - count == 0 && REQBUFS is unset: Just return true;
- if ((count > 0) == TestFlag(HWJPEG_FLAG_REQBUFS))
- return true;
+ if ((count > 0) == TestFlag(HWJPEG_FLAG_REQBUFS)) return true;
v4l2_requestbuffers reqbufs;
@@ -523,10 +559,8 @@ bool CHWJpegV4L2Compressor::ReqBufs(unsigned int count)
return true;
}
-bool CHWJpegV4L2Compressor::StreamOn()
-{
- if (TestFlag(HWJPEG_FLAG_STREAMING))
- return true;
+bool CHWJpegV4L2Compressor::StreamOn() {
+ if (TestFlag(HWJPEG_FLAG_STREAMING)) return true;
if (!TestFlag(HWJPEG_FLAG_REQBUFS)) {
ALOGE("Trying to STREAMON before REQBUFS");
@@ -549,10 +583,8 @@ bool CHWJpegV4L2Compressor::StreamOn()
return true;
}
-bool CHWJpegV4L2Compressor::StreamOff()
-{
- if (!TestFlag(HWJPEG_FLAG_STREAMING))
- return true;
+bool CHWJpegV4L2Compressor::StreamOff() {
+ if (!TestFlag(HWJPEG_FLAG_STREAMING)) return true;
// error during stream off do not need further handling because of nothing to do
if (ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2SrcBuffer.type) < 0)
@@ -566,8 +598,7 @@ bool CHWJpegV4L2Compressor::StreamOff()
return true;
}
-bool CHWJpegV4L2Compressor::QBuf()
-{
+bool CHWJpegV4L2Compressor::QBuf() {
if (!TestFlag(HWJPEG_FLAG_REQBUFS)) {
ALOGE("QBuf is not permitted until REQBUFS is performed");
return false;
@@ -592,8 +623,7 @@ bool CHWJpegV4L2Compressor::QBuf()
return true;
}
-ssize_t CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size)
-{
+ssize_t CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size) {
bool failed = false;
v4l2_buffer buffer_src, buffer_dst;
v4l2_plane planes_src[6], planes_dst[2];
@@ -627,8 +657,7 @@ ssize_t CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size)
ClearFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
- if (failed)
- return -1;
+ if (failed) return -1;
if (!!((buffer_src.flags | buffer_dst.flags) & V4L2_BUF_FLAG_ERROR)) {
ALOGE("Error occurred during compression");
@@ -646,14 +675,12 @@ ssize_t CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size)
return GetStreamSize(secondary_stream_size);
}
-ssize_t CHWJpegV4L2Compressor::WaitForCompression(size_t *secondary_stream_size)
-{
+ssize_t CHWJpegV4L2Compressor::WaitForCompression(size_t *secondary_stream_size) {
return DQBuf(secondary_stream_size);
}
bool CHWJpegV4L2Compressor::GetImageBuffers(int buffers[], size_t len_buffers[],
- unsigned int num_buffers)
-{
+ unsigned int num_buffers) {
if (m_v4l2SrcBuffer.memory != V4L2_MEMORY_DMABUF) {
ALOGE("Current image buffer type is not dma-buf but attempted to retrieve dma-buf buffers");
return false;
@@ -661,7 +688,7 @@ bool CHWJpegV4L2Compressor::GetImageBuffers(int buffers[], size_t len_buffers[],
if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
ALOGE("Number of planes are %u but attemts to retrieve %u buffers",
- m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
+ m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
return false;
}
@@ -674,8 +701,7 @@ bool CHWJpegV4L2Compressor::GetImageBuffers(int buffers[], size_t len_buffers[],
}
bool CHWJpegV4L2Compressor::GetImageBuffers(char *buffers[], size_t len_buffers[],
- unsigned int num_buffers)
-{
+ unsigned int num_buffers) {
if (m_v4l2SrcBuffer.memory != V4L2_MEMORY_USERPTR) {
ALOGE("Current image buffer type is not userptr but attempted to retrieve userptr buffers");
return false;
@@ -683,7 +709,7 @@ bool CHWJpegV4L2Compressor::GetImageBuffers(char *buffers[], size_t len_buffers[
if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
ALOGE("Number of planes are %u but attemts to retrieve %u buffers",
- m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
+ m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
return false;
}
@@ -695,8 +721,7 @@ bool CHWJpegV4L2Compressor::GetImageBuffers(char *buffers[], size_t len_buffers[
return true;
}
-bool CHWJpegV4L2Compressor::GetJpegBuffer(int *buffer, size_t *len_buffer)
-{
+bool CHWJpegV4L2Compressor::GetJpegBuffer(int *buffer, size_t *len_buffer) {
if (m_v4l2DstBuffer.memory != V4L2_MEMORY_DMABUF) {
ALOGE("Current jpeg buffer type is not dma-buf but attempted to retrieve dma-buf buffer");
return false;
@@ -708,8 +733,7 @@ bool CHWJpegV4L2Compressor::GetJpegBuffer(int *buffer, size_t *len_buffer)
return true;
}
-bool CHWJpegV4L2Compressor::GetJpegBuffer(char **buffer, size_t *len_buffer)
-{
+bool CHWJpegV4L2Compressor::GetJpegBuffer(char **buffer, size_t *len_buffer) {
if (m_v4l2DstBuffer.memory != V4L2_MEMORY_USERPTR) {
ALOGE("Current jpeg buffer type is not userptr but attempted to retrieve userptr buffer");
return false;
@@ -721,8 +745,7 @@ bool CHWJpegV4L2Compressor::GetJpegBuffer(char **buffer, size_t *len_buffer)
return true;
}
-void CHWJpegV4L2Compressor::Release()
-{
+void CHWJpegV4L2Compressor::Release() {
StopStreaming();
}
@@ -730,8 +753,7 @@ void CHWJpegV4L2Compressor::Release()
/********* D E C O M P R E S S I O N S U P P O R T **************************/
/******************************************************************************/
-CHWJpegV4L2Decompressor::CHWJpegV4L2Decompressor() : CHWJpegDecompressor("/dev/video12")
-{
+CHWJpegV4L2Decompressor::CHWJpegV4L2Decompressor() : CHWJpegDecompressor("/dev/video12") {
m_v4l2Format.type = 0; // inidication of uninitialized state
memset(&m_v4l2DstBuffer, 0, sizeof(m_v4l2DstBuffer));
@@ -748,21 +770,18 @@ CHWJpegV4L2Decompressor::CHWJpegV4L2Decompressor() : CHWJpegDecompressor("/dev/v
}
}
-CHWJpegV4L2Decompressor::~CHWJpegV4L2Decompressor()
-{
+CHWJpegV4L2Decompressor::~CHWJpegV4L2Decompressor() {
CancelCapture();
}
-bool CHWJpegV4L2Decompressor::PrepareCapture()
-{
+bool CHWJpegV4L2Decompressor::PrepareCapture() {
if (m_v4l2DstBuffer.length < m_v4l2Format.fmt.pix.sizeimage) {
- ALOGE("The size of the buffer %u is smaller than required %u",
- m_v4l2DstBuffer.length, m_v4l2Format.fmt.pix.sizeimage);
+ ALOGE("The size of the buffer %u is smaller than required %u", m_v4l2DstBuffer.length,
+ m_v4l2Format.fmt.pix.sizeimage);
return false;
}
- if (TestFlag(HWJPEG_FLAG_CAPTURE_READY))
- return true;
+ if (TestFlag(HWJPEG_FLAG_CAPTURE_READY)) return true;
v4l2_requestbuffers reqbufs;
@@ -788,10 +807,8 @@ bool CHWJpegV4L2Decompressor::PrepareCapture()
return true;
}
-void CHWJpegV4L2Decompressor::CancelCapture()
-{
- if (!TestFlag(HWJPEG_FLAG_CAPTURE_READY))
- return;
+void CHWJpegV4L2Decompressor::CancelCapture() {
+ if (!TestFlag(HWJPEG_FLAG_CAPTURE_READY)) return;
v4l2_requestbuffers reqbufs;
@@ -805,14 +822,12 @@ void CHWJpegV4L2Decompressor::CancelCapture()
ClearFlag(HWJPEG_FLAG_CAPTURE_READY);
}
-bool CHWJpegV4L2Decompressor::SetImageFormat(unsigned int v4l2_fmt,
- unsigned int width, unsigned int height)
-{
+bool CHWJpegV4L2Decompressor::SetImageFormat(unsigned int v4l2_fmt, unsigned int width,
+ unsigned int height) {
// Test if new format is the same as the current configured format
if (m_v4l2Format.type != 0) {
v4l2_pix_format *p = &m_v4l2Format.fmt.pix;
- if ((p->pixelformat == v4l2_fmt) &&
- (p->width == width) && (p->height == height))
+ if ((p->pixelformat == v4l2_fmt) && (p->width == width) && (p->height == height))
return true;
}
@@ -826,16 +841,14 @@ bool CHWJpegV4L2Decompressor::SetImageFormat(unsigned int v4l2_fmt,
m_v4l2Format.fmt.pix.height = height;
if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &m_v4l2Format) < 0) {
- ALOGERR("Failed to S_FMT for decompressed image (%08X,%ux%u)",
- v4l2_fmt, width, height);
+ ALOGERR("Failed to S_FMT for decompressed image (%08X,%ux%u)", v4l2_fmt, width, height);
return false;
}
return true;
}
-bool CHWJpegV4L2Decompressor::SetImageBuffer(char *buffer, size_t len_buffer)
-{
+bool CHWJpegV4L2Decompressor::SetImageBuffer(char *buffer, size_t len_buffer) {
m_v4l2DstBuffer.m.userptr = reinterpret_cast<unsigned long>(buffer);
m_v4l2DstBuffer.bytesused = m_v4l2Format.fmt.pix.sizeimage;
m_v4l2DstBuffer.length = len_buffer;
@@ -844,8 +857,7 @@ bool CHWJpegV4L2Decompressor::SetImageBuffer(char *buffer, size_t len_buffer)
return true;
}
-bool CHWJpegV4L2Decompressor::SetImageBuffer(int buffer, size_t len_buffer)
-{
+bool CHWJpegV4L2Decompressor::SetImageBuffer(int buffer, size_t len_buffer) {
m_v4l2DstBuffer.m.fd = buffer;
m_v4l2DstBuffer.bytesused = m_v4l2Format.fmt.pix.sizeimage;
m_v4l2DstBuffer.length = len_buffer;
@@ -854,10 +866,8 @@ bool CHWJpegV4L2Decompressor::SetImageBuffer(int buffer, size_t len_buffer)
return true;
}
-bool CHWJpegV4L2Decompressor::PrepareStream()
-{
- if (TestFlag(HWJPEG_FLAG_OUTPUT_READY))
- return true;
+bool CHWJpegV4L2Decompressor::PrepareStream() {
+ if (TestFlag(HWJPEG_FLAG_OUTPUT_READY)) return true;
/*
* S_FMT for output stream is unneccessary because the driver assumes that
@@ -893,10 +903,8 @@ bool CHWJpegV4L2Decompressor::PrepareStream()
return true;
}
-void CHWJpegV4L2Decompressor::CancelStream()
-{
- if (!TestFlag(HWJPEG_FLAG_OUTPUT_READY))
- return;
+void CHWJpegV4L2Decompressor::CancelStream() {
+ if (!TestFlag(HWJPEG_FLAG_OUTPUT_READY)) return;
v4l2_requestbuffers rb;
memset(&rb, 0, sizeof(rb));
@@ -911,8 +919,7 @@ void CHWJpegV4L2Decompressor::CancelStream()
ClearFlag(HWJPEG_FLAG_OUTPUT_READY);
}
-bool CHWJpegV4L2Decompressor::QBufAndWait(const char *buffer, size_t len)
-{
+bool CHWJpegV4L2Decompressor::QBufAndWait(const char *buffer, size_t len) {
v4l2_buffer buf;
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
@@ -952,8 +959,7 @@ bool CHWJpegV4L2Decompressor::QBufAndWait(const char *buffer, size_t len)
return ret;
}
-bool CHWJpegV4L2Decompressor::Decompress(const char *buffer, size_t len)
-{
+bool CHWJpegV4L2Decompressor::Decompress(const char *buffer, size_t len) {
if (m_v4l2Format.type == 0) {
ALOGE("Decompressed image format is not specified");
return false;
@@ -966,11 +972,9 @@ bool CHWJpegV4L2Decompressor::Decompress(const char *buffer, size_t len)
// Do not change the order of PrepareCapture() and PrepareStream().
// Otherwise, decompression will fail.
- if (!PrepareCapture() || !PrepareStream())
- return false;
+ if (!PrepareCapture() || !PrepareStream()) return false;
- if (!QBufAndWait(buffer, len))
- return false;
+ if (!QBufAndWait(buffer, len)) return false;
return true;
}
diff --git a/libhwjpeg/include/ExynosJpegApi.h b/libhwjpeg/include/ExynosJpegApi.h
index a82b65b..dcf06b3 100644
--- a/libhwjpeg/include/ExynosJpegApi.h
+++ b/libhwjpeg/include/ExynosJpegApi.h
@@ -33,7 +33,7 @@
#endif
#define JPEG_BUF_TYPE_USER_PTR 1
-#define JPEG_BUF_TYPE_DMA_BUF 2
+#define JPEG_BUF_TYPE_DMA_BUF 2
// CUSTOM V4L2 4CC FORMATS FOR LEGACY JPEG LIBRARY AND DRIVERS
#ifndef V4L2_PIX_FMT_JPEG_444
@@ -78,11 +78,12 @@ class ExynosJpegEncoder {
int m_nStreamSize;
bool __EnsureFormatIsApplied();
+
protected:
enum {
- STATE_SIZE_CHANGED = 1 << 0,
- STATE_PIXFMT_CHANGED = 1 << 1,
- STATE_BASE_MAX = 1 << 16,
+ STATE_SIZE_CHANGED = 1 << 0,
+ STATE_PIXFMT_CHANGED = 1 << 1,
+ STATE_BASE_MAX = 1 << 16,
};
unsigned int GetDeviceCapabilities() { return m_hwjpeg.GetDeviceCapabilities(); }
@@ -95,16 +96,29 @@ protected:
bool TestStateEither(unsigned int state) { return (m_uiState & state) != 0; }
virtual bool EnsureFormatIsApplied() { return __EnsureFormatIsApplied(); }
+
public:
- ExynosJpegEncoder(): m_hwjpeg(),
- m_iInBufType(JPEG_BUF_TYPE_USER_PTR), m_iOutBufType(JPEG_BUF_TYPE_USER_PTR), m_uiState(0),
- m_nQFactor(0), m_nWidth(0), m_nHeight(0), m_v4l2Format(0), m_jpegFormat(0), m_nStreamSize(0)
- {
+ ExynosJpegEncoder()
+ : m_hwjpeg(),
+ m_iInBufType(JPEG_BUF_TYPE_USER_PTR),
+ m_iOutBufType(JPEG_BUF_TYPE_USER_PTR),
+ m_uiState(0),
+ m_nQFactor(0),
+ m_nWidth(0),
+ m_nHeight(0),
+ m_v4l2Format(0),
+ m_jpegFormat(0),
+ m_nStreamSize(0) {
/* To detect setInBuf() call without format setting */
SetState(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED);
}
virtual ~ExynosJpegEncoder() { destroy(); }
+ // Acquire exclusive lock to V4L2 device. This is a blocking call.
+ int lock();
+ // Release exclusive lock to V4L2 device.
+ int unlock();
+
// Return 0 on success, -1 on error
int flagCreate() { return m_hwjpeg.Okay() ? 0 : -1; }
virtual int create(void) { return flagCreate(); }
@@ -113,7 +127,7 @@ public:
int setCache(int __unused val) { return 0; }
void *getJpegConfig() { return reinterpret_cast<void *>(this); }
- int setJpegConfig(void* pConfig);
+ int setJpegConfig(void *pConfig);
int checkInBufType(void) { return m_iInBufType; }
int checkOutBufType(void) { return m_iOutBufType; }
@@ -155,26 +169,24 @@ public:
int setQuality(int iQuality) {
if (m_nQFactor != iQuality) {
- if (!m_hwjpeg.SetQuality(static_cast<unsigned int>(iQuality)))
- return -1;
+ if (!m_hwjpeg.SetQuality(static_cast<unsigned int>(iQuality))) return -1;
m_nQFactor = iQuality;
}
return 0;
}
int setQuality(const unsigned char q_table[]);
+ int setPadding(unsigned char *padding, unsigned int num_planes);
int setColorBufSize(int *piBufSize, int iSize);
int getJpegSize(void) { return m_nStreamSize; }
int encode(void) {
- if (!__EnsureFormatIsApplied())
- return false;
+ if (!__EnsureFormatIsApplied()) return false;
m_nStreamSize = static_cast<int>(m_hwjpeg.Compress());
return (m_nStreamSize < 0) ? -1 : 0;
}
-
};
#endif //__HARDWARE_EXYNOS_EXYNOS_JPEG_API_H__
diff --git a/libhwjpeg/include/ExynosJpegEncoderForCamera.h b/libhwjpeg/include/ExynosJpegEncoderForCamera.h
index a50d884..e7a2eec 100644
--- a/libhwjpeg/include/ExynosJpegEncoderForCamera.h
+++ b/libhwjpeg/include/ExynosJpegEncoderForCamera.h
@@ -18,18 +18,18 @@
#ifndef __HARDWARE_EXYNOS_JPEG_ENCODER_FOR_CAMERA_H__
#define __HARDWARE_EXYNOS_JPEG_ENCODER_FOR_CAMERA_H__
-#include <memory>
-
+#include <ExynosExif.h>
+#include <hardware/exynos/ExynosExif.h>
#include <pthread.h>
-#include <ExynosExif.h>
+#include <memory>
+
#include "ExynosJpegApi.h"
-#include <hardware/exynos/ExynosExif.h>
class CAppMarkerWriter; // defined in libhwjpeg/AppMarkerWriter.h
-class ThumbnailScaler; // defined in libhwjpeg/thumbnail_scaler.h
+class ThumbnailScaler; // defined in libhwjpeg/thumbnail_scaler.h
-class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
+class ExynosJpegEncoderForCamera : public ExynosJpegEncoder {
enum {
STATE_THUMBSIZE_CHANGED = STATE_BASE_MAX << 0,
STATE_HWFC_ENABLED = STATE_BASE_MAX << 1,
@@ -64,7 +64,7 @@ class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
union {
char *m_pThumbnailImageBuffer[3]; // checkInBufType() == JPEG_BUF_TYPE_USER_PTR
- int m_fdThumbnailImageBuffer[3]; // checkInBufType() == JPEG_BUF_TYPE_DMA_BUF
+ int m_fdThumbnailImageBuffer[3]; // checkInBufType() == JPEG_BUF_TYPE_DMA_BUF
};
size_t m_szThumbnailImageLen[3];
@@ -76,10 +76,11 @@ class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
app_info_t m_appInfo[15];
bool AllocThumbBuffer(int v4l2Format); /* For single compression */
- bool AllocThumbJpegBuffer(); /* For BTB compression */
+ bool AllocThumbJpegBuffer(); /* For BTB compression */
bool GenerateThumbnailImage();
size_t CompressThumbnail();
- size_t CompressThumbnailOnly(size_t limit, int quality, unsigned int v4l2Format, int src_buftype);
+ size_t CompressThumbnailOnly(size_t limit, int quality, unsigned int v4l2Format,
+ int src_buftype);
size_t RemoveTrailingDummies(char *base, size_t len);
ssize_t FinishCompression(size_t mainlen, size_t thumblen);
bool ProcessExif(char *base, size_t limit, exif_attribute_t *exifInfo, extra_appinfo_t *extra);
@@ -87,28 +88,35 @@ class ExynosJpegEncoderForCamera: public ExynosJpegEncoder {
bool PrepareCompression(bool thumbnail);
// IsThumbGenerationNeeded - true if thumbnail image needed to be generated from the main image
- // It also implies that a worker thread is generated to generate thumbnail concurrently.
+ // It also implies that a worker thread is generated to generate
+ // thumbnail concurrently.
inline bool IsThumbGenerationNeeded() { return !TestState(STATE_NO_CREATE_THUMBIMAGE); }
inline void NoThumbGenerationNeeded() { SetState(STATE_NO_CREATE_THUMBIMAGE); }
inline void ThumbGenerationNeeded() { ClearState(STATE_NO_CREATE_THUMBIMAGE); }
inline bool IsBTBCompressionSupported() {
return !!(GetDeviceCapabilities() & V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION) &&
- !TestState(STATE_NO_BTBCOMP);
+ !TestState(STATE_NO_BTBCOMP);
}
+
protected:
virtual bool EnsureFormatIsApplied();
+
public:
ExynosJpegEncoderForCamera(bool bBTBComp = true);
virtual ~ExynosJpegEncoderForCamera();
- int encode(int *size, exif_attribute_t *exifInfo, char** pcJpegBuffer, debug_attribute_t *debugInfo = 0);
- int encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer, char** pcJpegBuffer, debug_attribute_t *debugInfo = 0);
- int encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer, char** pcJpegBuffer, extra_appinfo_t *appInfo = 0);
+ int encode(int *size, exif_attribute_t *exifInfo, char **pcJpegBuffer,
+ debug_attribute_t *debugInfo = 0);
+ int encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer, char **pcJpegBuffer,
+ debug_attribute_t *debugInfo = 0);
+ int encode(int *size, exif_attribute_t *exifInfo, int fdJpegBuffer, char **pcJpegBuffer,
+ extra_appinfo_t *appInfo = 0);
int setInBuf2(int *piBuf, int *iSize);
int setInBuf2(char **pcBuf, int *iSize);
int setThumbnailSize(int w, int h);
int setThumbnailQuality(int quality);
+ int setThumbnailPadding(unsigned char *padding, unsigned int num_planes);
void setExtScalerNum(int csc_hwscaler_id) { m_iHWScalerID = csc_hwscaler_id; }
diff --git a/libhwjpeg/include/FileLock.h b/libhwjpeg/include/FileLock.h
new file mode 100644
index 0000000..b308aa7
--- /dev/null
+++ b/libhwjpeg/include/FileLock.h
@@ -0,0 +1,16 @@
+#include "android-base/thread_annotations.h"
+
+// Encapsulates advisory file lock for a given field descriptor
+class CAPABILITY("mutex") FileLock {
+public:
+ FileLock(int fd);
+ ~FileLock() = default;
+
+ // Acquires advisory file lock. This will block.
+ int lock() ACQUIRE();
+ // Releases advisory file lock.
+ int unlock() RELEASE();
+
+private:
+ int fd_;
+}; \ No newline at end of file
diff --git a/libhwjpeg/include/exynos-hwjpeg.h b/libhwjpeg/include/exynos-hwjpeg.h
index 04ffed4..45114b5 100644
--- a/libhwjpeg/include/exynos-hwjpeg.h
+++ b/libhwjpeg/include/exynos-hwjpeg.h
@@ -18,46 +18,38 @@
#ifndef __EXYNOS_HWJPEG_H__
#define __EXYNOS_HWJPEG_H__
+#include <linux/videodev2.h>
+
#include <cstddef> // size_t
-/*
- * exynos-hwjpeg.h does not include videodev2.h because Exynos HAL code may
- * define its version of videodev2.h that may differ from <linux/videodev2.h>
- * of the current Linux version.
- * To prevent conflict different versions of videodev2.h, this header file does
- * not include videodev2.h even though it depends on the data types defined in
- * videodev2.h.
- * Therefore, the source files that include this header file, they should
- * include their proper version of videodev2.h.
- */
-#ifndef VIDEO_MAX_PLANES
-#error 'linux/videodev2.h' should be included before 'exynos-hwjpeg.h'
-#endif
#if VIDEO_MAX_PLANES < 6
#error VIDEO_MAX_PLANES should not be smaller than 6
#endif
+#include "FileLock.h"
+#include "android-base/thread_annotations.h"
+
// Exynos JPEG specific device capabilities
// Defined in the driver. Not in videodev2.h
-#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION 0x0100
-#define V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION 0x0200
-#define V4L2_CAP_EXYNOS_JPEG_HWFC 0x0400
-#define V4L2_CAP_EXYNOS_JPEG_HWFC_EMBEDDED 0x0800
-#define V4L2_CAP_EXYNOS_JPEG_MAX_STREAMSIZE 0x1000
+#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION 0x0100
+#define V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION 0x0200
+#define V4L2_CAP_EXYNOS_JPEG_HWFC 0x0400
+#define V4L2_CAP_EXYNOS_JPEG_HWFC_EMBEDDED 0x0800
+#define V4L2_CAP_EXYNOS_JPEG_MAX_STREAMSIZE 0x1000
#define V4L2_CAP_EXYNOS_JPEG_NO_STREAMBASE_ALIGN 0x2000
-#define V4L2_CAP_EXYNOS_JPEG_NO_IMAGEBASE_ALIGN 0x4000
-#define V4L2_CAP_EXYNOS_JPEG_NO_BUFFER_OVERRUN 0x8000
+#define V4L2_CAP_EXYNOS_JPEG_NO_IMAGEBASE_ALIGN 0x4000
+#define V4L2_CAP_EXYNOS_JPEG_NO_BUFFER_OVERRUN 0x8000
#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION_FROM_SOS 0x10000
-#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION_CROP 0x20000
-#define V4L2_CAP_EXYNOS_JPEG_DOWNSCALING 0x40000
-#define V4L2_CAP_EXYNOS_JPEG_DMABUF_OFFSET 0x80000
+#define V4L2_CAP_EXYNOS_JPEG_DECOMPRESSION_CROP 0x20000
+#define V4L2_CAP_EXYNOS_JPEG_DOWNSCALING 0x40000
+#define V4L2_CAP_EXYNOS_JPEG_DMABUF_OFFSET 0x80000
// EXYNOS HWJPEG specific auxiliary option flags
// The flags are common to all derived classes of CHWJpegCompressor
// but if a derived class does not support for a specified flag,
// it is discarded and ignored silently.
-#define EXYNOS_HWJPEG_AUXOPT_ENABLE_HWFC (1 << 4)
-#define EXYNOS_HWJPEG_AUXOPT_SRC_NOCACHECLEAN (1 << 8)
-#define EXYNOS_HWJPEG_AUXOPT_DST_NOCACHECLEAN (1 << 9)
+#define EXYNOS_HWJPEG_AUXOPT_ENABLE_HWFC (1 << 4)
+#define EXYNOS_HWJPEG_AUXOPT_SRC_NOCACHECLEAN (1 << 8)
+#define EXYNOS_HWJPEG_AUXOPT_DST_NOCACHECLEAN (1 << 9)
/*
* CHWJpegBase - The base class of JPEG compression and decompression
@@ -81,15 +73,19 @@ class CHWJpegBase {
*
*/
unsigned int m_uiAuxFlags;
+
protected:
CHWJpegBase(const char *path);
virtual ~CHWJpegBase();
int GetDeviceFD() { return m_iFD; }
void SetDeviceCapabilities(unsigned int cap) { m_uiDeviceCaps = cap; }
unsigned int GetAuxFlags() { return m_uiAuxFlags; }
+
public:
unsigned int GetDeviceCapabilities() { return m_uiDeviceCaps; }
- bool IsDeviceCapability(unsigned int cap_flags) { return (m_uiDeviceCaps & cap_flags) == cap_flags; }
+ bool IsDeviceCapability(unsigned int cap_flags) {
+ return (m_uiDeviceCaps & cap_flags) == cap_flags;
+ }
/*
* Okay - Test if the object is correctly initialized
@@ -144,6 +140,7 @@ public:
class CHWJpegCompressor : public CHWJpegBase {
size_t m_nLastStreamSize;
size_t m_nLastThumbStreamSize;
+
protected:
void SetStreamSize(size_t main_size, size_t secondary_size = 0) {
m_nLastStreamSize = main_size;
@@ -151,20 +148,23 @@ protected:
}
ssize_t GetStreamSize(size_t *secondary_size) {
- if (secondary_size)
- *secondary_size = m_nLastThumbStreamSize;
+ if (secondary_size) *secondary_size = m_nLastThumbStreamSize;
return static_cast<ssize_t>(m_nLastStreamSize);
}
+
public:
- CHWJpegCompressor(const char *path): CHWJpegBase(path), m_nLastStreamSize(0), m_nLastThumbStreamSize(0) { }
+ CHWJpegCompressor(const char *path)
+ : CHWJpegBase(path), m_nLastStreamSize(0), m_nLastThumbStreamSize(0) {}
/*
* SetImageFormat - Configure uncompressed image format, width and height
* @v4l2_fmt[in] : Image pixel format defined in <linux/videodev2.h>
* @width[in] : Width of the primary uncompressed image in the number of pixels
* @height[in] : Height of the primary uncompressed image in the number of pixels
- * @sec_width[in] : Width of the secondary uncompressed image in the number of pixels (optional)
- * @sec_height[in] : Height of the secondary uncompressed image in the number of pixels (optional)
+ * @sec_width[in] : Width of the secondary uncompressed image in the number of pixels
+ * (optional)
+ * @sec_height[in] : Height of the secondary uncompressed image in the number of pixels
+ * (optional)
* @return : true if configuration of image pixel format and size is successful.
* false, otherwise.
*
@@ -172,7 +172,7 @@ public:
* to configure different image formats for them.
*/
virtual bool SetImageFormat(unsigned int v4l2_fmt, unsigned int width, unsigned int height,
- unsigned int sec_width = 0, unsigned int sec_height = 0) = 0;
+ unsigned int sec_width = 0, unsigned int sec_height = 0) = 0;
/*
* GetImageBufferSizes - Ask the required buffer sizes for the given image format
@@ -196,7 +196,8 @@ public:
virtual bool SetChromaSampFactor(unsigned int horizontal, unsigned int vertical) = 0;
/*
* SetQuality - Configure quality factor for JPEG compression
- * @quality_factor[in] : JPEG compression quality factor between 1 and 100 for the primary image
+ * @quality_factor[in] : JPEG compression quality factor between 1 and 100 for the primary
+ * image
* @quality_factor2[in] : JPEG compression quality factor for the secondary image (optional)
* @return: true if quality factors are configured successfully.
* false, otherwise.
@@ -214,6 +215,24 @@ public:
*/
virtual bool SetQuality(const unsigned char __unused qtable[]) { return false; };
/*
+ * SetPadding - Configures padding per plane for primary image
+ * @padding[in] : Padding per plane
+ * @num_planes[in] : Number of planes. This should match the number of elements in @padding
+ * @return : true if padding is congured successfully.
+ * false, otherwise.
+ */
+ virtual bool SetPadding(unsigned char padding[], unsigned int num_planes) = 0;
+ /*
+ * SetPadding2 - Configures padding per plane for thumbnail image
+ * @padding[in] : padding per plane
+ * @num_planes[in] : Number of planes. This should match the number of elements in @padding
+ * @return : true if padding is congured successfully.
+ * false, otherwise.
+ */
+ virtual bool SetPadding2(unsigned char __unused padding[], unsigned int __unused num_planes) {
+ return false;
+ }
+ /*
* SetImageBuffer - Configure the uncompressed primary image buffers (userptr)
* @buffers[in] : addresses of the buffers
* @len_buffers[in] : sizes of the buffers
@@ -221,7 +240,8 @@ public:
* @return : true if buffer configuration is successful.
* false, otherwise.
*/
- virtual bool SetImageBuffer(char *buffers[], size_t len_buffers[], unsigned int num_buffers) = 0;
+ virtual bool SetImageBuffer(char *buffers[], size_t len_buffers[],
+ unsigned int num_buffers) = 0;
/*
* SetImageBuffer - Configure the uncompressed primary image buffers (dmabuf)
* @buffers[in] : file descriptors of the buffers exported by dma-buf
@@ -239,7 +259,10 @@ public:
* @return : true if buffer configuration is successful.
* false, otherwise.
*/
- virtual bool SetImageBuffer2(char __unused *buffers[], size_t __unused len_buffers[], unsigned int __unused num_buffers) { return false; }
+ virtual bool SetImageBuffer2(char __unused *buffers[], size_t __unused len_buffers[],
+ unsigned int __unused num_buffers) {
+ return false;
+ }
/*
* SetImageBuffer2 - Configure the uncompressed secondary image buffers (dmabuf)
* @buffers[in] : file descriptors of the buffers exported by dma-buf
@@ -248,7 +271,10 @@ public:
* @return : true if buffer configuration is successful.
* false, otherwise.
*/
- virtual bool SetImageBuffer2(int __unused buffers[], size_t __unused len_buffers[], unsigned int __unused num_buffers) { return false; }
+ virtual bool SetImageBuffer2(int __unused buffers[], size_t __unused len_buffers[],
+ unsigned int __unused num_buffers) {
+ return false;
+ }
/*
* SetJpegBuffer - Configure the buffer of JPEG stream of the primary image (userptr)
* @buffer [in] : The address of the buffer
@@ -311,7 +337,9 @@ public:
* returns and the returned size will be the stream sizes obtained by the last call to
* Compress().
*/
- virtual ssize_t WaitForCompression(size_t __unused *secondary_stream_size = NULL) { return GetStreamSize(secondary_stream_size); }
+ virtual ssize_t WaitForCompression(size_t __unused *secondary_stream_size = NULL) {
+ return GetStreamSize(secondary_stream_size);
+ }
/*
* GetImageBuffers - Retrieve the configured uncompressed image buffer information (dmabuf)
* @buffers[out]: The file descriptors of the buffers exported by dma-buf
@@ -322,7 +350,10 @@ public:
* DEPREDCATED. DO NOT USE THIS FUNCTION.
* This function is just provided to support the legacy ExynosJpegEncoder API.
*/
- virtual bool GetImageBuffers(int __unused buffers[], size_t __unused len_buffers[], unsigned int __unused num_buffers) { return false; }
+ virtual bool GetImageBuffers(int __unused buffers[], size_t __unused len_buffers[],
+ unsigned int __unused num_buffers) {
+ return false;
+ }
/*
* GetImageBuffers - Retrieve the configured uncompressed image buffer information (userptr)
* @buffers[out]: The addresses of the buffers
@@ -333,7 +364,10 @@ public:
* DEPREDCATED. DO NOT USE THIS FUNCTION.
* This function is just provided to support the legacy ExynosJpegEncoder API.
*/
- virtual bool GetImageBuffers(char __unused *buffers[], size_t __unused len_buffers[], unsigned int __unused num_buffers) { return false; }
+ virtual bool GetImageBuffers(char __unused *buffers[], size_t __unused len_buffers[],
+ unsigned int __unused num_buffers) {
+ return false;
+ }
/*
* GetJpegBuffers - Retrieve the configured JPEG stream image buffer information (dmabuf)
* @buffers[out]: The file descriptor of the buffer exported by dma-buf
@@ -353,11 +387,13 @@ public:
* DEPREDCATED. DO NOT USE THIS FUNCTION.
* This function is just provided to support the legacy ExynosJpegEncoder API.
*/
- virtual bool GetJpegBuffer(char __unused **buffers, size_t __unused *len_buffer) { return false; }
+ virtual bool GetJpegBuffer(char __unused **buffers, size_t __unused *len_buffer) {
+ return false;
+ }
/*
* Release - release the buffers acquired by CHWJpegCompressor
*/
- virtual void Release() { }
+ virtual void Release() {}
};
/*
@@ -381,8 +417,8 @@ public:
*/
class CHWJpegDecompressor : public CHWJpegBase {
public:
- CHWJpegDecompressor(const char *path) : CHWJpegBase(path) { }
- virtual ~CHWJpegDecompressor() { }
+ CHWJpegDecompressor(const char *path) : CHWJpegBase(path) {}
+ virtual ~CHWJpegDecompressor() {}
/*
* SetImageFormat - Configure decompressed image pixel format
* @v4l2_fmt[in] : Image pixel format defined in <linux/videodev2.h>
@@ -424,7 +460,9 @@ public:
* @width[in] : The number of horizontal pixels of the compressed image
* @height[in] : The number of vertical pixels of the compressed image
*/
- virtual bool SetStreamPixelSize(unsigned int __unused width, unsigned int __unused height) { return true; }
+ virtual bool SetStreamPixelSize(unsigned int __unused width, unsigned int __unused height) {
+ return true;
+ }
/*
* SetChromaSampFactor - Configure the chroma subsampling factor for JPEG stream
@@ -441,7 +479,10 @@ public:
* If it is required to specify chroma subsampling factors separately, you should
* override SetChromaSampFactor().
*/
- virtual bool SetChromaSampFactor(unsigned int __unused horizontal, unsigned int __unused vertical) { return true; }
+ virtual bool SetChromaSampFactor(unsigned int __unused horizontal,
+ unsigned int __unused vertical) {
+ return true;
+ }
/*
* SetDQT - Configure the address of DQT
@@ -484,8 +525,9 @@ public:
class CHWJpegFlagManager {
unsigned int m_uiHWConfigFlags;
+
public:
- CHWJpegFlagManager() : m_uiHWConfigFlags(0) { }
+ CHWJpegFlagManager() : m_uiHWConfigFlags(0) {}
void SetFlag(unsigned int flag) { m_uiHWConfigFlags |= flag; }
void ClearFlag(unsigned int flag) { m_uiHWConfigFlags &= ~flag; }
bool TestFlag(unsigned int flag) { return (m_uiHWConfigFlags & flag) == flag; }
@@ -497,7 +539,7 @@ class CHWJpegM2M1SHOTCompressor: public CHWJpegCompressor {
};
*/
-#define TO_SEC_IMG_SIZE(val) (((val) >> 16) & 0xFFFF)
+#define TO_SEC_IMG_SIZE(val) (((val) >> 16) & 0xFFFF)
class CHWJpegV4L2Compressor : public CHWJpegCompressor, private CHWJpegFlagManager {
enum {
@@ -505,20 +547,22 @@ class CHWJpegV4L2Compressor : public CHWJpegCompressor, private CHWJpegFlagManag
HWJPEG_CTRL_QFACTOR,
HWJPEG_CTRL_QFACTOR2,
HWJPEG_CTRL_HWFC,
+ HWJPEG_CTRL_PADDING,
+ HWJPEG_CTRL_PADDING2,
HWJPEG_CTRL_NUM,
};
- enum {
- HWJPEG_FLAG_PIX_FMT = 0x1, // Set if unapplied image format exists
+ enum {
+ HWJPEG_FLAG_PIX_FMT = 0x1, // Set if unapplied image format exists
- HWJPEG_FLAG_QBUF_OUT = 0x100, // Set if the image buffer is queued
- HWJPEG_FLAG_QBUF_CAP = 0x200, // Set if the JPEG stream buffer is queued
- HWJPEG_FLAG_REQBUFS = 0x400,
- HWJPEG_FLAG_STREAMING = 0x800,
+ HWJPEG_FLAG_QBUF_OUT = 0x100, // Set if the image buffer is queued
+ HWJPEG_FLAG_QBUF_CAP = 0x200, // Set if the JPEG stream buffer is queued
+ HWJPEG_FLAG_REQBUFS = 0x400,
+ HWJPEG_FLAG_STREAMING = 0x800,
- HWJPEG_FLAG_SRC_BUFFER = 0x10000, // Set if SetImageBuffer() is invoked successfully
+ HWJPEG_FLAG_SRC_BUFFER = 0x10000, // Set if SetImageBuffer() is invoked successfully
HWJPEG_FLAG_SRC_BUFFER2 = 0x20000, // Set if SetImageBuffer2() is invoked successfully
- HWJPEG_FLAG_DST_BUFFER = 0x40000, // Set if SetJpegBuffer() is invoked successfully
+ HWJPEG_FLAG_DST_BUFFER = 0x40000, // Set if SetJpegBuffer() is invoked successfully
HWJPEG_FLAG_DST_BUFFER2 = 0x80000, // Set if SetJpegBuffer2() is invoked successfully
};
@@ -532,7 +576,7 @@ class CHWJpegV4L2Compressor : public CHWJpegCompressor, private CHWJpegFlagManag
// Only valid after Compression() successes.
unsigned int m_uiHWDelay;
- v4l2_format m_v4l2Format; // v4l2 format for the source image
+ v4l2_format m_v4l2Format; // v4l2 format for the source image
v4l2_buffer m_v4l2SrcBuffer; // v4l2 source buffer
v4l2_plane m_v4l2SrcPlanes[6];
v4l2_buffer m_v4l2DstBuffer;
@@ -540,9 +584,11 @@ class CHWJpegV4L2Compressor : public CHWJpegCompressor, private CHWJpegFlagManag
bool m_bEnableHWFC;
+ FileLock file_lock_;
+
bool IsB2BCompression() {
return (TO_SEC_IMG_SIZE(m_v4l2Format.fmt.pix_mp.width) +
- TO_SEC_IMG_SIZE(m_v4l2Format.fmt.pix_mp.height)) != 0;
+ TO_SEC_IMG_SIZE(m_v4l2Format.fmt.pix_mp.height)) != 0;
}
// V4L2 Helpers
@@ -555,21 +601,28 @@ class CHWJpegV4L2Compressor : public CHWJpegCompressor, private CHWJpegFlagManag
bool QBuf();
ssize_t DQBuf(size_t *secondary_stream_size);
bool StopStreaming();
+
public:
CHWJpegV4L2Compressor();
virtual ~CHWJpegV4L2Compressor();
+ // Acquires exclusive lock to V4L2 device. This must be called before starting image
+ // configuration. This is a blocking call.
+ int lock();
+ // Releases exclusive lock to V4L2 device. This should be called after encoding is complete.
+ int unlock();
+
unsigned int GetHWDelay() { return m_uiHWDelay; }
// SetChromaSampFactor can be called during streaming
- virtual bool SetChromaSampFactor(unsigned int horizontal,
- unsigned int vertical);
- virtual bool SetQuality(unsigned int quality_factor,
- unsigned int quality_factor2 = 0);
+ virtual bool SetChromaSampFactor(unsigned int horizontal, unsigned int vertical);
+ virtual bool SetQuality(unsigned int quality_factor, unsigned int quality_factor2 = 0);
virtual bool SetQuality(const unsigned char qtable[]);
+ virtual bool SetPadding(unsigned char padding[], unsigned int num_planes);
+ virtual bool SetPadding2(unsigned char padding[], unsigned int num_planes);
virtual bool SetImageFormat(unsigned int v4l2_fmt, unsigned int width, unsigned int height,
- unsigned int sec_width = 0, unsigned sec_height = 0);
+ unsigned int sec_width = 0, unsigned sec_height = 0);
virtual bool GetImageBufferSizes(size_t buf_sizes[], unsigned int *num_bufffers);
virtual bool SetImageBuffer(char *buffers[], size_t len_buffers[], unsigned int num_buffers);
virtual bool SetImageBuffer(int buffers[], size_t len_buffers[], unsigned int num_buffers);
@@ -589,8 +642,8 @@ public:
};
class CHWJpegV4L2Decompressor : public CHWJpegDecompressor, private CHWJpegFlagManager {
- enum {
- HWJPEG_FLAG_OUTPUT_READY = 0x10, /* the output stream is ready */
+ enum {
+ HWJPEG_FLAG_OUTPUT_READY = 0x10, /* the output stream is ready */
HWJPEG_FLAG_CAPTURE_READY = 0x20, /* the capture stream is ready */
};
@@ -605,6 +658,7 @@ class CHWJpegV4L2Decompressor : public CHWJpegDecompressor, private CHWJpegFlagM
bool PrepareStream();
void CancelStream();
bool QBufAndWait(const char *buffer, size_t len);
+
public:
CHWJpegV4L2Decompressor();
virtual ~CHWJpegV4L2Decompressor();
diff --git a/libhwjpeg/include/hwjpeglib-exynos.h b/libhwjpeg/include/hwjpeglib-exynos.h
index ba95320..5d23630 100644
--- a/libhwjpeg/include/hwjpeglib-exynos.h
+++ b/libhwjpeg/include/hwjpeglib-exynos.h
@@ -25,16 +25,19 @@ extern "C" {
* hwjpeg_decompress_ptr - handle of decompressor instance
*/
typedef struct hwjpeg_decompressor_struct {
- unsigned int image_width; /* width of the compressed image */
- unsigned int image_height; /* height of the compressed image */
- unsigned char num_components; /* number of components of the compressed image */
- unsigned char chroma_h_samp_factor; /* horizontal chroma sampling factor of the compressed image */
- unsigned char chroma_v_samp_factor; /* vertical chroma sampling factor of the compressed image */
- unsigned char scale_factor; /* down-scaling factor during decompression: one of 1, 2, 4 and 8 */
-
- unsigned int output_width; /* width of the output image (image_width/scale_factor) */
- unsigned int output_height; /* height of the output image (image_height/scale_factor) */
- __u32 output_format; /* 4CC style format identifier of the output image defined in videodev2.h */
+ unsigned int image_width; /* width of the compressed image */
+ unsigned int image_height; /* height of the compressed image */
+ unsigned char num_components; /* number of components of the compressed image */
+ unsigned char
+ chroma_h_samp_factor; /* horizontal chroma sampling factor of the compressed image */
+ unsigned char
+ chroma_v_samp_factor; /* vertical chroma sampling factor of the compressed image */
+ unsigned char scale_factor; /* down-scaling factor during decompression: one of 1, 2, 4 and 8 */
+
+ unsigned int output_width; /* width of the output image (image_width/scale_factor) */
+ unsigned int output_height; /* height of the output image (image_height/scale_factor) */
+ __u32 output_format; /* 4CC style format identifier of the output image defined in videodev2.h
+ */
} *hwjpeg_decompress_ptr;
/*
@@ -79,7 +82,8 @@ bool hwjpeg_dmabuf_src(hwjpeg_decompress_ptr cinfo, int infd, size_t insize, siz
* @dummybytes: The available dummy bytes after @insize.
* @return: false on failure
*/
-bool hwjpeg_mem_src(hwjpeg_decompress_ptr cinfo, unsigned char *inbuffer, size_t insize, size_t dummybytes);
+bool hwjpeg_mem_src(hwjpeg_decompress_ptr cinfo, unsigned char *inbuffer, size_t insize,
+ size_t dummybytes);
/*
* hwjpeg_config_image_format - configure output image format
@@ -100,7 +104,8 @@ void hwjpeg_config_image_format(hwjpeg_decompress_ptr cinfo, __u32 v4l2_pix_fmt)
* @num_buffers: The number of elements in @outsizes and @outbuffer
* @return: false on failure.
*/
-bool hwjpeg_mem_dst(hwjpeg_decompress_ptr cinfo, unsigned char *outbuffer[], size_t outsize[], unsigned int num_buffers);
+bool hwjpeg_mem_dst(hwjpeg_decompress_ptr cinfo, unsigned char *outbuffer[], size_t outsize[],
+ unsigned int num_buffers);
/*
* hwjpeg_dmabuf_dst - configure the buffer to store decompressed image
@@ -113,7 +118,8 @@ bool hwjpeg_mem_dst(hwjpeg_decompress_ptr cinfo, unsigned char *outbuffer[], siz
* @num_buffers: The number of elements in @outsizes and @outfd
* @return: false on failure.
*/
-bool hwjpeg_dmabuf_dst(hwjpeg_decompress_ptr cinfo, int outfd[], size_t outsize[], unsigned int num_buffers);
+bool hwjpeg_dmabuf_dst(hwjpeg_decompress_ptr cinfo, int outfd[], size_t outsize[],
+ unsigned int num_buffers);
/*
* hwjpeg_set_downscale_factor - configure the downscaling factor during decompression
@@ -171,7 +177,7 @@ bool hwjpeg_start_decompress(hwjpeg_decompress_ptr cinfo);
*/
void hwjpeg_destroy_decompress(hwjpeg_decompress_ptr cinfo);
-}; /* extern "C" */
+}; /* extern "C" */
#endif /* __cplusplus */
#endif /*__HARDWARE_SAMSUNG_EXYNOS7420_HWJPEGDECOMPRESSOR_H__*/
diff --git a/libhwjpeg/libhwjpeg-exynos.cpp b/libhwjpeg/libhwjpeg-exynos.cpp
index 1bfa55a..5f6dd6e 100644
--- a/libhwjpeg/libhwjpeg-exynos.cpp
+++ b/libhwjpeg/libhwjpeg-exynos.cpp
@@ -15,28 +15,26 @@
* limitations under the License.
*/
-#include <cstdio>
-
-#include <cstring>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
+#include <exynos-hwjpeg.h>
#include <fcntl.h>
-
+#include <hwjpeglib-exynos.h>
#include <linux/videodev2.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
-#include <exynos-hwjpeg.h>
-#include <hwjpeglib-exynos.h>
+#include <cstdio>
+#include <cstring>
#include "hwjpeg-internal.h"
#define ALOGERR(fmt, args...) ((void)ALOG(LOG_ERROR, LOG_TAG, fmt " [%s]", ##args, strerror(errno)))
-#define ROUND_DOWN(val, denom) ((val) & ~((denom) - 1))
-#define ROUND_UP(val, denom) ROUND_DOWN((val) + (denom) - 1, denom)
-#define TO_MASK(val) ((val) - 1)
+#define ROUND_DOWN(val, denom) ((val) & ~((denom)-1))
+#define ROUND_UP(val, denom) ROUND_DOWN((val) + (denom)-1, denom)
+#define TO_MASK(val) ((val)-1)
class CJpegStreamParser {
private:
@@ -51,18 +49,18 @@ private:
size_t GetLength(unsigned char *addr);
bool ParseFrame(unsigned char *addr);
- off_t GetOffset(unsigned char *addr) {
+ ptrdiff_t GetOffset(unsigned char *addr) {
unsigned long beg = reinterpret_cast<unsigned long>(m_pStreamBase);
unsigned long cur = reinterpret_cast<unsigned long>(addr);
- return static_cast<off_t>(cur - beg);
+ return static_cast<ptrdiff_t>(cur - beg);
}
public:
unsigned char m_iHorizontalFactor;
unsigned char m_iVerticalFactor;
- CJpegStreamParser() : m_pStreamBase(NULL), m_nStreamSize(0) { }
- ~CJpegStreamParser() { }
+ CJpegStreamParser() : m_pStreamBase(NULL), m_nStreamSize(0) {}
+ ~CJpegStreamParser() {}
bool Parse(unsigned char *streambase, size_t length);
@@ -72,8 +70,7 @@ public:
unsigned int GetNumComponents() { return m_nComponents; }
};
-void CJpegStreamParser::Initialize()
-{
+void CJpegStreamParser::Initialize() {
m_nComponents = 0;
m_nWidth = 0;
m_nHeight = 0;
@@ -81,14 +78,12 @@ void CJpegStreamParser::Initialize()
m_iVerticalFactor = 1;
}
-size_t CJpegStreamParser::GetLength(unsigned char *addr)
-{
+size_t CJpegStreamParser::GetLength(unsigned char *addr) {
size_t len = static_cast<size_t>(*addr++) * 0x100;
return len + *addr;
}
-bool CJpegStreamParser::Parse(unsigned char *streambase, size_t length)
-{
+bool CJpegStreamParser::Parse(unsigned char *streambase, size_t length) {
Initialize();
m_pStreamBase = streambase;
@@ -117,6 +112,7 @@ bool CJpegStreamParser::Parse(unsigned char *streambase, size_t length)
}
unsigned char marker = *addr++;
+ filelen -= 2;
if ((marker != 0xC4) && ((marker & 0xF0) == 0xC0)) { // SOFn
if (marker != 0xC0) {
@@ -124,18 +120,17 @@ bool CJpegStreamParser::Parse(unsigned char *streambase, size_t length)
return false;
}
- if (filelen < GetLength(addr)) {
+ if (filelen < 2 || filelen < GetLength(addr)) {
ALOGE("Too small SOF0 segment");
return false;
}
- if (!ParseFrame(addr))
- return false;
+ if (!ParseFrame(addr)) return false;
- return true; // this is the successful exit point
+ return true; // this is the successful exit point
} else if (marker == 0xD9) { // EOI
// This will not meet.
- ALOGE("Unexpected EOI found at %lu\n", GetOffset(addr - 2));
+ ALOGE("Unexpected EOI found at %td\n", GetOffset(addr - 2));
return false;
} else {
if ((marker == 0xCC) || (marker == 0xDC)) { // DAC and DNL
@@ -143,14 +138,19 @@ bool CJpegStreamParser::Parse(unsigned char *streambase, size_t length)
return false;
}
- if (filelen < GetLength(addr)) {
+ if (filelen < 2 || filelen < GetLength(addr)) {
ALOGE("Corrupted JPEG stream");
return false;
}
}
- if (GetLength(addr) == 0) {
- ALOGE("Invalid length 0 is read at offset %lu", GetOffset(addr));
+ if (filelen < 2 || GetLength(addr) == 0) {
+ ALOGE("Invalid length 0 is read at offset %td", GetOffset(addr));
+ return false;
+ }
+
+ if (filelen < GetLength(addr)) {
+ ALOGE("Corrupted JPEG Stream");
return false;
}
@@ -165,8 +165,7 @@ bool CJpegStreamParser::Parse(unsigned char *streambase, size_t length)
return false;
}
-bool CJpegStreamParser::ParseFrame(unsigned char *addr)
-{ // 2 bytes of length
+bool CJpegStreamParser::ParseFrame(unsigned char *addr) { // 2 bytes of length
// 1 byte of bits per sample
// 2 bytes of height
// 2 bytes of width
@@ -217,7 +216,7 @@ bool CJpegStreamParser::ParseFrame(unsigned char *addr)
return true;
}
-class CLibhwjpegDecompressor: public hwjpeg_decompressor_struct {
+class CLibhwjpegDecompressor : public hwjpeg_decompressor_struct {
enum {
HWJPG_FLAG_NEED_MUNMAP = 1,
};
@@ -231,6 +230,7 @@ class CLibhwjpegDecompressor: public hwjpeg_decompressor_struct {
size_t m_nDummyBytes;
CJpegStreamParser m_jpegStreamParser;
+
public:
CLibhwjpegDecompressor() : m_flags(0) {
// members of hwjpeg_decompressor_struct
@@ -243,7 +243,7 @@ public:
output_width = 0;
output_height = 0;
m_bPrepared = false;
- m_pStreamBuffer = NULL;
+ m_pStreamBuffer = NULL;
output_format = V4L2_PIX_FMT_RGB32;
@@ -290,8 +290,7 @@ public:
m_nDummyBytes = 0;
m_pStreamBuffer = reinterpret_cast<unsigned char *>(
- mmap(NULL, m_nStreamLength,
- PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
+ mmap(NULL, m_nStreamLength, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0));
if (m_pStreamBuffer == MAP_FAILED) {
m_pStreamBuffer = NULL;
close(fd);
@@ -332,8 +331,8 @@ public:
m_nDummyBytes = dummybytes;
m_pStreamBuffer = reinterpret_cast<unsigned char *>(
- mmap(NULL, m_nStreamLength + m_nDummyBytes,
- PROT_READ | PROT_WRITE, MAP_SHARED, buffer, 0));
+ mmap(NULL, m_nStreamLength + m_nDummyBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
+ buffer, 0));
if (m_pStreamBuffer == MAP_FAILED) {
m_pStreamBuffer = NULL;
ALOGERR("Failed to mmap %zu bytes of dmabuf fd %d", m_nStreamLength, buffer);
@@ -373,15 +372,13 @@ public:
bool IsEnoughStreamBuffer() { return true; }
};
-bool CLibhwjpegDecompressor::PrepareDecompression()
-{
+bool CLibhwjpegDecompressor::PrepareDecompression() {
if (!m_hwjpeg) {
ALOGE("device node is not opened!");
return false;
}
- if ((scale_factor != 1) && (scale_factor != 2) &&
- (scale_factor != 4) && (scale_factor != 8)) {
+ if ((scale_factor != 1) && (scale_factor != 2) && (scale_factor != 4) && (scale_factor != 8)) {
ALOGE("Invalid downscaling factor %d", scale_factor);
return false;
}
@@ -391,8 +388,7 @@ bool CLibhwjpegDecompressor::PrepareDecompression()
return false;
}
- if (!m_jpegStreamParser.Parse(m_pStreamBuffer, m_nStreamLength))
- return false;
+ if (!m_jpegStreamParser.Parse(m_pStreamBuffer, m_nStreamLength)) return false;
image_width = m_jpegStreamParser.GetWidth();
image_height = m_jpegStreamParser.GetHeight();
@@ -401,9 +397,10 @@ bool CLibhwjpegDecompressor::PrepareDecompression()
chroma_v_samp_factor = m_jpegStreamParser.m_iVerticalFactor;
if (((image_width % (chroma_h_samp_factor * scale_factor)) != 0) ||
- ((image_height % (chroma_v_samp_factor * scale_factor)) != 0)) {
- ALOGE("Downscaling by factor %d of compressed image size %dx%d(chroma %d:%d) is not supported",
- scale_factor, image_width, image_height, chroma_h_samp_factor, chroma_v_samp_factor);
+ ((image_height % (chroma_v_samp_factor * scale_factor)) != 0)) {
+ ALOGE("Downscaling by factor %d of compressed image size %dx%d(chroma %d:%d) is not "
+ "supported",
+ scale_factor, image_width, image_height, chroma_h_samp_factor, chroma_v_samp_factor);
return false;
}
@@ -416,7 +413,8 @@ bool CLibhwjpegDecompressor::PrepareDecompression()
}
if (!m_hwjpeg->SetImageFormat(output_format, output_width, output_height)) {
- ALOGE("Failed to configure image format (%ux%u/%08X)", output_width, output_height, output_format);
+ ALOGE("Failed to configure image format (%ux%u/%08X)", output_width, output_height,
+ output_format);
return false;
}
@@ -425,8 +423,7 @@ bool CLibhwjpegDecompressor::PrepareDecompression()
return true;
}
-bool CLibhwjpegDecompressor::Decompress()
-{
+bool CLibhwjpegDecompressor::Decompress() {
if (!m_bPrepared) {
ALOGE("JPEG header is not parsed");
return false;
@@ -447,77 +444,64 @@ bool CLibhwjpegDecompressor::Decompress()
return true;
}
-hwjpeg_decompress_ptr hwjpeg_create_decompress()
-{
+hwjpeg_decompress_ptr hwjpeg_create_decompress() {
hwjpeg_decompress_ptr p = new CLibhwjpegDecompressor();
- if (!p)
- ALOGE("Failed to create decompress struct");
+ if (!p) ALOGE("Failed to create decompress struct");
return p;
}
-bool hwjpeg_file_src(hwjpeg_decompress_ptr cinfo, const char *path)
-{
+bool hwjpeg_file_src(hwjpeg_decompress_ptr cinfo, const char *path) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->SetStreamPath(path);
}
-void hwjpeg_config_image_format(hwjpeg_decompress_ptr cinfo, __u32 v4l2_pix_fmt)
-{
+void hwjpeg_config_image_format(hwjpeg_decompress_ptr cinfo, __u32 v4l2_pix_fmt) {
cinfo->output_format = v4l2_pix_fmt;
}
-bool hwjpeg_dmabuf_src(hwjpeg_decompress_ptr cinfo, int infd, size_t insize, size_t dummybytes)
-{
+bool hwjpeg_dmabuf_src(hwjpeg_decompress_ptr cinfo, int infd, size_t insize, size_t dummybytes) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->SetStreamBuffer(infd, insize, dummybytes);
}
-bool hwjpeg_mem_src(hwjpeg_decompress_ptr cinfo,
- unsigned char *inbuffer, size_t insize, size_t dummybytes)
-{
+bool hwjpeg_mem_src(hwjpeg_decompress_ptr cinfo, unsigned char *inbuffer, size_t insize,
+ size_t dummybytes) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->SetStreamBuffer(inbuffer, insize, dummybytes);
}
-bool hwjpeg_mem_dst(hwjpeg_decompress_ptr cinfo,
- unsigned char *outbuffer[], size_t outsize[], unsigned int num_buffers)
-{
+bool hwjpeg_mem_dst(hwjpeg_decompress_ptr cinfo, unsigned char *outbuffer[], size_t outsize[],
+ unsigned int num_buffers) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->SetImageBuffer(outbuffer, outsize, num_buffers);
}
-bool hwjpeg_dmabuf_dst(hwjpeg_decompress_ptr cinfo,
- int outfd[], size_t outsize[], unsigned int num_buffers)
-{
+bool hwjpeg_dmabuf_dst(hwjpeg_decompress_ptr cinfo, int outfd[], size_t outsize[],
+ unsigned int num_buffers) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->SetImageBuffer(outfd, outsize, num_buffers);
}
-void hwjpeg_set_downscale_factor(hwjpeg_decompress_ptr cinfo, unsigned int factor)
-{
+void hwjpeg_set_downscale_factor(hwjpeg_decompress_ptr cinfo, unsigned int factor) {
cinfo->scale_factor = factor;
}
-bool hwjpeg_read_header(hwjpeg_decompress_ptr cinfo)
-{
+bool hwjpeg_read_header(hwjpeg_decompress_ptr cinfo) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->PrepareDecompression();
}
-bool hwjpeg_start_decompress(hwjpeg_decompress_ptr cinfo)
-{
+bool hwjpeg_start_decompress(hwjpeg_decompress_ptr cinfo) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->Decompress();
}
-void hwjpeg_destroy_decompress(hwjpeg_decompress_ptr cinfo)
-{
+void hwjpeg_destroy_decompress(hwjpeg_decompress_ptr cinfo) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
delete decomp;
}
-bool hwjpeg_has_enough_stream_buffer(hwjpeg_decompress_ptr cinfo)
-{
+bool hwjpeg_has_enough_stream_buffer(hwjpeg_decompress_ptr cinfo) {
CLibhwjpegDecompressor *decomp = reinterpret_cast<CLibhwjpegDecompressor *>(cinfo);
return decomp->IsEnoughStreamBuffer();
}
diff --git a/libion/ion.cpp b/libion/ion.cpp
index cf4d36a..d4d7cb8 100644
--- a/libion/ion.cpp
+++ b/libion/ion.cpp
@@ -30,6 +30,8 @@
#include <mutex>
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
static const struct {
std::string heap_name;
std::string ion_heap_name;
@@ -50,6 +52,13 @@ static const struct {
{"famodel-secure", "famodel_heap", ION_FLAG_PROTECTED, EXYNOS_ION_HEAP_FA_MODEL_MASK},
};
+const char *exynos_ion_get_heap_name(unsigned int legacy_heap_id) {
+ if (legacy_heap_id >= ARRAY_SIZE(heap_map_table))
+ return NULL;
+
+ return heap_map_table[legacy_heap_id].ion_heap_name.c_str();
+}
+
int exynos_ion_open(void) {
return 0;
}
diff --git a/libion/test/Android.bp b/libion/test/Android.bp
index 017eca2..fcc51f5 100644
--- a/libion/test/Android.bp
+++ b/libion/test/Android.bp
@@ -21,17 +21,20 @@ package {
cc_test {
name: "iontests_google",
- clang: true,
+
vendor: true,
proprietary: true,
- cflags: [ "-g", "-Werror" ],
+ cflags: [
+ "-g",
+ "-Werror",
+ ],
shared_libs: ["libion_google"],
srcs: [
"ion_test_fixture.cpp",
"ion_allocate_test.cpp",
"ion_allocate_api_test.cpp",
"ion_device_test.cpp",
- "ion_allocate_special.cpp",
+ "ion_allocate_special.cpp",
//"map_test.cpp",
//"exynos_api_test.cpp",
],