Merge "Don't depend on String8 cast to C string" into main
diff --git a/BoardConfigCFlags.mk b/BoardConfigCFlags.mk
index 0b567a9..679f44f 100644
--- a/BoardConfigCFlags.mk
+++ b/BoardConfigCFlags.mk
@@ -9,8 +9,8 @@
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)
diff --git a/hwc3/Android.mk b/hwc3/Android.mk
index 43538d3..28ed88d 100644
--- a/hwc3/Android.mk
+++ b/hwc3/Android.mk
@@ -28,14 +28,14 @@
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-V7-ndk \
+ com.google.hardware.pixel.display-V8-ndk \
libbase \
libbinder \
libbinder_ndk \
@@ -66,6 +66,7 @@
$(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 @@
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 @@
// 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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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 @@
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 @@
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 @@
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 @@
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 @@
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 4b3a1a3..8b0f005 100644
--- a/hwc3/ComposerCommandEngine.cpp
+++ b/hwc3/ComposerCommandEngine.cpp
@@ -55,9 +55,9 @@
} \
} 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,16 +232,12 @@
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 = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED
- : 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
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 @@
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..76e0f2d 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_.c_str()); \
+ } \
+ 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..93cc6ad 100644
--- a/hwc3/impl/HalImpl.cpp
+++ b/hwc3/impl/HalImpl.cpp
@@ -99,6 +99,20 @@
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 @@
}
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 @@
// 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 @@
// unregister HWC3 Callback
mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onVsyncIdle, this, nullptr);
+ mDevice->registerHwc3Callback(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug, this,
+ nullptr);
mEventCallback = nullptr;
}
@@ -457,6 +477,10 @@
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);
@@ -558,10 +582,10 @@
// TODO: not expect acceptDisplayChanges if there are no changes to accept
if (halDisplay->mRenderingState == RENDERING_STATE_VALIDATED) {
- LOG(INFO) << halDisplay->mDisplayName.string()
+ LOG(INFO) << halDisplay->mDisplayName.c_str()
<< ": acceptDisplayChanges was not called";
if (halDisplay->acceptDisplayChanges() != HWC2_ERROR_NONE) {
- LOG(ERROR) << halDisplay->mDisplayName.string()
+ LOG(ERROR) << halDisplay->mDisplayName.c_str()
<< ": acceptDisplayChanges is failed";
}
}
@@ -632,6 +656,14 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0856add..f23d8a8 100644
--- a/include/displaycolor/displaycolor.h
+++ b/include/displaycolor/displaycolor.h
@@ -34,6 +34,7 @@
/**
* hwc/displaycolor interface history
*
+ * 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.
@@ -61,8 +62,8 @@
}
} kInterfaceVersion {
- 6,
- 2,
+ 7,
+ 0,
0,
};
@@ -345,6 +346,13 @@
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:
@@ -364,7 +372,7 @@
* @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
@@ -375,29 +383,27 @@
* @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.
@@ -406,7 +412,7 @@
* @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 @@
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_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 bb004fe..b7be04e 100644
--- a/libacryl/acrylic_formats.cpp
+++ b/libacryl/acrylic_formats.cpp
@@ -91,6 +91,7 @@
{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 @@
{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 @@
{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 @@
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 @@
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 @@
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 @@
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 71391cd..1e23ab7 100644
--- a/libhwc2.1/Android.mk
+++ b/libhwc2.1/Android.mk
@@ -67,8 +67,8 @@
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-V7-ndk \
+LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V2-ndk \
+ com.google.hardware.pixel.display-V8-ndk \
libbinder_ndk \
libbase \
libpng \
@@ -97,6 +97,7 @@
$(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 \
@@ -134,7 +135,7 @@
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)
@@ -158,9 +159,10 @@
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-V7-ndk \
+LOCAL_SHARED_LIBRARIES += com.google.hardware.pixel.display-V8-ndk \
libbinder_ndk \
libbase
@@ -180,6 +182,7 @@
$(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 \
@@ -190,7 +193,7 @@
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 := \
@@ -220,8 +223,8 @@
android.hardware.graphics.mapper@2.0 \
libui
-LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V1-ndk \
- com.google.hardware.pixel.display-V7-ndk \
+LOCAL_SHARED_LIBRARIES += android.hardware.graphics.composer3-V2-ndk \
+ com.google.hardware.pixel.display-V8-ndk \
libbinder_ndk \
libbase
@@ -230,7 +233,7 @@
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)
@@ -251,6 +254,7 @@
$(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 fee44ed..914c54f 100644
--- a/libhwc2.1/ExynosHWC.cpp
+++ b/libhwc2.1/ExynosHWC.cpp
@@ -192,7 +192,7 @@
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)
@@ -520,10 +520,10 @@
if (exynosDisplay->mHWCRenderingState == RENDERING_STATE_VALIDATED) {
ALOGI("%s:: acceptDisplayChanges was not called",
- exynosDisplay->mDisplayName.string());
+ exynosDisplay->mDisplayName.c_str());
if (exynosDisplay->acceptDisplayChanges() != HWC2_ERROR_NONE) {
ALOGE("%s:: acceptDisplayChanges is failed",
- exynosDisplay->mDisplayName.string());
+ exynosDisplay->mDisplayName.c_str());
}
}
int32_t ret = exynosDisplay->presentDisplay(outRetireFence);
diff --git a/libhwc2.1/ExynosHWCDebug.cpp b/libhwc2.1/ExynosHWCDebug.cpp
index bbf676c..3473d50 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 @@
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).c_str(),
+ display->mErrorFrameCount, errString.c_str());
- 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;
}
@@ -102,7 +54,7 @@
struct timeval tv;
gettimeofday(&tv, NULL);
- saveString.appendFormat("\n====== Fences at time:%s ======\n", getLocalTimeStr(tv).string());
+ saveString.appendFormat("\n====== Fences at time:%s ======\n", getLocalTimeStr(tv).c_str());
if (device != NULL) {
for (const auto &[fd, info] : device->mFenceInfos) {
@@ -112,17 +64,12 @@
for (const auto &trace : info.traces) {
saveString.appendFormat("> dir: %d, type: %d, ip: %d, time:%s\n", trace.direction,
- trace.type, trace.ip, getLocalTimeStr(trace.time).string());
+ trace.type, trace.ip, getLocalTimeStr(trace.time).c_str());
}
}
}
- 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..2f2d0b3 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 @@
eDebugColorManagement = 0x00080000,
eDebugAttrSetting = 0x00100000,
eDebugDisplayConfig = 0x00400000,
+ eDebugTDM = 0x00800000,
+ eDebugLoadBalancing = 0x01000000,
};
class ExynosDisplay;
@@ -91,31 +95,38 @@
#define DISPLAY_LOGD(type, msg, ...) \
{\
if (hwcCheckDebugMessages(type)) \
- ALOGD("%s:: [%s] " msg, __func__, mDisplayName.string(), ##__VA_ARGS__); \
+ ALOGD("%s:: [%s] " msg, __func__, mDisplayName.c_str(), ##__VA_ARGS__); \
}
#define MPP_LOGD(type, msg, ...) \
{\
if (hwcCheckDebugMessages(type)) \
- ALOGD("%s:: [%s][%d] " msg, __func__, mName.string(), mLogicalIndex, ##__VA_ARGS__); \
+ ALOGD("%s:: [%s][%d] " msg, __func__, mName.c_str(), mLogicalIndex, ##__VA_ARGS__); \
}
#endif
-#define DISPLAY_LOGV(msg, ...) ALOGV("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
-#define DISPLAY_LOGI(msg, ...) ALOGI("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
-#define DISPLAY_LOGW(msg, ...) ALOGW("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__)
+#define DISPLAY_LOGV(msg, ...) ALOGV("[%s] " msg, mDisplayName.c_str(), ##__VA_ARGS__)
+#define DISPLAY_LOGI(msg, ...) ALOGI("[%s] " msg, mDisplayName.c_str(), ##__VA_ARGS__)
+#define DISPLAY_LOGW(msg, ...) ALOGW("[%s] " msg, mDisplayName.c_str(), ##__VA_ARGS__)
#define DISPLAY_LOGE(msg, ...) \
{\
- ALOGE("[%s] " msg, mDisplayName.string(), ##__VA_ARGS__); \
+ ALOGE("[%s] " msg, mDisplayName.c_str(), ##__VA_ARGS__); \
String8 saveString; \
saveString.appendFormat(msg, ##__VA_ARGS__); \
saveErrorLog(saveString, this); \
}
-#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__)
+#define DISPLAY_DRM_LOGI(msg, ...) \
+ ALOGI("[%s] " msg, mExynosDisplay->mDisplayName.c_str(), ##__VA_ARGS__)
+#define DISPLAY_DRM_LOGW(msg, ...) \
+ ALOGW("[%s] " msg, mExynosDisplay->mDisplayName.c_str(), ##__VA_ARGS__)
+#define DISPLAY_DRM_LOGE(msg, ...) \
+ ALOGE("[%s] " msg, mExynosDisplay->mDisplayName.c_str(), ##__VA_ARGS__)
+
+#define MPP_LOGV(msg, ...) ALOGV("[%s][%d] " msg, mName.c_str(), mLogicalIndex, ##__VA_ARGS__)
+#define MPP_LOGI(msg, ...) ALOGI("[%s][%d] " msg, mName.c_str(), mLogicalIndex, ##__VA_ARGS__)
+#define MPP_LOGW(msg, ...) ALOGW("[%s][%d] " msg, mName.c_str(), mLogicalIndex, ##__VA_ARGS__)
#define MPP_LOGE(msg, ...) \
{\
- ALOGE("[%s][%d] " msg, mName.string(), mLogicalIndex, ##__VA_ARGS__); \
+ ALOGE("[%s][%d] " msg, mName.c_str(), mLogicalIndex, ##__VA_ARGS__); \
String8 saveString; \
saveString.appendFormat(msg, ##__VA_ARGS__); \
saveErrorLog(saveString, mAssignedDisplay); \
@@ -129,4 +140,38 @@
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.c_str()); \
+ } \
+ ScopedTraceEnder traceEnder
+
+#define DISPLAY_ATRACE_NAME(name) ATRACE_FORMAT("%s for %s", name, mDisplayTraceName.c_str())
+#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.c_str()).c_str(), \
+ value); \
+ }
+#define DISPLAY_ATRACE_INT64(name, value) \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) { \
+ ATRACE_INT64(String8::format("%s for %s", name, mDisplayTraceName.c_str()).c_str(), \
+ 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.c_str()); \
+ if (CC_UNLIKELY(ATRACE_ENABLED())) ATRACE_NAME(log.c_str()); \
+ }
+
#endif
diff --git a/libhwc2.1/histogram_mediator.cpp b/libhwc2.1/histogram_mediator.cpp
index 991b972..f23feec 100644
--- a/libhwc2.1/histogram_mediator.cpp
+++ b/libhwc2.1/histogram_mediator.cpp
@@ -56,12 +56,12 @@
ExynosDisplayDrmInterface *moduleDisplayInterface =
static_cast<ExynosDisplayDrmInterface *>(mDisplay->mDisplayInterface.get());
- if (moduleDisplayInterface->setHistogramControl(
- hidl_histogram_control_t::HISTOGRAM_CONTROL_REQUEST) != NO_ERROR) {
- return histogram::HistogramErrorCode::ENABLE_HIST_ERROR;
- }
{
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;
@@ -93,7 +93,7 @@
}
histogram::HistogramErrorCode histogram::HistogramMediator::setRoiWeightThreshold(
- const RoiRect roi, const Weight weight, const HistogramPos pos) {
+ 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),
@@ -118,7 +118,7 @@
return histogram::HistogramErrorCode::NONE;
}
-histogram::RoiRect histogram::HistogramMediator::calRoi(RoiRect roi) {
+histogram::RoiRect histogram::HistogramMediator::calRoi(const RoiRect &roi) {
RoiRect roi_return = {-1, -1, -1, -1};
ExynosDisplayDrmInterface *moduleDisplayInterface =
static_cast<ExynosDisplayDrmInterface *>(mDisplay->mDisplayInterface.get());
diff --git a/libhwc2.1/histogram_mediator.h b/libhwc2.1/histogram_mediator.h
index eac4c98..54d28c9 100644
--- a/libhwc2.1/histogram_mediator.h
+++ b/libhwc2.1/histogram_mediator.h
@@ -62,9 +62,9 @@
HistogramErrorCode requestHist();
HistogramErrorCode cancelHistRequest();
HistogramErrorCode collectRoiLuma(std::vector<char16_t> *buf);
- HistogramErrorCode setRoiWeightThreshold(const RoiRect roi, const Weight weight,
- const HistogramPos pos);
- RoiRect calRoi(RoiRect roi);
+ 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;
@@ -73,10 +73,38 @@
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);
diff --git a/libhwc2.1/libdevice/BrightnessController.cpp b/libhwc2.1/libdevice/BrightnessController.cpp
index b8ae2ee..b651ead 100644
--- a/libhwc2.1/libdevice/BrightnessController.cpp
+++ b/libhwc2.1/libdevice/BrightnessController.cpp
@@ -90,9 +90,9 @@
void BrightnessController::initBrightnessSysfs() {
String8 nodeName;
nodeName.appendFormat(BRIGHTNESS_SYSFS_NODE, mPanelIndex);
- mBrightnessOfs.open(nodeName.string(), std::ofstream::out);
+ mBrightnessOfs.open(nodeName.c_str(), std::ofstream::out);
if (mBrightnessOfs.fail()) {
- ALOGE("%s %s fail to open", __func__, nodeName.string());
+ ALOGE("%s %s fail to open", __func__, nodeName.c_str());
mBrightnessOfs.close();
return;
}
@@ -100,9 +100,9 @@
nodeName.clear();
nodeName.appendFormat(MAX_BRIGHTNESS_SYSFS_NODE, mPanelIndex);
- std::ifstream ifsMaxBrightness(nodeName.string());
+ std::ifstream ifsMaxBrightness(nodeName.c_str());
if (ifsMaxBrightness.fail()) {
- ALOGE("%s fail to open %s", __func__, nodeName.string());
+ ALOGE("%s fail to open %s", __func__, nodeName.c_str());
return;
}
@@ -117,9 +117,9 @@
String8 nodeName;
nodeName.appendFormat(kLocalCabcModeFileNode, mPanelIndex);
- mCabcModeOfs.open(nodeName.string(), std::ofstream::out);
+ mCabcModeOfs.open(nodeName.c_str(), std::ofstream::out);
if (mCabcModeOfs.fail()) {
- ALOGE("%s %s fail to open", __func__, nodeName.string());
+ ALOGE("%s %s fail to open", __func__, nodeName.c_str());
mCabcModeOfs.close();
return;
}
@@ -166,9 +166,9 @@
String8 nodeName;
nodeName.appendFormat(kDimBrightnessFileNode, mPanelIndex);
- std::ifstream ifsDimBrightness(nodeName.string());
+ std::ifstream ifsDimBrightness(nodeName.c_str());
if (ifsDimBrightness.fail()) {
- ALOGW("%s fail to open %s", __func__, nodeName.string());
+ ALOGW("%s fail to open %s", __func__, nodeName.c_str());
} else {
ifsDimBrightness >> mDimBrightness;
ifsDimBrightness.close();
@@ -247,21 +247,23 @@
} 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,
+ 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;
}
@@ -300,7 +302,8 @@
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;
}
@@ -314,6 +317,13 @@
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();
}
@@ -698,34 +708,39 @@
}
// Return immediately if it's already in the status. Otherwise poll the status
-int BrightnessController::checkSysfsStatus(const char* file,
+int BrightnessController::checkSysfsStatus(const std::string& file,
const std::vector<std::string>& expectedValue,
const nsecs_t timeoutNs) {
ATRACE_CALL();
- if (expectedValue.size() == 0) return false;
+ 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'
std::string val = std::string(buf, size - 1);
if (std::find(expectedValue.begin(), expectedValue.end(), val) != expectedValue.end()) {
- return true;
+ return OK;
} else if (timeoutNs == 0) {
- return false;
+ // 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();
@@ -739,9 +754,9 @@
}
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)) {
@@ -754,7 +769,8 @@
val = std::string(buf, size - 1);
if (std::find(expectedValue.begin(), expectedValue.end(), val) !=
expectedValue.end()) {
- ret = 0;
+ ret = OK;
+ break;
} else {
std::string values;
for (auto& s : expectedValue) {
@@ -763,27 +779,27 @@
if (values.size() > 0) {
values.resize(values.size() - 1);
}
- ALOGE("%s read %s expected %s after notified", __func__, val.c_str(),
- values.c_str());
- ret = EINVAL;
+ 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() {
diff --git a/libhwc2.1/libdevice/BrightnessController.h b/libhwc2.1/libdevice/BrightnessController.h
index 9090689..66f4b23 100644
--- a/libhwc2.1/libdevice/BrightnessController.h
+++ b/libhwc2.1/libdevice/BrightnessController.h
@@ -114,8 +114,12 @@
std::lock_guard<std::recursive_mutex> lock(mBrightnessMutex);
return mLhbm.get();
}
- int checkSysfsStatus(const char *file, const std::vector<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() {
@@ -143,6 +147,21 @@
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;
@@ -217,6 +236,8 @@
"/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.
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 a53bd3e..8082351 100644
--- a/libhwc2.1/libdevice/ExynosDevice.cpp
+++ b/libhwc2.1/libdevice/ExynosDevice.cpp
@@ -45,7 +45,6 @@
class ExynosDevice;
-extern uint32_t mFenceLogSize;
extern void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str);
static const std::map<const uint32_t, const std::string_view> pixelDisplayIntfName =
@@ -96,9 +95,18 @@
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++) {
@@ -107,7 +115,9 @@
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;
@@ -121,10 +131,14 @@
}
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:
@@ -132,8 +146,8 @@
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)
@@ -145,7 +159,6 @@
dynamicRecompositionThreadCreate();
- hwcDebug = 0;
for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
hwcFenceDebug[i] = 0;
@@ -154,24 +167,25 @@
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.c_str());
+ 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.c_str());
+ 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);
}
char value[PROPERTY_VALUE_MAX];
@@ -212,6 +226,7 @@
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++;
@@ -261,6 +276,17 @@
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);
@@ -342,24 +368,6 @@
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
@@ -399,7 +407,7 @@
size_t copySize = min(static_cast<size_t>(*outSize), result.size());
ALOGI("HWC dump:: resultSize(%zu), outSize(%d), copySize(%zu)", result.size(), *outSize,
copySize);
- strlcpy(outBuffer, result.string(), copySize);
+ strlcpy(outBuffer, result.c_str(), copySize);
}
}
@@ -802,13 +810,12 @@
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) {
@@ -819,18 +826,38 @@
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;
@@ -895,7 +922,6 @@
if (exynosHWCControl.doFenceFileDump) {
ALOGD("Fence file dump !");
- if (mFenceLogSize != 0) ALOGD("Fence file not empty!");
saveFenceTrace(display);
exynosHWCControl.doFenceFileDump = false;
}
@@ -981,7 +1007,7 @@
VendorGraphicBufferMeta gmeta(mBuffer);
snprintf(filePath, MAX_DEV_NAME,
- "%s/%s", WRITEBACK_CAPTURE_PATH, fileName.string());
+ "%s/%s", WRITEBACK_CAPTURE_PATH, fileName.c_str());
FILE *fp = fopen(filePath, "w");
if (fp) {
uint32_t writeSize =
@@ -1193,3 +1219,19 @@
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 d6821f6..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 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 @@
GEOMETRY_ERROR_CASE = 1ULL << 63,
};
-class ExynosDevice;
class ExynosDisplay;
class ExynosResourceManager;
-class ExynosDeviceInterface;
class ExynosDevice {
public:
@@ -153,6 +154,7 @@
* Display list that managed by Device.
*/
android::Vector< ExynosDisplay* > mDisplays;
+ std::map<uint32_t, ExynosDisplay *> mDisplayMap;
int mNumVirtualDisplay;
@@ -235,7 +237,7 @@
/**
* @param display
*/
- ExynosDisplay* getDisplay(uint32_t display);
+ ExynosDisplay* getDisplay(uint32_t display) { return mDisplayMap[display]; }
/**
* Device Functions for HWC 2.0
@@ -297,6 +299,7 @@
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();
@@ -338,6 +341,12 @@
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);
diff --git a/libhwc2.1/libdevice/ExynosDisplay.cpp b/libhwc2.1/libdevice/ExynosDisplay.cpp
index 6d4dce3..8c66345 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>
@@ -60,7 +61,8 @@
constexpr float nsecsPerSec = std::chrono::nanoseconds(1s).count();
constexpr int64_t nsecsIdleHintTimeout = std::chrono::nanoseconds(100ms).count();
-ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker(uint32_t displayId)
+ExynosDisplay::PowerHalHintWorker::PowerHalHintWorker(uint32_t displayId,
+ const String8 &displayTraceName)
: Worker("DisplayHints", HAL_PRIORITY_URGENT_DISPLAY),
mNeedUpdateRefreshRateHint(false),
mLastRefreshRateHint(0),
@@ -69,8 +71,10 @@
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),
@@ -110,7 +114,8 @@
mPowerHalAidl = IPower::fromBinder(pwBinder);
if (!mPowerHalAidl) {
- ALOGE("failed to connect power HAL");
+ ALOGE("failed to connect power HAL (retry %u)", mConnectRetryCount);
+ mConnectRetryCount++;
return -EINVAL;
}
@@ -121,10 +126,12 @@
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;
@@ -190,6 +197,10 @@
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 */
@@ -262,6 +273,11 @@
int32_t ExynosDisplay::PowerHalHintWorker::checkIdleHintSupport(void) {
int32_t ret = NO_ERROR;
+
+ if (!isPowerHalExist()) {
+ return -EOPNOTSUPP;
+ }
+
Lock();
if (mIdleHintSupportIsChecked) {
ret = mIdleHintIsSupported ? NO_ERROR : -EOPNOTSUPP;
@@ -293,6 +309,10 @@
return *(sSharedDisplayData.hintSessionSupported);
}
+ if (!isPowerHalExist()) {
+ return -EOPNOTSUPP;
+ }
+
if (connectPowerHal() != NO_ERROR) {
ALOGW("Error connecting to the PowerHAL");
return -EINVAL;
@@ -327,7 +347,7 @@
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(mIdleHintStr, enableIdleHint);
@@ -443,13 +463,13 @@
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,
@@ -473,12 +493,12 @@
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();
@@ -906,9 +926,9 @@
if ((mOtfMPP == NULL) && (mM2mMPP == NULL))
result.appendFormat("\tresource is not assigned\n");
if (mOtfMPP != NULL)
- result.appendFormat("\tassignedMPP: %s\n", mOtfMPP->mName.string());
+ result.appendFormat("\tassignedMPP: %s\n", mOtfMPP->mName.c_str());
if (mM2mMPP != NULL)
- result.appendFormat("\t%s\n", mM2mMPP->mName.string());
+ result.appendFormat("\t%s\n", mM2mMPP->mName.c_str());
}
if (mTargetBuffer != NULL) {
uint64_t internal_format = 0;
@@ -948,9 +968,10 @@
}
}
-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),
@@ -960,13 +981,15 @@
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),
@@ -1001,7 +1024,11 @@
mVsyncPeriodChangeConstraints{systemTime(SYSTEM_TIME_MONOTONIC), 0},
mVsyncAppliedTimeLine{false, 0, systemTime(SYSTEM_TIME_MONOTONIC)},
mConfigRequestState(hwc_request_state_t::SET_CONFIG_STATE_DONE),
- mPowerHalHint(getDisplayId(mDisplayId, mIndex)) {
+ 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;
@@ -1146,6 +1173,7 @@
}
mDisplayInterface->destroyLayer(layer);
+ layer->resetAssignedResource();
delete layer;
@@ -1280,7 +1308,7 @@
/* 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;
@@ -1450,11 +1478,16 @@
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)
@@ -1510,7 +1543,7 @@
android::String8 result;
result.appendFormat("config[%zu]\n", i);
dumpConfig(result, mLastDpuData.configs[i]);
- DISPLAY_LOGE("%s", result.string());
+ DISPLAY_LOGE("%s", result.c_str());
}
DISPLAY_LOGE("compositionInfo.mLastWinConfigData config [%d, %d, %d]",
compositionInfo.mLastWinConfigData.fd_idma[0],
@@ -1676,11 +1709,14 @@
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;
}
}
@@ -2388,31 +2424,15 @@
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());
+ getLocalTimeStr(tv).c_str());
+ ALOGD("%s", reason.c_str());
- 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;
@@ -2423,25 +2443,21 @@
ExynosCompositionInfo exynosCompInfo = mExynosCompositionInfo;
clientCompInfo.dump(result);
exynosCompInfo.dump(result);
- ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ ALOGD("%s", result.c_str());
+ 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);
- }
+ ALOGD("%s", result.c_str());
+ 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();
}
}
@@ -2449,41 +2465,35 @@
if (mIgnoreLayers.size()) {
result.appendFormat("======================= dump ignore layers (%zu) ================================\n",
mIgnoreLayers.size());
- ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ ALOGD("%s", result.c_str());
+ 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();
}
}
}
result.appendFormat("============================= dump win configs ===================================\n");
- ALOGD("%s", result.string());
- if (pFile != NULL) {
- fwrite(result.string(), 1, result.size(), pFile);
- }
+ ALOGD("%s", result.c_str());
+ 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()
@@ -2503,7 +2513,7 @@
if ((config.assignedMPP != NULL) &&
(config.assignedMPP == compare_config.assignedMPP)) {
DISPLAY_LOGE("WIN_CONFIG error: duplicated assignedMPP(%s) between win%zu, win%zu",
- config.assignedMPP->mName.string(), i, j);
+ config.assignedMPP->mName.c_str(), i, j);
compare_config.state = compare_config.WIN_STATE_DISABLED;
flagValidConfig = false;
continue;
@@ -2545,7 +2555,7 @@
{
DISPLAY_LOGE("WIN_CONFIG error: invalid src alignment : %zu, "\
"assignedMPP: %s, mppType:%d, format(%d), s_x: %d(%d), s_y: %d(%d), s_w : %d(%d), s_h : %d(%d)", i,
- config.assignedMPP->mName.string(), exynosMPP->mLogicalType, config.format, config.src.x, srcXAlign,
+ config.assignedMPP->mName.c_str(), exynosMPP->mLogicalType, config.format, config.src.x, srcXAlign,
config.src.y, srcYAlign, config.src.w, srcWidthAlign, config.src.h, srcHeightAlign);
configInvalid = true;
}
@@ -3025,6 +3035,9 @@
} 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;
}
@@ -3376,7 +3389,7 @@
}
int32_t ExynosDisplay::presentDisplay(int32_t* outRetireFence) {
- ATRACE_CALL();
+ DISPLAY_ATRACE_CALL();
gettimeofday(&updateTimeInfo.lastPresentTime, NULL);
const bool mixedComposition = isMixedComposition();
@@ -3471,7 +3484,7 @@
* 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
@@ -3602,10 +3615,14 @@
goto err;
}
- if (mGeometryChanged != 0 || !skipSignalIdleForVideoLayer()) {
+ if (mGeometryChanged != 0 || !skipSignalIdle()) {
mPowerHalHint.signalIdle();
}
+ if (isFrameUpdate()) {
+ updateRefreshRateIndicator();
+ }
+
handleWindowUpdate();
setDisplayWinConfigData();
@@ -3649,7 +3666,7 @@
mLayers[i]->mExynosCompositionType,
mLayers[i]->mValidateCompositionType);
if (mLayers[i]->mM2mMPP != NULL)
- DISPLAY_LOGE("\t%s is assigned", mLayers[i]->mM2mMPP->mName.string());
+ DISPLAY_LOGE("\t%s is assigned", mLayers[i]->mM2mMPP->mName.c_str());
if (mLayers[i]->mAcquireFence > 0)
fence_close(mLayers[i]->mAcquireFence, this,
FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_LAYER);
@@ -3832,7 +3849,7 @@
for (size_t i = 0; i < mLastDpuData.configs.size(); i++) {
errString.appendFormat("config[%zu]\n", i);
dumpConfig(errString, mLastDpuData.configs[i]);
- DISPLAY_LOGE("\t%s", errString.string());
+ DISPLAY_LOGE("\t%s", errString.c_str());
errString.clear();
}
errString.appendFormat("%s:: skip flag is enabled but buffer is updated\n",
@@ -3981,9 +3998,16 @@
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;
}
@@ -4053,17 +4077,23 @@
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");
@@ -4106,6 +4136,7 @@
mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_PENDING;
mVsyncPeriodChangeConstraints = *vsyncPeriodChangeConstraints;
mDesiredConfig = config;
+ DISPLAY_ATRACE_INT("Pending ActiveConfig", mDesiredConfig);
calculateTimeline(config, vsyncPeriodChangeConstraints, outTimeline);
@@ -4249,14 +4280,6 @@
__func__, mConfigRequestState);
mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
updateAppliedActiveConfig(mActiveConfig, systemTime(SYSTEM_TIME_MONOTONIC));
-
- std::lock_guard<std::mutex> lock(mPeakRefreshRateMutex);
- bool isPeakRefreshRate = isCurrentPeakRefreshRate();
- ATRACE_INT("isPeakRefreshRate", isPeakRefreshRate);
- if (isPeakRefreshRate && mNotifyPeakRefreshRate) {
- mPeakRefreshRateCondition.notify_one();
- mNotifyPeakRefreshRate = false;
- }
}
return NO_ERROR;
}
@@ -4326,6 +4349,7 @@
int32_t ExynosDisplay::doDisplayConfigPostProcess(ExynosDevice *dev)
{
+ ATRACE_CALL();
uint64_t current = systemTime(SYSTEM_TIME_MONOTONIC);
int64_t actualChangeTime = 0;
@@ -4340,11 +4364,13 @@
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) {
@@ -4470,8 +4496,7 @@
int32_t ExynosDisplay::validateDisplay(
uint32_t* outNumTypes, uint32_t* outNumRequests) {
-
- ATRACE_CALL();
+ DISPLAY_ATRACE_CALL();
gettimeofday(&updateTimeInfo.lastValidateTime, NULL);
Mutex::Autolock lock(mDisplayMutex);
@@ -4612,6 +4637,7 @@
int32_t ExynosDisplay::startPostProcessing()
{
+ ATRACE_CALL();
int ret = NO_ERROR;
String8 errString;
@@ -4698,7 +4724,7 @@
Mutex::Autolock lock(mDisplayMutex);
result.appendFormat("[%s] display information size: %d x %d, vsyncState: %d, colorMode: %d, "
"colorTransformHint: %d, orientation %d\n",
- mDisplayName.string(), mXres, mYres, mVsyncState, mColorMode,
+ mDisplayName.c_str(), mXres, mYres, mVsyncState, mColorMode,
mColorTransformHint, mMountOrientation);
mClientCompositionInfo.dump(result);
mExynosCompositionInfo.dump(result);
@@ -5018,9 +5044,7 @@
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;
@@ -5099,7 +5123,7 @@
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)
{
@@ -5123,7 +5147,7 @@
if ((ret = m2mMPP->assignMPP(this, layer)) != NO_ERROR)
{
HWC_LOGE(this, "%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), ret);
return ret;
}
if (layer->mValidateCompositionType == HWC2_COMPOSITION_DEVICE) mWindowNumUsed--;
@@ -5164,7 +5188,7 @@
if ((ret = m2mMPP->assignMPP(this, mLayers[maxPriorityIndex])) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), ret);
return ret;
}
}
@@ -5859,13 +5883,13 @@
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() {
@@ -5924,6 +5948,9 @@
int32_t ExynosDisplay::flushDisplayBrightnessChange() {
if (mBrightnessController) {
+ if (mOperationRateManager) {
+ mOperationRateManager->onBrightness(mBrightnessController->getBrightnessLevel());
+ }
return mBrightnessController->applyPendingChangeViaSysfs(mVsyncPeriod);
}
return NO_ERROR;
@@ -6041,6 +6068,11 @@
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) {
@@ -6073,3 +6105,227 @@
}
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 c5e9704..5ad016e 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
@@ -285,6 +287,22 @@
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){};
@@ -367,13 +385,15 @@
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;
@@ -386,13 +406,15 @@
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;
@@ -428,10 +450,17 @@
* 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.
*/
@@ -533,10 +562,8 @@
hwc2_config_t mDesiredConfig;
hwc2_config_t mActiveConfig = UINT_MAX;
-
- bool mNotifyPeakRefreshRate = false;
- std::mutex mPeakRefreshRateMutex;
- std::condition_variable mPeakRefreshRateCondition;
+ hwc2_config_t mPendingConfig = UINT_MAX;
+ int64_t mLastVsyncTimestamp = 0;
void initDisplay();
@@ -547,7 +574,7 @@
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.
@@ -1173,6 +1200,7 @@
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);
@@ -1207,6 +1235,7 @@
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;
}
@@ -1255,15 +1284,17 @@
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; }
-
- bool isCurrentPeakRefreshRate(void) {
- return ((mConfigRequestState == hwc_request_state_t::SET_CONFIG_STATE_DONE) &&
- (mVsyncPeriod == mMinDisplayVsyncPeriod));
- }
+ 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);
// check if there are any dimmed layers
bool isMixedComposition();
@@ -1276,7 +1307,7 @@
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
@@ -1287,8 +1318,8 @@
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.
@@ -1297,7 +1328,7 @@
/* Display hint to notify power hal */
class PowerHalHintWorker : public Worker {
public:
- PowerHalHintWorker(uint32_t displayId);
+ PowerHalHintWorker(uint32_t displayId, const String8& displayTraceName);
virtual ~PowerHalHintWorker();
int Init();
@@ -1370,12 +1401,16 @@
// 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
@@ -1455,8 +1490,8 @@
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 mIndex have been declared
- // since the result of getDisplayId(mDisplayId, mIndex) is needed as the parameter of
+ // 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;
@@ -1496,6 +1531,106 @@
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.c_str(), 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 24c6cac..740ffa4 100644
--- a/libhwc2.1/libdevice/ExynosLayer.cpp
+++ b/libhwc2.1/libdevice/ExynosLayer.cpp
@@ -39,6 +39,7 @@
: 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),
@@ -59,6 +60,7 @@
mNextLastFpsTime(0),
mLastLayerBuffer(NULL),
mLayerBuffer(NULL),
+ mLastUpdateTime(0),
mDamageNum(0),
mBlending(HWC2_BLEND_MODE_NONE),
mPlaneAlpha(1.0),
@@ -324,7 +326,7 @@
uint32_t minDstHeight = exynosMPPVG->getDstMinHeight(dst_img);
if ((uint32_t)WIDTH(mDisplayFrame) < minDstWidth) {
ALOGI("%s DRM layer displayFrame width %d is smaller than otf minWidth %d",
- mDisplay->mDisplayName.string(),
+ mDisplay->mDisplayName.c_str(),
WIDTH(mDisplayFrame), minDstWidth);
mPreprocessedInfo.displayFrame.right = mDisplayFrame.left +
pixel_align(WIDTH(mDisplayFrame), minDstWidth);
@@ -337,7 +339,7 @@
}
if ((uint32_t)HEIGHT(mDisplayFrame) < minDstHeight) {
ALOGI("%s DRM layer displayFrame height %d is smaller than vpp minHeight %d",
- mDisplay->mDisplayName.string(),
+ mDisplay->mDisplayName.c_str(),
HEIGHT(mDisplayFrame), minDstHeight);
mPreprocessedInfo.displayFrame.bottom = mDisplayFrame.top +
pixel_align(HEIGHT(mDisplayFrame), minDstHeight);
@@ -419,6 +421,11 @@
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);
@@ -511,6 +518,7 @@
}
mCompositionType = type;
+ mRequestedCompositionType = type;
return HWC2_ERROR_NONE;
}
@@ -953,12 +961,12 @@
{
int32_t ret = NO_ERROR;
if (mM2mMPP != NULL) {
- HDEBUGLOGD(eDebugResourceManager, "\t\t %s mpp is reset", mM2mMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceManager, "\t\t %s mpp is reset", mM2mMPP->mName.c_str());
mM2mMPP->resetAssignedState(this);
mM2mMPP = NULL;
}
if (mOtfMPP != NULL) {
- HDEBUGLOGD(eDebugResourceManager, "\t\t %s mpp is reset", mOtfMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceManager, "\t\t %s mpp is reset", mOtfMPP->mName.c_str());
mOtfMPP->resetAssignedState();
mOtfMPP = NULL;
}
@@ -1028,7 +1036,7 @@
.add("fd", std::vector<int>({fd, fd1, fd2}))
.add("AFBC", static_cast<bool>(mCompressed));
}
- tb.add("format", getFormatStr(format, mCompressed ? AFBC : 0).string())
+ tb.add("format", getFormatStr(format, mCompressed ? AFBC : 0).c_str())
.add("dataSpace", mDataSpace, true)
.add("colorTr", mLayerColorTransform.enable)
.add("blend", mBlending, true)
@@ -1069,13 +1077,13 @@
if ((mDisplay != NULL) && (mDisplay->mResourceManager != NULL)) {
result.appendFormat("MPPFlags for otfMPP\n");
for (uint32_t i = 0; i < mDisplay->mResourceManager->getOtfMPPSize(); i++) {
- result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getOtfMPP(i)->mName.string(),
+ result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getOtfMPP(i)->mName.c_str(),
mCheckMPPFlag[mDisplay->mResourceManager->getOtfMPP(i)->mLogicalType]);
}
result.appendFormat("\n");
result.appendFormat("MPPFlags for m2mMPP\n");
for (uint32_t i = 0; i < mDisplay->mResourceManager->getM2mMPPSize(); i++) {
- result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getM2mMPP(i)->mName.string(),
+ result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getM2mMPP(i)->mName.c_str(),
mCheckMPPFlag[mDisplay->mResourceManager->getM2mMPP(i)->mLogicalType]);
if ((i!=0) && (i%4==0)) result.appendFormat("\n");
}
@@ -1085,9 +1093,9 @@
if ((mOtfMPP == NULL) && (mM2mMPP == NULL))
result.appendFormat("\tresource is not assigned.\n");
if (mOtfMPP != NULL)
- result.appendFormat("\tassignedMPP: %s\n", mOtfMPP->mName.string());
+ result.appendFormat("\tassignedMPP: %s\n", mOtfMPP->mName.c_str());
if (mM2mMPP != NULL)
- result.appendFormat("\tassignedM2mMPP: %s\n", mM2mMPP->mName.string());
+ result.appendFormat("\tassignedM2mMPP: %s\n", mM2mMPP->mName.c_str());
result.appendFormat("\tdump midImg\n");
dumpExynosImage(result, mMidImg);
@@ -1112,7 +1120,7 @@
fd2 = -1;
}
result.appendFormat("handle: %p [fd: %d, %d, %d], acquireFence: %d, tr: 0x%2x, AFBC: %1d, dataSpace: 0x%8x, format: %s\n",
- mLayerBuffer, fd, fd1, fd2, mAcquireFence, mTransform, mCompressed, mDataSpace, getFormatStr(format, mCompressed? AFBC : 0).string());
+ mLayerBuffer, fd, fd1, fd2, mAcquireFence, mTransform, mCompressed, mDataSpace, getFormatStr(format, mCompressed? AFBC : 0).c_str());
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: %.2f, priority: %d, windowIndex: %d\n", mFps, mOverlayPriority,
@@ -1128,38 +1136,40 @@
if ((mDisplay != NULL) && (mDisplay->mResourceManager != NULL)) {
result.appendFormat("MPPFlags for otfMPP\n");
for (uint32_t i = 0; i < mDisplay->mResourceManager->getOtfMPPSize(); i++) {
- result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getOtfMPP(i)->mName.string(),
+ result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getOtfMPP(i)->mName.c_str(),
mCheckMPPFlag[mDisplay->mResourceManager->getOtfMPP(i)->mLogicalType]);
}
result.appendFormat("\n");
result.appendFormat("MPPFlags for m2mMPP\n");
for (uint32_t i = 0; i < mDisplay->mResourceManager->getM2mMPPSize(); i++) {
- result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getM2mMPP(i)->mName.string(),
+ result.appendFormat("[%s: 0x%" PRIx64 "] ", mDisplay->mResourceManager->getM2mMPP(i)->mName.c_str(),
mCheckMPPFlag[mDisplay->mResourceManager->getM2mMPP(i)->mLogicalType]);
if ((i!=0) && (i%4==0)) result.appendFormat("\n");
}
result.appendFormat("\n");
}
- ALOGD("%s", result.string());
+ ALOGD("%s", result.c_str());
result.clear();
if ((mOtfMPP == NULL) && (mM2mMPP == NULL))
ALOGD("\tresource is not assigned.");
if (mOtfMPP != NULL)
- ALOGD("\tassignedMPP: %s", mOtfMPP->mName.string());
+ ALOGD("\tassignedMPP: %s", mOtfMPP->mName.c_str());
if (mM2mMPP != NULL)
- ALOGD("\tassignedM2mMPP: %s", mM2mMPP->mName.string());
+ ALOGD("\tassignedM2mMPP: %s", mM2mMPP->mName.c_str());
ALOGD("\t++ dump midImg ++");
dumpExynosImage(result, mMidImg);
- ALOGD("%s", result.string());
+ ALOGD("%s", result.c_str());
}
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 c180fb3..e1df54d 100644
--- a/libhwc2.1/libdevice/ExynosLayer.h
+++ b/libhwc2.1/libdevice/ExynosLayer.h
@@ -77,6 +77,7 @@
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,
};
@@ -91,10 +92,20 @@
/**
* 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)
*/
@@ -178,6 +189,8 @@
*/
buffer_handle_t mLayerBuffer;
+ nsecs_t mLastUpdateTime;
+
/**
* Surface Damage
*/
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
index febd76d..eab4cd1 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.cpp
@@ -312,3 +312,12 @@
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 9aa2798..69fc4f0 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDeviceDrmInterface.h
@@ -31,6 +31,10 @@
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,
diff --git a/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp b/libhwc2.1/libdisplayinterface/ExynosDeviceInterface.cpp
index eb54aca..4893310 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)
{
@@ -101,7 +99,7 @@
queried_format.format = format;
queried_format.reserved = 0;
resourceManager->makeFormatRestrictions(queried_format);
- HDEBUGLOGD(eDebugAttrSetting, "%s : %d", getMPPStr(hwType).string(), format);
+ HDEBUGLOGD(eDebugAttrSetting, "%s : %d", getMPPStr(hwType).c_str(), format);
}
}
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 @@
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 19a5d2f..6f11eb7 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.cpp
@@ -31,8 +31,10 @@
#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;
@@ -118,21 +120,26 @@
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()
@@ -159,6 +166,7 @@
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};
@@ -198,7 +206,7 @@
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; });
@@ -257,7 +265,7 @@
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) {
@@ -289,11 +297,10 @@
if (config.layer || config.buffer_id) {
Mutex::Autolock lock(mMutex);
- auto &cachedBuffers = mCachedLayerBuffers[config.layer];
- auto maxCachedBufferSize = MAX_CACHED_BUFFERS_PER_LAYER;
- if (config.protection && config.layer && config.layer->mM2mMPP) {
- maxCachedBufferSize = MAX_CACHED_SECURE_BUFFERS_PER_G2D_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",
@@ -311,6 +318,7 @@
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);
@@ -319,7 +327,7 @@
return 0;
}
-void FramebufferManager::flip(bool hasSecureFrameBuffer) {
+void FramebufferManager::flip(const bool hasSecureFrameBuffer, const bool hasM2mSecureLayerBuffer) {
bool needCleanup = false;
{
Mutex::Autolock lock(mMutex);
@@ -327,6 +335,10 @@
if (!hasSecureFrameBuffer) {
destroySecureFramebufferLocked();
}
+
+ if (!hasM2mSecureLayerBuffer) {
+ destroyM2mSecureLayerBufferLocked();
+ }
needCleanup = mCleanBuffers.size() > 0;
}
@@ -339,6 +351,7 @@
{
Mutex::Autolock lock(mMutex);
mCachedLayerBuffers.clear();
+ mCachedM2mSecureLayerBuffers.clear();
mCleanBuffers.clear();
}
@@ -356,31 +369,50 @@
}
}
-void FramebufferManager::markInuseLayerLocked(const ExynosLayer *layer) {
- if (mCacheShrinkPending) {
+void FramebufferManager::markInuseLayerLocked(const ExynosLayer *layer,
+ const bool isM2mSecureLayer) {
+ if (!isM2mSecureLayer && mCacheShrinkPending) {
mCachedLayersInuse.insert(layer);
}
+
+ if (isM2mSecureLayer && mCacheM2mSecureShrinkPending) {
+ mCachedM2mSecureLayersInuse.insert(layer);
+ }
}
void FramebufferManager::destroyUnusedLayersLocked() {
- if (!mCacheShrinkPending || mCachedLayersInuse.size() == mCachedLayerBuffers.size()) {
- mCachedLayersInuse.clear();
- return;
- }
-
- ALOGW("FBManager: shrink cached layers from %zu to %zu", mCachedLayerBuffers.size(),
- mCachedLayersInuse.size());
-
- 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;
+ 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 = 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() {
@@ -406,6 +438,22 @@
}
}
+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);
}
@@ -429,7 +477,8 @@
return NO_ERROR;
}
-ExynosDisplayDrmInterface::ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay)
+ExynosDisplayDrmInterface::ExynosDisplayDrmInterface(ExynosDisplay *exynosDisplay):
+ mMonitorDescription{0}
{
mType = INTERFACE_TYPE_DRM;
init(exynosDisplay);
@@ -452,6 +501,7 @@
void ExynosDisplayDrmInterface::init(ExynosDisplay *exynosDisplay)
{
mExynosDisplay = exynosDisplay;
+ mDisplayTraceName = mExynosDisplay->mDisplayTraceName;
mDrmDevice = NULL;
mDrmCrtc = NULL;
mDrmConnector = NULL;
@@ -597,6 +647,27 @@
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;
@@ -620,12 +691,12 @@
mReadbackInfo.init(mDrmDevice, drmDisplayId);
if ((mDrmCrtc = mDrmDevice->GetCrtcForDisplay(drmDisplayId)) == NULL) {
ALOGE("%s:: GetCrtcForDisplay is NULL (id: %d)",
- mExynosDisplay->mDisplayName.string(), drmDisplayId);
+ mExynosDisplay->mDisplayName.c_str(), drmDisplayId);
return -EINVAL;
}
if ((mDrmConnector = mDrmDevice->GetConnectorForDisplay(drmDisplayId)) == NULL) {
ALOGE("%s:: GetConnectorForDisplay is NULL (id: %d)",
- mExynosDisplay->mDisplayName.string(), drmDisplayId);
+ mExynosDisplay->mDisplayName.c_str(), drmDisplayId);
return -EINVAL;
}
@@ -666,7 +737,7 @@
getLowPowerDrmModeModeInfo();
- mDrmVSyncWorker.Init(mDrmDevice, drmDisplayId);
+ mDrmVSyncWorker.Init(mDrmDevice, drmDisplayId, mDisplayTraceName);
mDrmVSyncWorker.RegisterCallback(std::shared_ptr<VsyncCallback>(this));
if (!mDrmDevice->planes().empty()) {
@@ -683,6 +754,8 @@
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__);
@@ -720,13 +793,37 @@
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;
}
@@ -824,7 +921,7 @@
ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
if (exynosDevice->isCallbackAvailable(HWC2_CALLBACK_VSYNC_2_4)) {
- ATRACE_INT(vsyncPeriodTag, 0);
+ DISPLAY_ATRACE_INT(vsyncPeriodTag, 0);
}
return NO_ERROR;
@@ -899,11 +996,12 @@
/* 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;
@@ -920,14 +1018,15 @@
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());
@@ -954,7 +1053,7 @@
for (uint32_t i = 0; i < num_modes; i++) {
auto mode = mDrmConnector->modes().at(i);
ALOGD("%s display config[%d] %s:: id(%d), clock(%d), flags(%d), type(%d)",
- mExynosDisplay->mDisplayName.string(), i, mode.name().c_str(), mode.id(), mode.clock(), mode.flags(), mode.type());
+ mExynosDisplay->mDisplayName.c_str(), i, mode.name().c_str(), mode.id(), mode.clock(), mode.flags(), mode.type());
ALOGD("\th_display(%d), h_sync_start(%d), h_sync_end(%d), h_total(%d), h_skew(%d)",
mode.h_display(), mode.h_sync_start(), mode.h_sync_end(), mode.h_total(), mode.h_skew());
ALOGD("\tv_display(%d), v_sync_start(%d), v_sync_end(%d), v_total(%d), v_scan(%d), v_refresh(%f)",
@@ -1081,8 +1180,9 @@
int32_t ExynosDisplayDrmInterface::setActiveConfigWithConstraints(
hwc2_config_t config, bool test)
{
- ALOGD("%s:: %s config(%d) test(%d)", __func__, mExynosDisplay->mDisplayName.string(), config,
+ ALOGD("%s:: %s config(%d) test(%d)", __func__, mExynosDisplay->mDisplayName.c_str(), 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()) {
@@ -1119,6 +1219,10 @@
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);
}
@@ -1204,11 +1308,15 @@
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;
@@ -1332,7 +1440,7 @@
if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
mExynosDisplay->mHdrTypes.push_back(HAL_HDR_DOLBY_VISION);
HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
- mExynosDisplay->mDisplayName.string(), HAL_HDR_DOLBY_VISION);
+ mExynosDisplay->mDisplayName.c_str(), HAL_HDR_DOLBY_VISION);
}
std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HDR10");
if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
@@ -1341,23 +1449,23 @@
mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HDR10_PLUS);
}
HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
- mExynosDisplay->mDisplayName.string(), HAL_HDR_HDR10);
+ mExynosDisplay->mDisplayName.c_str(), HAL_HDR_HDR10);
}
std::tie(typeBit, ret) = prop_hdr_formats.GetEnumValueWithName("HLG");
if ((ret == 0) && (hdr_formats & (1 << typeBit))) {
mExynosDisplay->mHdrTypes.push_back(HAL_HDR_HLG);
HDEBUGLOGD(eDebugHWC, "%s: supported hdr types : %d",
- mExynosDisplay->mDisplayName.string(), HAL_HDR_HLG);
+ mExynosDisplay->mDisplayName.c_str(), HAL_HDR_HLG);
}
ALOGI("%s: get hdrCapabilities info max_luminance(%" PRId64 "), "
"max_avg_luminance(%" PRId64 "), min_luminance(%" PRId64 "), "
"hdr_formats(0x%" PRIx64 ")",
- mExynosDisplay->mDisplayName.string(),
+ mExynosDisplay->mDisplayName.c_str(),
max_luminance, max_avg_luminance, min_luminance, hdr_formats);
ALOGI("%s: mHdrTypes size(%zu), maxLuminance(%f), maxAverageLuminance(%f), minLuminance(%f)",
- mExynosDisplay->mDisplayName.string(), mExynosDisplay->mHdrTypes.size(), mExynosDisplay->mMaxLuminance,
+ mExynosDisplay->mDisplayName.c_str(), mExynosDisplay->mHdrTypes.size(), mExynosDisplay->mMaxLuminance,
mExynosDisplay->mMaxAverageLuminance, mExynosDisplay->mMinLuminance);
return 0;
@@ -1365,11 +1473,11 @@
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;
}
@@ -1381,6 +1489,7 @@
const std::unique_ptr<DrmPlane> &plane,
uint32_t &fbId)
{
+ ATRACE_CALL();
int ret = NO_ERROR;
if (fbId == 0) {
@@ -1579,7 +1688,7 @@
HDEBUGLOGD(eDebugWindowUpdate,
"%s: partial region updated [%d, %d, %d, %d] -> [%d, %d, %d, %d] blob(%d)",
- mExynosDisplay->mDisplayName.string(),
+ mExynosDisplay->mDisplayName.c_str(),
mPartialRegionState.partial_rect.x1,
mPartialRegionState.partial_rect.y1,
mPartialRegionState.partial_rect.x2,
@@ -1661,12 +1770,16 @@
std::unordered_map<uint32_t, uint32_t> planeEnableInfo;
android::String8 result;
bool hasSecureFrameBuffer = false;
+ bool hasM2mSecureLayerBuffer = false;
- mFrameCounter++;
+ 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();
}
});
@@ -1763,6 +1876,7 @@
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;
}
@@ -1770,15 +1884,18 @@
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;
}
}
@@ -1792,6 +1909,15 @@
(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;
@@ -1924,6 +2050,21 @@
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;
@@ -1937,6 +2078,11 @@
(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;
@@ -1954,7 +2100,8 @@
int32_t ExynosDisplayDrmInterface::clearDisplay(bool needModeClear)
{
ExynosDevice *exynosDevice = mExynosDisplay->mDevice;
- const bool isAsyncOff = needModeClear && exynosDevice->isDispOffAsyncSupported();
+ const bool isAsyncOff = needModeClear && exynosDevice->isDispOffAsyncSupported() &&
+ !exynosDevice->hasOtherDisplayOn(mExynosDisplay);
int ret = NO_ERROR;
DrmModeAtomicReq drmReq(this);
@@ -2050,7 +2197,7 @@
result.appendFormat("atomic commit error\n");
if (hwcCheckDebugMessages(eDebugDisplayInterfaceConfig) == false)
dumpAtomicCommitInfo(result);
- HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "%s", result.string());
+ HWC_LOGE(mDrmDisplayInterface->mExynosDisplay, "%s", result.c_str());
}
if(mPset)
@@ -2093,7 +2240,7 @@
return result;
if (debugPrint)
- ALOGD("%s atomic config ++++++++++++", mDrmDisplayInterface->mExynosDisplay->mDisplayName.string());
+ ALOGD("%s atomic config ++++++++++++", mDrmDisplayInterface->mExynosDisplay->mDisplayName.c_str());
for (int i = 0; i < drmModeAtomicGetCursor(mPset); i++) {
const DrmProperty *property = NULL;
@@ -2155,10 +2302,10 @@
if (debugPrint)
ALOGD("property[%d] %s object_id: %d, property_id: %d, name: %s, value: %" PRId64 ")\n",
- i, objectName.string(), mPset->items[i].object_id, mPset->items[i].property_id, property->name().c_str(), mPset->items[i].value);
+ i, objectName.c_str(), mPset->items[i].object_id, mPset->items[i].property_id, property->name().c_str(), mPset->items[i].value);
else
result.appendFormat("property[%d] %s object_id: %d, property_id: %d, name: %s, value: %" PRId64 ")\n",
- i, objectName.string(), mPset->items[i].object_id, mPset->items[i].property_id, property->name().c_str(), mPset->items[i].value);
+ i, objectName.c_str(), mPset->items[i].object_id, mPset->items[i].property_id, property->name().c_str(), mPset->items[i].value);
}
return result;
}
@@ -2378,6 +2525,11 @@
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) {
@@ -2397,14 +2549,14 @@
{
if ((mDrmDevice == nullptr) || (mDrmConnector == nullptr)) {
ALOGE("%s: display(%s) mDrmDevice(%p), mDrmConnector(%p)",
- __func__, mExynosDisplay->mDisplayName.string(),
+ __func__, mExynosDisplay->mDisplayName.c_str(),
mDrmDevice, mDrmConnector);
return HWC2_ERROR_UNSUPPORTED;
}
if (mDrmConnector->edid_property().id() == 0) {
ALOGD("%s: edid_property is not supported",
- mExynosDisplay->mDisplayName.string());
+ mExynosDisplay->mDisplayName.c_str());
return HWC2_ERROR_UNSUPPORTED;
}
@@ -2421,14 +2573,14 @@
}
if (blobId == 0) {
ALOGD("%s: edid_property is supported but blob is not valid",
- mExynosDisplay->mDisplayName.string());
+ mExynosDisplay->mDisplayName.c_str());
return getDisplayFakeEdid(*outPort, *outDataSize, outData);
}
blob = drmModeGetPropertyBlob(mDrmDevice->fd(), blobId);
if (blob == nullptr) {
ALOGD("%s: Failed to get blob",
- mExynosDisplay->mDisplayName.string());
+ mExynosDisplay->mDisplayName.c_str());
return HWC2_ERROR_UNSUPPORTED;
}
@@ -2443,3 +2595,16 @@
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 561e5b3..3997b0f 100644
--- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
+++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterface.h
@@ -37,6 +37,9 @@
/* 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
@@ -60,7 +63,7 @@
// 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);
@@ -68,7 +71,7 @@
// 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
@@ -109,7 +112,8 @@
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,
@@ -123,15 +127,19 @@
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.
@@ -140,11 +148,15 @@
// 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;
@@ -152,8 +164,9 @@
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_SECURE_BUFFERS_PER_G2D_LAYER = 3;
+ static constexpr size_t MAX_CACHED_M2M_SECURE_BUFFERS_PER_LAYER = 3;
};
inline bool isFramebuffer(const ExynosLayer *layer) {
@@ -161,10 +174,12 @@
}
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;
}
@@ -324,10 +339,12 @@
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 {
@@ -406,6 +423,7 @@
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);
@@ -415,6 +433,7 @@
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 {
@@ -490,10 +509,12 @@
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;
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 @@
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 @@
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/drmcrtc.cpp b/libhwc2.1/libdrmresource/drm/drmcrtc.cpp
index 21fd040..55cee3c 100644
--- a/libhwc2.1/libdrmresource/drm/drmcrtc.cpp
+++ b/libhwc2.1/libdrmresource/drm/drmcrtc.cpp
@@ -97,6 +97,8 @@
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_);
@@ -126,6 +128,8 @@
properties_.push_back(&histogram_threshold_property_);
properties_.push_back(&histogram_position_property_);
+ properties_.push_back(&rcd_plane_id_property_);
+
return 0;
}
@@ -262,4 +266,8 @@
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 3132bc5..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 @@
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;
@@ -267,6 +306,23 @@
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;
@@ -280,11 +336,13 @@
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..a795fb3 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 @@
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.c_str());
+ hw_vsync_enabled_tag_.appendFormat("HWCVsync for %s", display_trace_name.c_str());
return InitWorker();
}
@@ -71,8 +73,8 @@
last_timestamp_ = -1;
Unlock();
- ATRACE_INT("HWCVsync", static_cast<int32_t>(enabled));
- ATRACE_INT64(hwVsyncPeriodTag, 0);
+ ATRACE_INT(hw_vsync_enabled_tag_.c_str(), static_cast<int32_t>(enabled));
+ ATRACE_INT64(hw_vsync_period_tag_.c_str(), 0);
Signal();
}
@@ -211,8 +213,8 @@
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_.c_str(), period);
+ ALOGV("HW vsync period %" PRId64 "ns for %s", period, display_trace_name_.c_str());
}
last_timestamp_ = timestamp;
diff --git a/libhwc2.1/libdrmresource/include/drmcrtc.h b/libhwc2.1/libdrmresource/include/drmcrtc.h
index 9149f51..6bb73fd 100644
--- a/libhwc2.1/libdrmresource/include/drmcrtc.h
+++ b/libhwc2.1/libdrmresource/include/drmcrtc.h
@@ -72,6 +72,8 @@
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_;
}
@@ -113,6 +115,8 @@
DrmProperty histogram_threshold_property_;
DrmProperty histogram_position_property_;
+ DrmProperty rcd_plane_id_property_;
+
std::vector<DrmProperty *> properties_;
};
} // namespace android
diff --git a/libhwc2.1/libdrmresource/include/drmeventlistener.h b/libhwc2.1/libdrmresource/include/drmeventlistener.h
index 474b116..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;
@@ -62,9 +64,19 @@
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 @@
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 @@
void UEventHandler();
void DRMEventHandler();
void TUIEventHandler();
+ void SysfsEventHandler(int fd);
UniqueFd epoll_fd_;
UniqueFd uevent_fd_;
@@ -102,7 +117,10 @@
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 <stdint.h>
-#include <map>
-
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include <stdint.h>
+#include <utils/String8.h>
+
+#include <map>
+
+#include "drmdevice.h"
+#include "worker.h"
namespace android {
@@ -39,7 +40,7 @@
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 @@
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 36fde04..ed99759 100644
--- a/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
+++ b/libhwc2.1/libexternaldisplay/ExynosExternalDisplay.cpp
@@ -30,15 +30,11 @@
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;
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 @@
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 ba8f996..fd8278b 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.cpp
+++ b/libhwc2.1/libhwcService/ExynosHWCService.cpp
@@ -492,4 +492,28 @@
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 3400fcc..abb525f 100644
--- a/libhwc2.1/libhwcService/ExynosHWCService.h
+++ b/libhwc2.1/libhwcService/ExynosHWCService.h
@@ -79,6 +79,11 @@
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();
diff --git a/libhwc2.1/libhwcService/IExynosHWC.cpp b/libhwc2.1/libhwcService/IExynosHWC.cpp
index e0867fa..f092696 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.cpp
+++ b/libhwc2.1/libhwcService/IExynosHWC.cpp
@@ -64,6 +64,8 @@
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> {
@@ -445,7 +447,7 @@
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;
}
@@ -459,6 +461,30 @@
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");
@@ -713,6 +739,22 @@
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 23cb113..bf51c85 100644
--- a/libhwc2.1/libhwcService/IExynosHWC.h
+++ b/libhwc2.1/libhwcService/IExynosHWC.h
@@ -74,6 +74,9 @@
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 1c10909..1e963b9 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 @@
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;
@@ -464,7 +489,7 @@
String8 result;
dumpExynosImage(result, img);
- ALOGD("%s", result.string());
+ ALOGD("%s", result.c_str());
}
void dumpExynosImage(String8& result, exynos_image &img)
@@ -472,7 +497,7 @@
result.appendFormat("\tbufferHandle: %p, fullWidth: %d, fullHeight: %d, x: %d, y: %d, w: %d, "
"h: %d, format: %s\n",
img.bufferHandle, img.fullWidth, img.fullHeight, img.x, img.y, img.w, img.h,
- getFormatStr(img.format, img.compressed ? AFBC : 0).string());
+ getFormatStr(img.format, img.compressed ? AFBC : 0).c_str());
result.appendFormat("\tusageFlags: 0x%" PRIx64 ", layerFlags: 0x%8x, acquireFenceFd: %d, releaseFenceFd: %d\n",
img.usageFlags, img.layerFlags, img.acquireFenceFd, img.releaseFenceFd);
result.appendFormat("\tdataSpace(%d), blending(%d), transform(0x%2x), afbc(%d)\n",
@@ -647,11 +672,13 @@
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 @@
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 @@
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:
@@ -891,7 +922,7 @@
for (const auto& trace : info.traces) {
FT_LOGD("> dir: %d, type: %d, ip: %d, time:%s", trace.direction, trace.type, trace.ip,
- getLocalTimeStr(trace.time).string());
+ getLocalTimeStr(trace.time).c_str());
}
}
@@ -925,7 +956,7 @@
}
}
- FT_LOGW("%s", errString.string());
+ FT_LOGW("%s", errString.c_str());
};
reportLeakFds(+1);
@@ -993,10 +1024,10 @@
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);
diff --git a/libhwc2.1/libhwchelper/ExynosHWCHelper.h b/libhwc2.1/libhwchelper/ExynosHWCHelper.h
index 3262634..87b6163 100644
--- a/libhwc2.1/libhwchelper/ExynosHWCHelper.h
+++ b/libhwc2.1/libhwchelper/ExynosHWCHelper.h
@@ -82,22 +82,35 @@
};
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 @@
* 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 @@
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 @@
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 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);
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
index 0b3099d..eb4f0bb 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.cpp
@@ -43,7 +43,15 @@
{{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 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);
@@ -73,8 +81,9 @@
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),
@@ -85,9 +94,6 @@
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);
@@ -119,7 +125,7 @@
mResolutionInfo.nPanelType[2] = PANEL_LEGACY;
char value[PROPERTY_VALUE_MAX];
- const char *earlyWakeupNodeBase = EARLY_WAKUP_NODE_0_BASE;
+ 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;
@@ -130,6 +136,8 @@
mBrightnessController = std::make_unique<BrightnessController>(
mIndex, [this]() { mDevice->onRefresh(mDisplayId); },
[this]() { updatePresentColorConversionInfo(); });
+
+ mDisplayControl.multiThreadedPresent = true;
}
ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
@@ -170,8 +178,9 @@
}
int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) {
- if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON)) {
- mPendActiveConfig = config;
+ 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;
@@ -180,8 +189,8 @@
}
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);
@@ -195,19 +204,21 @@
ALOGI("%s:: Same display config is set", __func__);
return HWC2_ERROR_NONE;
}
- if (!mPowerModeState.has_value() || (*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);
}
@@ -237,13 +248,13 @@
ALOGD("%s: mode=%s (%d) vsyncPeriod=%d", __func__, modeStr, config,
mode.vsyncPeriod);
- ret = property_set(PROPERTY_BOOT_MODE, modeStr);
+ ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), 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).c_str(), nullptr);
ALOGD("%s: clearing boot mode", __func__);
return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
@@ -251,7 +262,7 @@
int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
char modeStr[PROPERTY_VALUE_MAX];
- auto ret = property_get(PROPERTY_BOOT_MODE, modeStr, "");
+ auto ret = property_get(getPropertyBootModeStr(mDisplayId).c_str(), modeStr, "");
if (ret <= 0) {
return mDisplayInterface->getDefaultModeId(outConfig);
@@ -274,6 +285,10 @@
updateAppliedActiveConfig(0, 0);
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();
}
@@ -370,6 +385,9 @@
} 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 (mPowerModeState.has_value() && (mode == static_cast<int32_t>(mPowerModeState.value()))) {
@@ -385,6 +403,7 @@
else
mDREnable = mDRDefault;
+ if (mOperationRateManager) mOperationRateManager->onPowerMode(mode);
switch (mode) {
case HWC2_POWER_MODE_DOZE_SUSPEND:
case HWC2_POWER_MODE_DOZE:
@@ -521,130 +540,225 @@
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();
+ DISPLAY_ATRACE_CALL();
+ DISPLAY_LOGI("%s: enabled=%d", __func__, enabled);
{
- ATRACE_NAME("wait for power mode on");
+ 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);
})) {
- ALOGW("%s(%d) wait for power mode on timeout !", __func__, enabled);
+ DISPLAY_LOGW("%s: wait for power mode on timeout !", __func__);
return TIMED_OUT;
}
}
}
- if (enabled) {
- ATRACE_NAME("wait for peak refresh rate");
- std::unique_lock<std::mutex> lock(mPeakRefreshRateMutex);
- mNotifyPeakRefreshRate = true;
- if (!mPeakRefreshRateCondition.wait_for(lock,
- std::chrono::milliseconds(
- kLhbmWaitForPeakRefreshRateMs),
- [this]() { return isCurrentPeakRefreshRate(); })) {
- ALOGW("setLhbmState(on) wait for peak refresh rate timeout !");
- return TIMED_OUT;
- }
- }
-
- if (enabled) {
- setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs);
- }
-
- bool wasDisabled =
- mBrightnessController
- ->checkSysfsStatus(BrightnessController::kLocalHbmModeFileNode,
- {std::to_string(static_cast<int>(
- BrightnessController::LhbmMode::DISABLED))},
- 0);
+ 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) {
- ALOGW("lhbm is at DISABLED state, skip disabling");
+ DISPLAY_LOGW("%s: lhbm is at DISABLED state, skip disabling", __func__);
return NO_ERROR;
} else if (enabled && !wasDisabled) {
requestLhbm(true);
- ALOGI("lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer");
+ DISPLAY_LOGI("%s: lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer",
+ __func__);
return NO_ERROR;
}
- int64_t lhbmEnablingNanos;
- std::vector<std::string> checkingValue = {
- std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))};
- if (enabled) {
- 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(enabled);
- constexpr uint32_t kSysfsCheckTimeoutMs = 500;
- ALOGI("setLhbmState =%d", enabled);
- bool succeed =
- mBrightnessController->checkSysfsStatus(BrightnessController::kLocalHbmModeFileNode,
- checkingValue, ms2ns(kSysfsCheckTimeoutMs));
- if (!succeed) {
- ALOGE("failed to update lhbm mode");
- if (enabled) {
- setLHBMRefreshRateThrottle(0);
+ std::vector<std::string> checkingValue;
+ if (!enabled) {
+ ATRACE_NAME("disable_lhbm");
+ {
+ Mutex::Autolock lock(mDisplayMutex);
+ restoreLhbmDisplayConfigLocked();
}
- return -ENODEV;
+ 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;
}
- if (enabled) {
- int64_t lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC);
- bool enablingStateSupported = !mFramesToReachLhbmPeakBrightness;
+ 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);
+ {
+ 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 (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()) {
+ DISPLAY_LOGE("%s: failed to blindly wait for peak refresh rate=%d, i=%d", __func__,
+ peakRate, i);
+ ret = -ENODEV;
+ goto enable_err;
+ }
+ }
+ }
+
+ 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) {
- ATRACE_NAME("lhbm_wait_peak_brightness");
- if (!mBrightnessController
- ->checkSysfsStatus(BrightnessController::kLocalHbmModeFileNode,
+ ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
{std::to_string(static_cast<int>(
BrightnessController::LhbmMode::ENABLED))},
- ms2ns(kSysfsCheckTimeoutMs))) {
- ALOGE("failed to wait for lhbm becoming effective");
- return -EIO;
+ 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
- ATRACE_NAME("lhbm_wait_apply");
- if (mDisplayInterface->waitVBlank()) {
- ALOGE("%s failed to wait vblank for taking effect", __func__);
- return -ENODEV;
- }
- ATRACE_NAME("lhbm_wait_peak_brightness");
- for (int32_t i = mFramesToReachLhbmPeakBrightness; i > 0; i--) {
- if (mDisplayInterface->waitVBlank()) {
- ALOGE("%s failed to wait vblank for peak brightness, %d", __func__, i);
- return -ENODEV;
+ 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;
}
}
}
- ALOGI("lhbm delay mode: %s, latency(ms): total: %d cmd: %d\n",
- enablingStateSupported ? "poll" : "fixed",
- static_cast<int>((systemTime(SYSTEM_TIME_MONOTONIC) - lhbmEnablingNanos) / 1000000),
- static_cast<int>((lhbmEnablingDoneNanos - lhbmEnablingNanos) / 1000000));
- } else {
- setLHBMRefreshRateThrottle(0);
- // lhbm takes effect at next vblank
- ATRACE_NAME("lhbm_wait_apply");
- if (mDisplayInterface->waitVBlank()) {
- ALOGE("%s failed to wait vblank for taking effect", __func__);
- return -ENODEV;
- }
}
+ 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 = enabled;
+ 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() {
@@ -657,6 +771,7 @@
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>(
@@ -864,6 +979,7 @@
int ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
const VrrThrottleRequester requester) {
+ ATRACE_CALL();
ALOGI("%s() requester(%u) set delay to %" PRId64 "ns", __func__, toUnderlying(requester),
delayNanos);
if (delayNanos < 0) {
@@ -881,12 +997,12 @@
}
}
+ DISPLAY_ATRACE_INT64("RefreshRateDelay", ns2ms(maxDelayNanos));
if (mRefreshRateDelayNanos == maxDelayNanos) {
return NO_ERROR;
}
mRefreshRateDelayNanos = maxDelayNanos;
-
return setDisplayIdleDelayNanos(mRefreshRateDelayNanos, DispIdleTimerRequester::VRR_THROTTLE);
}
@@ -902,12 +1018,16 @@
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");
}
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;
@@ -935,31 +1055,30 @@
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)) {
@@ -968,6 +1087,7 @@
" -> %" PRIu64 ")",
__func__, mAppliedActiveConfig, newConfig, mLastRefreshRateAppliedNanos, ts);
mLastRefreshRateAppliedNanos = ts;
+ DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
}
mAppliedActiveConfig = newConfig;
@@ -978,6 +1098,7 @@
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 &&
diff --git a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
index e66bb2a..323eb5a 100644
--- a/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
+++ b/libhwc2.1/libmaindisplay/ExynosPrimaryDisplay.h
@@ -25,7 +25,7 @@
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);
@@ -64,6 +64,8 @@
virtual int32_t setBootDisplayConfig(int32_t config) override;
virtual int32_t clearBootDisplayConfig() override;
virtual int32_t getPreferredDisplayConfigInternal(int32_t* outConfig) override;
+ virtual bool isConfigSettingEnabled() override;
+ virtual void enableConfigSetting(bool en) override;
protected:
/* setPowerMode(int32_t mode)
@@ -88,6 +90,8 @@
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";
@@ -96,7 +100,6 @@
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;
@@ -113,14 +116,25 @@
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;
+ bool mConfigSettingDisabled = false;
+ int64_t mConfigSettingDisabledTimestamp = 0;
// timeout value of waiting for peak refresh rate
- static constexpr uint32_t kLhbmWaitForPeakRefreshRateMs = 200;
- static constexpr uint32_t kLhbmRefreshRateThrottleMs = 1000;
+ 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 =
diff --git a/libhwc2.1/libresource/ExynosMPP.cpp b/libhwc2.1/libresource/ExynosMPP.cpp
index 740cec7..fae248a 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 @@
memset(&mMidImg, 0, sizeof(mMidImg));
mMidImg.acquireFenceFd = -1;
mMidImg.releaseFenceFd = -1;
+
+ mHWResourceAmount.clear();
}
ExynosMPPSource::ExynosMPPSource(uint32_t sourceType, void *source)
@@ -130,6 +130,40 @@
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 @@
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 @@
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 @@
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))
@@ -807,7 +844,7 @@
if (mExynosMPP == NULL)
return false;
- ALOGI("%s threadLoop is started", mExynosMPP->mName.string());
+ ALOGI("%s threadLoop is started", mExynosMPP->mName.c_str());
while(mRunning) {
Mutex::Autolock lock(mMutex);
while((mFreedBuffers.size() == 0) &&
@@ -824,7 +861,7 @@
if ((mStateFences.size() != 0) &&
(mExynosMPP->mHWState != MPP_HW_STATE_RUNNING)) {
ALOGW("%s, mHWState(%d) but mStateFences size(%zu)",
- mExynosMPP->mName.string(), mExynosMPP->mHWState,
+ mExynosMPP->mName.c_str(), mExynosMPP->mHWState,
mStateFences.size());
checkStateFences();
}
@@ -852,14 +889,14 @@
dumpExynosMPPImgInfo(eDebugMPP|eDebugFence|eDebugBuf, freeBuffer);
if (fence_valid(freeBuffer.acrylicAcquireFenceFd)) {
if (sync_wait(freeBuffer.acrylicAcquireFenceFd, 1000) < 0)
- HWC_LOGE(NULL, "%s:: acquire fence sync_wait error", mExynosMPP->mName.string());
+ HWC_LOGE(NULL, "%s:: acquire fence sync_wait error", mExynosMPP->mName.c_str());
freeBuffer.acrylicAcquireFenceFd =
fence_close(freeBuffer.acrylicAcquireFenceFd, mExynosMPP->mAssignedDisplay,
FENCE_TYPE_SRC_ACQUIRE, FENCE_IP_ALL);
}
if (fence_valid(freeBuffer.acrylicReleaseFenceFd)) {
if (sync_wait(freeBuffer.acrylicReleaseFenceFd, 1000) < 0)
- HWC_LOGE(NULL, "%s:: release fence sync_wait error", mExynosMPP->mName.string());
+ HWC_LOGE(NULL, "%s:: release fence sync_wait error", mExynosMPP->mName.c_str());
freeBuffer.acrylicReleaseFenceFd =
fence_close(freeBuffer.acrylicReleaseFenceFd, mExynosMPP->mAssignedDisplay,
FENCE_TYPE_SRC_RELEASE, FENCE_IP_ALL);
@@ -885,7 +922,7 @@
if (fence_valid(fence)) {
if (sync_wait(fence, 5000) < 0) {
HWC_LOGE(NULL, "%s::[%s][%d] sync_wait(%d) error(%s)", __func__,
- mExynosMPP->mName.string(), mExynosMPP->mLogicalIndex, fence, strerror(errno));
+ mExynosMPP->mName.c_str(), mExynosMPP->mLogicalIndex, fence, strerror(errno));
ret = false;
}
fence = fence_close(fence, mExynosMPP->mAssignedDisplay,
@@ -964,9 +1001,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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,
@@ -2855,7 +2912,7 @@
assignedDisplayType = mAssignedDisplay->mType;
result.appendFormat("%s: types mppType(%d), (p:%d, l:0x%2x), indexs(p:%d, l:%d), preAssignDisplay(0x%2x)\n",
- mName.string(), mMPPType, mPhysicalType, mLogicalType, mPhysicalIndex, mLogicalIndex, mPreAssignDisplayInfo);
+ mName.c_str(), mMPPType, mPhysicalType, mLogicalType, mPhysicalIndex, mLogicalIndex, mPreAssignDisplayInfo);
result.appendFormat("\tEnable: %d, HWState: %d, AssignedState: %d, assignedDisplay(%d)\n",
mEnable, mHWState, mAssignedState, assignedDisplayType);
result.appendFormat("\tPrevAssignedState: %d, PrevAssignedDisplayType: %d, ReservedDisplay: %d\n",
diff --git a/libhwc2.1/libresource/ExynosMPP.h b/libhwc2.1/libresource/ExynosMPP.h
index dd9bfd7..715c9dc 100644
--- a/libhwc2.1/libresource/ExynosMPP.h
+++ b/libhwc2.1/libresource/ExynosMPP.h
@@ -113,6 +113,11 @@
#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
@@ -167,6 +172,7 @@
eMPPUnsupportedDRM = 1ULL << 31,
eMPPUnsupportedDynamicMeta = 1ULL << 32,
eMPPSatisfiedRestriction = 1ULL << 33,
+ eMPPExeedHWResource = 1ULL << 34,
};
enum {
@@ -220,11 +226,13 @@
#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 {
@@ -454,7 +462,22 @@
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);
@@ -547,6 +570,10 @@
/* MPP's attribute bit (supported feature bit) */
uint64_t mAttr;
+ uint32_t mAssignOrder;
+ uint32_t mAXIPortId;
+ uint32_t mHWBlockId;
+
bool mNeedSolidColorLayer;
ExynosMPP(ExynosResourceManager* resourceManager,
@@ -570,7 +597,7 @@
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);
@@ -639,11 +666,12 @@
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();
@@ -671,6 +699,13 @@
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);
@@ -711,6 +746,12 @@
*/
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 {
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 @@
* 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 @@
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 @@
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 ba30526..5e78eff 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 @@
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 @@
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);
}
@@ -188,14 +144,14 @@
HDEBUGLOGD(eDebugResourceManager, "otfMPP[%d]", i);
String8 dumpMPP;
mOtfMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
}
for (uint32_t i = 0; i < mM2mMPPs.size(); i++)
{
HDEBUGLOGD(eDebugResourceManager, "m2mMPP[%d]", i);
String8 dumpMPP;
mM2mMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
}
}
@@ -439,6 +395,11 @@
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)
@@ -475,15 +436,15 @@
HDEBUGLOGD(eDebugResourceManager, "AssignResource result");
String8 result;
display->mClientCompositionInfo.dump(result);
- HDEBUGLOGD(eDebugResourceManager, "%s", result.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", result.c_str());
result.clear();
display->mExynosCompositionInfo.dump(result);
- HDEBUGLOGD(eDebugResourceManager, "%s", result.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", result.c_str());
for (uint32_t i = 0; i < display->mLayers.size(); i++) {
result.clear();
HDEBUGLOGD(eDebugResourceManager, "%d layer(%p) dump", i, display->mLayers[i]);
display->mLayers[i]->printLayer();
- HDEBUGLOGD(eDebugResourceManager, "%s", result.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", result.c_str());
}
}
@@ -500,7 +461,7 @@
if ((ret = display->mExynosCompositionInfo.mM2mMPP->assignMPP(display, &display->mClientCompositionInfo)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, display->mExynosCompositionInfo.mM2mMPP->mName.string(), ret);
+ __func__, display->mExynosCompositionInfo.mM2mMPP->mName.c_str(), ret);
return ret;
}
int prevHasCompositionLayer = display->mExynosCompositionInfo.mHasCompositionLayer;
@@ -535,7 +496,7 @@
layer->mValidateCompositionType = HWC2_COMPOSITION_DEVICE;
ret = EXYNOS_ERROR_CHANGED;
HDEBUGLOGD(eDebugResourceManager, "\t%s is reserved without display because of panding work",
- m2mMPP->mName.string());
+ m2mMPP->mName.c_str());
m2mMPP->reserveMPP();
layer->mCheckMPPFlag[m2mMPP->mLogicalType] = eMPPHWBusy;
}
@@ -550,7 +511,7 @@
HWC_LOGE(display, "There is exynos composition layers but resource is null (%p)",
m2mMPP);
} else if ((check_ret = m2mMPP->prioritize(2)) != NO_ERROR) {
- HDEBUGLOGD(eDebugResourceManager, "%s setting priority error(%d)", m2mMPP->mName.string(), check_ret);
+ HDEBUGLOGD(eDebugResourceManager, "%s setting priority error(%d)", m2mMPP->mName.c_str(), check_ret);
if (check_ret < 0) {
HWC_LOGE(display, "Fail to set exynoscomposition priority(%d)", ret);
} else {
@@ -569,11 +530,11 @@
ret = EXYNOS_ERROR_CHANGED;
m2mMPP->resetUsedCapacity();
HDEBUGLOGD(eDebugResourceManager, "\t%s is reserved without display because of pending work",
- m2mMPP->mName.string());
+ m2mMPP->mName.c_str());
m2mMPP->reserveMPP();
}
} else {
- HDEBUGLOGD(eDebugResourceManager, "%s setting priority is ok", m2mMPP->mName.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s setting priority is ok", m2mMPP->mName.c_str());
}
}
@@ -605,7 +566,7 @@
}
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) {
@@ -694,12 +655,13 @@
{
String8 dumpMPP;
mM2mMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugCapacity, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugCapacity, "%s", dumpMPP.c_str());
}
}
}
return ret;
}
+
int32_t ExynosResourceManager::updateExynosComposition(ExynosDisplay *display)
{
int ret = NO_ERROR;
@@ -712,8 +674,9 @@
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;
@@ -725,29 +688,32 @@
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;
+ ((display->mDisplayControl.cursorSupport == false) ||
+ (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
+ (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignableState;
- HDEBUGLOGD(eDebugResourceManager, "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, remainNum(%d)",
- i, layer->mValidateCompositionType,
- layer->mSupportedMPPFlag, isAssignable, canChange, remainNum);
+ 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;
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), ret);
return ret;
}
layer->setExynosMidImage(dst_img);
- display->addExynosCompositionLayer(i);
+ float totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
+ display->addExynosCompositionLayer(i, totalUsedCapacity);
layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
remainNum--;
}
@@ -762,29 +728,32 @@
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;
+ ((display->mDisplayControl.cursorSupport == false) ||
+ (layer->mCompositionType != HWC2_COMPOSITION_CURSOR)) &&
+ (layer->mSupportedMPPFlag & m2mMPP->mLogicalType) && isAssignableState;
- HDEBUGLOGD(eDebugResourceManager, "\tlayer[%d] type: %d, 0x%8x, isAssignable: %d, canChange: %d, remainNum(%d)",
- i, layer->mValidateCompositionType,
- layer->mSupportedMPPFlag, isAssignable, canChange, remainNum);
+ 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;
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), ret);
return ret;
}
layer->setExynosMidImage(dst_img);
- display->addExynosCompositionLayer(i);
+ float totalUsedCapacity = getResourceUsedCapa(*m2mMPP);
+ display->addExynosCompositionLayer(i, totalUsedCapacity);
layer->mValidateCompositionType = HWC2_COMPOSITION_EXYNOS;
remainNum--;
}
@@ -792,8 +761,10 @@
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);
}
/*
@@ -816,13 +787,13 @@
if ((ret = otfMPP->resetAssignedState()) != NO_ERROR)
{
ALOGE("%s:: %s MPP resetAssignedState() error (%d)",
- __func__, otfMPP->mName.string(), ret);
+ __func__, otfMPP->mName.c_str(), ret);
}
// assign otfMPP again
if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, otfMPP->mName.string(), ret);
+ __func__, otfMPP->mName.c_str(), ret);
}
}
}
@@ -842,27 +813,27 @@
if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, otfMPP->mName.string(), ret);
+ __func__, otfMPP->mName.c_str(), 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.c_str());
}
if (m2mMPP != NULL) {
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), ret);
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.c_str());
}
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;
}
@@ -1034,27 +1005,35 @@
}
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.c_str(), -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);
+ __func__, mOtfMPPs[i]->mName.c_str(), ret);
return ret;
}
- compositionInfo->setExynosImage(src_img, dst_img);
- compositionInfo->setExynosMidImage(dst_img);
compositionInfo->mOtfMPP = mOtfMPPs[i];
display->mWindowNumUsed++;
- HDEBUGLOGD(eDebugResourceManager, "%s:: %s is assigned", __func__, mOtfMPPs[i]->mName.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s:: %s is assigned", __func__, mOtfMPPs[i]->mName.c_str());
return NO_ERROR;
}
}
@@ -1218,40 +1197,33 @@
uint32_t otfMppRatio = 1;
uint32_t m2mMppRatio = 1;
if (scaleUp) {
- std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
- [&dst_scale_img, &dst_img, &otfMpp, &otfMppRatio](auto m) {
- auto ratio = m->getMaxUpscale(dst_scale_img, dst_img);
- if (ratio > 1) {
- otfMpp = m;
- otfMppRatio = ratio;
- return true;
- }
- return false;
- });
+ for (ExynosMPP *m : mOtfMPPs) {
+ auto ratio = m->getMaxUpscale(dst_scale_img, dst_img);
+ if (ratio > 1) {
+ otfMpp = m;
+ otfMppRatio = ratio;
+ break;
+ }
+ }
const auto reqRatio = max(float(dst_img.w) / float(srcWidth * otfMppRatio),
float(dst_img.h) / float(srcHeight * otfMppRatio));
- std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(),
- [&src_img, &dst_scale_img, reqRatio, &m2mMpp, &m2mMppRatio](auto m) {
- float ratio = float(m->getMaxUpscale(src_img, dst_scale_img));
- if (ratio > reqRatio) {
- m2mMpp = m;
- m2mMppRatio = ratio;
- return true;
- }
- return false;
- });
+ for (ExynosMPP *m : mM2mMPPs) {
+ float ratio = float(m->getMaxUpscale(src_img, dst_scale_img));
+ if (ratio > reqRatio) {
+ m2mMpp = m;
+ m2mMppRatio = ratio;
+ break;
+ }
+ }
} else {
- std::find_if(mM2mMPPs.begin(), mM2mMPPs.end(),
- [&src_img, &dst_scale_img, display, &m2mMpp, &m2mMppRatio](auto m) {
- auto ratio = m->getMaxDownscale(*display, src_img, dst_scale_img);
- if (ratio > 1) {
- m2mMpp = m;
- m2mMppRatio = ratio;
- return true;
- }
- return false;
- });
-
+ for (ExynosMPP *m : mM2mMPPs) {
+ auto ratio = m->getMaxDownscale(*display, src_img, dst_scale_img);
+ if (ratio > 1) {
+ m2mMpp = m;
+ m2mMppRatio = ratio;
+ break;
+ }
+ }
const float otfSrcWidth = float(srcWidth / m2mMppRatio);
const float scaleRatio_H = otfSrcWidth / float(dst_img.w);
const float otfSrcHeight = float(srcHeight / m2mMppRatio);
@@ -1259,19 +1231,16 @@
const float displayRatio_V = float(dst_img.h) / float(display->mYres);
const float resolution = otfSrcWidth * otfSrcHeight * display->getBtsRefreshRate() / 1000;
- std::find_if(mOtfMPPs.begin(), mOtfMPPs.end(),
- [&dst_scale_img, &dst_img, resolution, scaleRatio_H, scaleRatio_V,
- displayRatio_V, &otfMpp, &otfMppRatio](auto m) {
- auto ratio = m->getDownscaleRestriction(dst_scale_img, dst_img);
+ for (ExynosMPP *m : mOtfMPPs) {
+ auto ratio = m->getDownscaleRestriction(dst_scale_img, dst_img);
- if (ratio >= scaleRatio_H && ratio >= scaleRatio_V &&
- m->checkDownscaleCap(resolution, displayRatio_V)) {
- otfMpp = m;
- otfMppRatio = ratio;
- return true;
- }
- return false;
- });
+ if (ratio >= scaleRatio_H && ratio >= scaleRatio_V &&
+ m->checkDownscaleCap(resolution, displayRatio_V)) {
+ otfMpp = m;
+ otfMppRatio = ratio;
+ break;
+ }
+ }
}
if (!otfMpp && !m2mMpp) {
@@ -1305,7 +1274,7 @@
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);
@@ -1486,26 +1455,32 @@
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(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)) {
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t check %s: flag (%d) supportedBit(%d), isAssignable(%d)",
+ mOtfMPPs[j]->mName.c_str(), layer->mSupportedMPPFlag,
+ (layer->mSupportedMPPFlag & mOtfMPPs[j]->mLogicalType),
+ isAssignableFlag);
+
+ 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;
@@ -1516,7 +1491,6 @@
/* 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;
@@ -1530,16 +1504,19 @@
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.c_str(),
+ (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)) {
@@ -1553,9 +1530,10 @@
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)) {
@@ -1573,24 +1551,43 @@
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.c_str(), -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);
- HDEBUGLOGD(eDebugResourceManager, "\t\t\t check %s: supportedBit(0x%" PRIx64 "), isAssignable(%d)",
- mOtfMPPs[k]->mName.string(), -isSupported, isAssignable);
- if ((isSupported == NO_ERROR) && isAssignable) {
+ isAssignableFlag = isAssignable(mOtfMPPs[k], display, otf_src_img,
+ otf_dst_img, &dpuSrcInfo);
+ }
+
+ HDEBUGLOGD(eDebugResourceAssigning,
+ "\t\t\t check %s: supportedBit(0x%" PRIx64
+ "), isAssignable(%d)",
+ mOtfMPPs[k]->mName.c_str(), -isSupported, isAssignableFlag);
+ if ((isSupported == NO_ERROR) && isAssignableFlag) {
*m2mMPP = mM2mMPPs[j];
*otfMPP = mOtfMPPs[k];
m2m_out_img = otf_src_img;
@@ -1600,12 +1597,16 @@
}
} 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.c_str(), layer->mSupportedMPPFlag,
+ isAssignableFlag);
}
}
}
@@ -1621,8 +1622,8 @@
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;
@@ -1660,44 +1661,47 @@
if ((ret = otfMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, otfMPP->mName.string(), ret);
+ __func__, otfMPP->mName.c_str(), 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.c_str());
}
if (m2mMPP != NULL) {
if ((ret = m2mMPP->assignMPP(display, layer)) != NO_ERROR)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), ret);
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.c_str());
}
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)
{
ALOGE("%s:: %s MPP assignMPP() error (%d)",
- __func__, m2mMPP->mName.string(), ret);
+ __func__, m2mMPP->mName.c_str(), 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.c_str());
}
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 {
/*
@@ -1768,7 +1772,8 @@
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;
@@ -1786,7 +1791,7 @@
(compositionInfo->mLastIndex < 0)) {
HWC_LOGE(display, "%s:: Invalid %s CompositionInfo mHasCompositionLayer(%d), "
"mFirstIndex(%d), mLastIndex(%d) ",
- __func__, compositionInfo->getTypeStr().string(),
+ __func__, compositionInfo->getTypeStr().c_str(),
compositionInfo->mHasCompositionLayer,
compositionInfo->mFirstIndex,
compositionInfo->mLastIndex);
@@ -1796,7 +1801,7 @@
continue;
compositionInfo->mWindowIndex = windowIndex;
HDEBUGLOGD(eDebugResourceManager, "\t\t[%d] %s Composition windowIndex: %d",
- i, compositionInfo->getTypeStr().string(), windowIndex);
+ i, compositionInfo->getTypeStr().c_str(), windowIndex);
} else if (layer->mValidateCompositionType == HWC2_COMPOSITION_DISPLAY_DECORATION) {
layer->mWindowIndex = -1;
continue;
@@ -1818,10 +1823,10 @@
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;
@@ -1834,10 +1839,10 @@
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;
@@ -1847,16 +1852,18 @@
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.c_str());
} 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.c_str());
}
}
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.c_str(), -ret);
uint64_t checkFlag = 0x0;
if (layer->mCheckMPPFlag.find(mOtfMPPs[j]->mLogicalType) !=
layer->mCheckMPPFlag.end()) {
@@ -1871,16 +1878,18 @@
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.c_str());
} 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.c_str());
}
}
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.c_str(), -ret);
uint64_t checkFlag = 0x0;
if (layer->mCheckMPPFlag.find(mM2mMPPs[j]->mLogicalType) !=
layer->mCheckMPPFlag.end()) {
@@ -1890,9 +1899,10 @@
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;
}
@@ -1906,7 +1916,7 @@
if (hwcCheckDebugMessages(eDebugResourceManager)) {
String8 dumpMPP;
mOtfMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
}
}
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
@@ -1914,7 +1924,7 @@
if (hwcCheckDebugMessages(eDebugResourceManager)) {
String8 dumpMPP;
mM2mMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
}
}
@@ -1934,7 +1944,9 @@
}
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.c_str(), displayMode,
+ mOtfMPPs[i]->mPreAssignDisplayList[displayMode]);
ExynosDisplay *display = NULL;
for (size_t j = 0; j < mDevice->mDisplays.size(); j++) {
@@ -1942,15 +1954,19 @@
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.has_value() &&
(display->mPowerModeState.value() != HWC2_POWER_MODE_OFF))))) {
- HDEBUGLOGD(eDebugResourceManager, "\t\treserve to display %d", display->mDisplayId);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t\treserve to display %d",
+ display->mDisplayId);
mOtfMPPs[i]->reserveMPP(display->mDisplayId);
break;
}
@@ -1970,21 +1986,26 @@
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.c_str(),
+ 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();
}
}
@@ -1995,14 +2016,14 @@
if (hwcCheckDebugMessages(eDebugResourceManager)) {
String8 dumpMPP;
mOtfMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
}
}
for (uint32_t i = 0; i < mM2mMPPs.size(); i++) {
if (hwcCheckDebugMessages(eDebugResourceManager)) {
String8 dumpMPP;
mM2mMPPs[i]->dump(dumpMPP);
- HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.string());
+ HDEBUGLOGD(eDebugResourceManager, "%s", dumpMPP.c_str());
}
}
HDEBUGLOGD(eDebugResourceManager, "%s-----------", __func__);
@@ -2121,7 +2142,7 @@
{
int fps = ceil(msecsPerSec / mpp.mCapacity);
HDEBUGLOGD(eDebugResourceAssigning, "%s setFrameRate %d",
- mpp.mName.string(), fps);
+ mpp.mName.c_str(), fps);
frame->setFrameRate(fps);
}
@@ -2243,9 +2264,8 @@
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.c_str(),
+ mpp.mLogicalIndex, mpp.mPhysicalType, mpp.mPhysicalIndex);
if (mpp.mMPPType == MPP_TYPE_OTF) {
for (uint32_t i = 0; i < mOtfMPPs.size(); i++) {
@@ -2263,8 +2283,8 @@
}
}
- HDEBUGLOGD(eDebugResourceManager, "\t[%s][%d] mpp usedCapa: %f",
- mpp.mName.string(), mpp.mLogicalIndex, usedCapa);
+ HDEBUGLOGD(eDebugResourceAssigning, "\t[%s][%d] mpp usedCapa: %f", mpp.mName.c_str(),
+ mpp.mLogicalIndex, usedCapa);
return usedCapa;
}
@@ -2335,7 +2355,9 @@
return ret;
}
- return ret;
+ setDisplaysTDMInfo();
+
+ return ret;
}
int32_t ExynosResourceManager::finishAssignResourceWork()
@@ -2387,7 +2409,7 @@
mSizeRestrictions[format][mSizeRestrictionCnt[format]++].sizeRestriction = size;
HDEBUGLOGD(eDebugDefault, "MPP : %s, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
- getMPPStr(mppId).string(),
+ getMPPStr(mppId).c_str(),
size.maxDownScale,
size.maxUpScale,
size.maxFullWidth,
@@ -2411,9 +2433,9 @@
mFormatRestrictions[mFormatRestrictionCnt] = table;
HDEBUGLOGD(eDebugDefault, "MPP : %s, %d, %s, %d",
- getMPPStr(mFormatRestrictions[mFormatRestrictionCnt].hwType).string(),
+ getMPPStr(mFormatRestrictions[mFormatRestrictionCnt].hwType).c_str(),
mFormatRestrictions[mFormatRestrictionCnt].nodeType,
- getFormatStr(mFormatRestrictions[mFormatRestrictionCnt].format, COMP_ANY).string(),
+ getFormatStr(mFormatRestrictions[mFormatRestrictionCnt].format, COMP_ANY).c_str(),
mFormatRestrictions[mFormatRestrictionCnt].reserved);
mFormatRestrictionCnt++;
}
@@ -2495,8 +2517,8 @@
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;
@@ -2507,8 +2529,8 @@
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;
}
}
@@ -2636,3 +2658,84 @@
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 badb6c7..e996554 100644
--- a/libhwc2.1/libresource/ExynosResourceManager.h
+++ b/libhwc2.1/libresource/ExynosResourceManager.h
@@ -38,18 +38,17 @@
#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 [] =
@@ -139,6 +138,12 @@
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 @@
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,
@@ -201,6 +208,41 @@
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 @@
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 @@
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 86c1b03..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>7</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
index 515bc21..ff313be 100644
--- a/libhwc2.1/pixel-display-secondary.xml
+++ b/libhwc2.1/pixel-display-secondary.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>com.google.hardware.pixel.display</name>
- <version>7</version>
+ <version>8</version>
<fqname>IDisplay/secondary</fqname>
</hal>
</manifest>
diff --git a/libhwc2.1/pixel-display.cpp b/libhwc2.1/pixel-display.cpp
index 32bc806..366945a 100644
--- a/libhwc2.1/pixel-display.cpp
+++ b/libhwc2.1/pixel-display.cpp
@@ -137,6 +137,30 @@
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);
+}
+
ndk::ScopedAStatus Display::setCompensationImageHandle(const NativeHandle &native_handle,
const std::string &imageName,
int *_aidl_return) {
@@ -175,19 +199,38 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
-bool Display::runMediator(const RoiRect roi, const Weight weight, const HistogramPos pos,
+bool Display::runMediator(const RoiRect &roi, const Weight &weight, const HistogramPos &pos,
std::vector<char16_t> *histogrambuffer) {
- if (mMediator.setRoiWeightThreshold(roi, weight, pos) != HistogramErrorCode::NONE) {
- ALOGE("histogram error, SET_ROI_WEIGHT_THRESHOLD ERROR\n");
- return false;
+ 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");
}
- if (mMediator.getFrameCount() != mMediator.getSampleFrameCounter()) {
- mDisplay->mDevice->onRefresh(mDisplay->mDisplayId); // DRM not busy & sampled frame changed
+
+ /*
+ * 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;
diff --git a/libhwc2.1/pixel-display.h b/libhwc2.1/pixel-display.h
index b1696d5..df437af 100644
--- a/libhwc2.1/pixel-display.h
+++ b/libhwc2.1/pixel-display.h
@@ -61,9 +61,12 @@
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:
- bool runMediator(const RoiRect roi, const Weight weight, const HistogramPos pos,
+ bool runMediator(const RoiRect &roi, const Weight &weight, const HistogramPos &pos,
std::vector<char16_t> *histogrambuffer);
ExynosDisplay *mDisplay = nullptr;
histogram::HistogramMediator mMediator;
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 @@
"AppMarkerWriter.cpp",
"ExynosJpegEncoder.cpp",
"ExynosJpegEncoderForCamera.cpp",
+ "FileLock.cpp",
"hwjpeg-base.cpp",
"hwjpeg-v4l2.cpp",
"libhwjpeg-exynos.cpp",
@@ -24,6 +25,9 @@
"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"
-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
+#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
#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 @@
}
}
-
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 @@
PrepareAppWriter(base, exif, &extraInfo);
}
-void CAppMarkerWriter::Init()
-{
+void CAppMarkerWriter::Init() {
m_pApp1End = NULL;
m_szApp1 = 0;
@@ -85,8 +81,8 @@
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 @@
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 @@
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 @@
* - 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 @@
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 @@
* - 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 @@
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 @@
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 @@
}
#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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
} 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 @@
}
*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 @@
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 @@
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 @@
* 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 @@
}
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
return AllocThumbJpegBuffer();
}
-bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer()
-{
+bool ExynosJpegEncoderForCamera::AllocThumbJpegBuffer() {
if (m_fdIONClient < 0) {
ALOGE("ION client is not created");
return false;
@@ -702,8 +677,7 @@
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 @@
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 @@
}
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 @@
[[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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
"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 @@
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 @@
#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 @@
} 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 @@
}
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 @@
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 @@
*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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 <fcntl.h>
-
-#include <linux/videodev2.h>
-#include <linux/v4l2-controls.h>
-
#include <exynos-hwjpeg.h>
+#include <fcntl.h>
+#include <linux/v4l2-controls.h>
+#include <linux/videodev2.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.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 @@
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 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 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 @@
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 <log/log.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+
#include <cerrno>
#include <cstring>
-#include <unistd.h>
-#include <log/log.h>
-#include <time.h>
-#include <sys/ioctl.h>
-
#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 @@
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 <linux/v4l2-controls.h>
-
#include <exynos-hwjpeg.h>
-#include "hwjpeg-internal.h"
+#include <linux/v4l2-controls.h>
+#include <linux/videodev2.h>
-CHWJpegV4L2Compressor::CHWJpegV4L2Compressor(): CHWJpegCompressor("/dev/video12")
-{
+#include "hwjpeg-internal.h"
+#include "log/log_main.h"
+
+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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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::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(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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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(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 @@
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 @@
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 @@
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 @@
return true;
}
-void CHWJpegV4L2Compressor::Release()
-{
+void CHWJpegV4L2Compressor::Release() {
StopStreaming();
}
@@ -730,8 +753,7 @@
/********* 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()
-{
+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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
*
*/
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 @@
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 @@
}
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 @@
* 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 @@
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 @@
*/
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 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
*/
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 @@
* @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 @@
* 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 @@
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 @@
};
*/
-#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 @@
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 @@
// 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 @@
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 @@
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 @@
};
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 @@
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 @@
* 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 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 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 @@
* @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 @@
* @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 @@
* @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 @@
*/
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 <fcntl.h>
-
-#include <linux/videodev2.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 <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 @@
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 @@
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 @@
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 @@
}
unsigned char marker = *addr++;
+ filelen -= 2;
if ((marker != 0xC4) && ((marker & 0xF0) == 0xC0)) { // SOFn
if (marker != 0xC0) {
@@ -124,18 +120,17 @@
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 @@
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 @@
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 @@
return true;
}
-class CLibhwjpegDecompressor: public hwjpeg_decompressor_struct {
+class CLibhwjpegDecompressor : public hwjpeg_decompressor_struct {
enum {
HWJPG_FLAG_NEED_MUNMAP = 1,
};
@@ -231,6 +230,7 @@
size_t m_nDummyBytes;
CJpegStreamParser m_jpegStreamParser;
+
public:
CLibhwjpegDecompressor() : m_flags(0) {
// members of hwjpeg_decompressor_struct
@@ -243,7 +243,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
return true;
}
-bool CLibhwjpegDecompressor::Decompress()
-{
+bool CLibhwjpegDecompressor::Decompress() {
if (!m_bPrepared) {
ALOGE("JPEG header is not parsed");
return false;
@@ -447,77 +444,64 @@
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();
}