Refactor HWC2on1Adapter
- Simply memory allocation with a single, consolidated calloc().
- Remove latch system which did not prove useful.
- Converted { to be before \n.
Change-Id: Id1daec2343225598160395bfecddc86955e2b610
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 1d2c178..d72139e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -34,33 +34,6 @@
using namespace std::chrono_literals;
-static bool operator==(const hwc_color_t& lhs, const hwc_color_t& rhs) {
- return lhs.r == rhs.r &&
- lhs.g == rhs.g &&
- lhs.b == rhs.b &&
- lhs.a == rhs.a;
-}
-
-static bool operator==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
- return lhs.left == rhs.left &&
- lhs.top == rhs.top &&
- lhs.right == rhs.right &&
- lhs.bottom == rhs.bottom;
-}
-
-static bool operator==(const hwc_frect_t& lhs, const hwc_frect_t& rhs) {
- return lhs.left == rhs.left &&
- lhs.top == rhs.top &&
- lhs.right == rhs.right &&
- lhs.bottom == rhs.bottom;
-}
-
-template <typename T>
-static inline bool operator!=(const T& lhs, const T& rhs)
-{
- return !(lhs == rhs);
-}
-
static uint8_t getMinorVersion(struct hwc_composer_device_1* device)
{
auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
@@ -80,19 +53,6 @@
namespace android {
-void HWC2On1Adapter::DisplayContentsDeleter::operator()(
- hwc_display_contents_1_t* contents)
-{
- if (contents != nullptr) {
- for (size_t l = 0; l < contents->numHwLayers; ++l) {
- auto& layer = contents->hwLayers[l];
- std::free(const_cast<hwc_rect_t*>(layer.visibleRegionScreen.rects));
- std::free(const_cast<hwc_rect_t*>(layer.surfaceDamage.rects));
- }
- }
- std::free(contents);
-}
-
class HWC2On1Adapter::Callbacks : public hwc_procs_t {
public:
explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) {
@@ -161,8 +121,7 @@
}
void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount,
- int32_t* outCapabilities)
-{
+ int32_t* outCapabilities) {
if (outCapabilities == nullptr) {
*outCount = mCapabilities.size();
return;
@@ -179,8 +138,7 @@
}
hwc2_function_pointer_t HWC2On1Adapter::doGetFunction(
- FunctionDescriptor descriptor)
-{
+ FunctionDescriptor descriptor) {
switch (descriptor) {
// Device functions
case FunctionDescriptor::CreateVirtualDisplay:
@@ -350,8 +308,7 @@
// Device functions
Error HWC2On1Adapter::createVirtualDisplay(uint32_t width,
- uint32_t height, hwc2_display_t* outDisplay)
-{
+ uint32_t height, hwc2_display_t* outDisplay) {
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
if (mHwc1VirtualDisplay) {
@@ -381,8 +338,7 @@
return Error::None;
}
-Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId)
-{
+Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) {
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) {
@@ -396,8 +352,7 @@
return Error::None;
}
-void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer)
-{
+void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) {
if (outBuffer != nullptr) {
auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
*outSize = static_cast<uint32_t>(copiedBytes);
@@ -450,8 +405,7 @@
*outSize = static_cast<uint32_t>(mDumpString.size());
}
-uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount()
-{
+uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() {
return mHwc1SupportsVirtualDisplays ? 1 : 0;
}
@@ -465,8 +419,7 @@
}
Error HWC2On1Adapter::registerCallback(Callback descriptor,
- hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer)
-{
+ hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) {
if (!isValid(descriptor)) {
return Error::BadParameter;
}
@@ -553,11 +506,8 @@
HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type)
: mId(sNextId++),
mDevice(device),
- mDirtyCount(0),
mStateMutex(),
- mZIsDirty(false),
mHwc1RequestedContents(nullptr),
- mHwc1ReceivedContents(nullptr),
mRetireFence(),
mChanges(),
mHwc1Id(-1),
@@ -572,10 +522,13 @@
mOutputBuffer(),
mHasColorTransform(false),
mLayers(),
- mHwc1LayerMap() {}
+ mHwc1LayerMap(),
+ mNumAvailableRects(0),
+ mNextAvailableRect(nullptr),
+ mGeometryChanged(false)
+ {}
-Error HWC2On1Adapter::Display::acceptChanges()
-{
+Error HWC2On1Adapter::Display::acceptChanges() {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!mChanges) {
@@ -594,25 +547,21 @@
mChanges->clearTypeChanges();
- mHwc1RequestedContents = std::move(mHwc1ReceivedContents);
-
return Error::None;
}
-Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId)
-{
+Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
*outLayerId = layer->getId();
ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
- mZIsDirty = true;
+ markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId)
-{
+Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
const auto mapLayer = mDevice.mLayers.find(layerId);
@@ -631,12 +580,11 @@
}
}
ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId);
- mZIsDirty = true;
+ markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig)
-{
+Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!mActiveConfig) {
@@ -651,8 +599,7 @@
}
Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId,
- Attribute attribute, int32_t* outValue)
-{
+ Attribute attribute, int32_t* outValue) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
@@ -667,8 +614,7 @@
}
Error HWC2On1Adapter::Display::getChangedCompositionTypes(
- uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes)
-{
+ uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!mChanges) {
@@ -701,8 +647,7 @@
}
Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes,
- int32_t* outModes)
-{
+ int32_t* outModes) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!outModes) {
@@ -717,8 +662,7 @@
}
Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs,
- hwc2_config_t* outConfigs)
-{
+ hwc2_config_t* outConfigs) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!outConfigs) {
@@ -737,8 +681,7 @@
return Error::None;
}
-Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport)
-{
+Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) {
@@ -751,15 +694,13 @@
Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
- float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/)
-{
+ float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) {
// This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
*outNumTypes = 0;
return Error::None;
}
-Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName)
-{
+Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!outName) {
@@ -772,8 +713,7 @@
}
Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements,
- hwc2_layer_t* outLayers, int32_t* outFences)
-{
+ hwc2_layer_t* outLayers, int32_t* outFences) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
uint32_t numWritten = 0;
@@ -799,8 +739,7 @@
Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests,
uint32_t* outNumElements, hwc2_layer_t* outLayers,
- int32_t* outLayerRequests)
-{
+ int32_t* outLayerRequests) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!mChanges) {
@@ -829,16 +768,14 @@
return Error::None;
}
-Error HWC2On1Adapter::Display::getType(int32_t* outType)
-{
+Error HWC2On1Adapter::Display::getType(int32_t* outType) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
*outType = static_cast<int32_t>(mType);
return Error::None;
}
-Error HWC2On1Adapter::Display::present(int32_t* outRetireFence)
-{
+Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (mChanges) {
@@ -857,8 +794,7 @@
return Error::None;
}
-Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId)
-{
+Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
auto config = getConfig(configId);
@@ -890,8 +826,7 @@
}
Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target,
- int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/)
-{
+ int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence);
@@ -901,8 +836,7 @@
return Error::None;
}
-Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode)
-{
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) {
std::unique_lock<std::recursive_mutex> lock (mStateMutex);
ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
@@ -933,8 +867,7 @@
return Error::None;
}
-Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint)
-{
+Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
@@ -944,8 +877,7 @@
}
Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer,
- int32_t releaseFence)
-{
+ int32_t releaseFence) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence);
@@ -954,30 +886,25 @@
return Error::None;
}
-static bool isValid(PowerMode mode)
-{
+static bool isValid(PowerMode mode) {
switch (mode) {
case PowerMode::Off: // Fall-through
case PowerMode::DozeSuspend: // Fall-through
case PowerMode::Doze: // Fall-through
case PowerMode::On: return true;
- default: return false;
}
}
-static int getHwc1PowerMode(PowerMode mode)
-{
+static int getHwc1PowerMode(PowerMode mode) {
switch (mode) {
case PowerMode::Off: return HWC_POWER_MODE_OFF;
case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND;
case PowerMode::Doze: return HWC_POWER_MODE_DOZE;
case PowerMode::On: return HWC_POWER_MODE_NORMAL;
- default: return HWC_POWER_MODE_OFF;
}
}
-Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode)
-{
+Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) {
if (!isValid(mode)) {
return Error::BadParameter;
}
@@ -1007,12 +934,11 @@
switch (enable) {
case Vsync::Enable: // Fall-through
case Vsync::Disable: return true;
- default: return false;
+ case Vsync::Invalid: return false;
}
}
-Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable)
-{
+Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) {
if (!isValid(enable)) {
return Error::BadParameter;
}
@@ -1032,8 +958,7 @@
}
Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes,
- uint32_t* outNumRequests)
-{
+ uint32_t* outNumRequests) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
ALOGV("[%" PRIu64 "] Entering validate", mId);
@@ -1042,6 +967,8 @@
if (!mDevice.prepareAllDisplays()) {
return Error::BadDisplay;
}
+ } else {
+ ALOGE("Validate was called more than once!");
}
*outNumTypes = mChanges->getNumTypes();
@@ -1055,10 +982,7 @@
return *outNumTypes > 0 ? Error::HasChanges : Error::None;
}
-// Display helpers
-
-Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z)
-{
+Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
const auto mapLayer = mDevice.mLayers.find(layerId);
@@ -1090,7 +1014,7 @@
layer->setZ(z);
mLayers.emplace(std::move(layer));
- mZIsDirty = true;
+ markGeometryChanged();
return Error::None;
}
@@ -1159,8 +1083,7 @@
static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
"Tables out of sync");
-void HWC2On1Adapter::Display::populateConfigs()
-{
+void HWC2On1Adapter::Display::populateConfigs() {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
ALOGV("[%" PRIu64 "] populateConfigs", mId);
@@ -1238,8 +1161,7 @@
populateColorModes();
}
-void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height)
-{
+void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
mConfigs.emplace_back(std::make_shared<Config>(*this));
@@ -1252,8 +1174,7 @@
mActiveConfig = config;
}
-bool HWC2On1Adapter::Display::prepare()
-{
+bool HWC2On1Adapter::Display::prepare() {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
// Only prepare display contents for displays HWC1 knows about
@@ -1270,86 +1191,45 @@
ALOGV("[%" PRIu64 "] Entering prepare", mId);
- auto currentCount = mHwc1RequestedContents ?
- mHwc1RequestedContents->numHwLayers : 0;
- auto requiredCount = mLayers.size() + 1;
- ALOGV("[%" PRIu64 "] Requires %zd layers, %zd allocated in %p", mId,
- requiredCount, currentCount, mHwc1RequestedContents.get());
-
- bool layerCountChanged = (currentCount != requiredCount);
- if (layerCountChanged) {
- reallocateHwc1Contents();
- }
-
- bool applyAllState = false;
- if (layerCountChanged || mZIsDirty) {
- assignHwc1LayerIds();
- mZIsDirty = false;
- applyAllState = true;
- }
+ allocateRequestedContents();
+ assignHwc1LayerIds();
mHwc1RequestedContents->retireFenceFd = -1;
mHwc1RequestedContents->flags = 0;
- if (isDirty() || applyAllState) {
+ if (mGeometryChanged) {
mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED;
}
+ mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
+ mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
+ // +1 is for framebuffer target layer.
+ mHwc1RequestedContents->numHwLayers = mLayers.size() + 1;
for (auto& layer : mLayers) {
auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()];
hwc1Layer.releaseFenceFd = -1;
hwc1Layer.acquireFenceFd = -1;
ALOGV("Applying states for layer %" PRIu64 " ", layer->getId());
- layer->applyState(hwc1Layer, applyAllState);
+ layer->applyState(hwc1Layer);
}
- mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
- mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
-
prepareFramebufferTarget();
+ resetGeometryMarker();
+
return true;
}
-static void cloneHWCRegion(hwc_region_t& region)
-{
- auto size = sizeof(hwc_rect_t) * region.numRects;
- auto newRects = static_cast<hwc_rect_t*>(std::malloc(size));
- std::copy_n(region.rects, region.numRects, newRects);
- region.rects = newRects;
-}
-
-HWC2On1Adapter::Display::HWC1Contents
- HWC2On1Adapter::Display::cloneRequestedContents() const
-{
+void HWC2On1Adapter::Display::generateChanges() {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
- size_t size = sizeof(hwc_display_contents_1_t) +
- sizeof(hwc_layer_1_t) * (mHwc1RequestedContents->numHwLayers);
- auto contents = static_cast<hwc_display_contents_1_t*>(std::malloc(size));
- std::memcpy(contents, mHwc1RequestedContents.get(), size);
- for (size_t layerId = 0; layerId < contents->numHwLayers; ++layerId) {
- auto& layer = contents->hwLayers[layerId];
- // Deep copy the regions to avoid double-frees
- cloneHWCRegion(layer.visibleRegionScreen);
- cloneHWCRegion(layer.surfaceDamage);
- }
- return HWC1Contents(contents);
-}
-
-void HWC2On1Adapter::Display::setReceivedContents(HWC1Contents contents)
-{
- std::unique_lock<std::recursive_mutex> lock(mStateMutex);
-
- mHwc1ReceivedContents = std::move(contents);
-
mChanges.reset(new Changes);
- size_t numLayers = mHwc1ReceivedContents->numHwLayers;
+ size_t numLayers = mHwc1RequestedContents->numHwLayers;
for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
- const auto& receivedLayer = mHwc1ReceivedContents->hwLayers[hwc1Id];
+ const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id];
if (mHwc1LayerMap.count(hwc1Id) == 0) {
ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET,
- "setReceivedContents: HWC1 layer %zd doesn't have a"
+ "generateChanges: HWC1 layer %zd doesn't have a"
" matching HWC2 layer, and isn't the framebuffer target",
hwc1Id);
continue;
@@ -1361,14 +1241,12 @@
}
}
-bool HWC2On1Adapter::Display::hasChanges() const
-{
+bool HWC2On1Adapter::Display::hasChanges() const {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
return mChanges != nullptr;
}
-Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents)
-{
+Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
if (!mChanges || (mChanges->getNumTypes() > 0)) {
@@ -1404,15 +1282,13 @@
return Error::None;
}
-void HWC2On1Adapter::Display::addRetireFence(int fenceFd)
-{
+void HWC2On1Adapter::Display::addRetireFence(int fenceFd) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
mRetireFence.add(fenceFd);
}
void HWC2On1Adapter::Display::addReleaseFences(
- const hwc_display_contents_1_t& hwcContents)
-{
+ const hwc_display_contents_1_t& hwcContents) {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
size_t numLayers = hwcContents.numHwLayers;
@@ -1439,14 +1315,12 @@
}
}
-bool HWC2On1Adapter::Display::hasColorTransform() const
-{
+bool HWC2On1Adapter::Display::hasColorTransform() const {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
return mHasColorTransform;
}
-static std::string hwc1CompositionString(int32_t type)
-{
+static std::string hwc1CompositionString(int32_t type) {
switch (type) {
case HWC_FRAMEBUFFER: return "Framebuffer";
case HWC_OVERLAY: return "Overlay";
@@ -1459,8 +1333,7 @@
}
}
-static std::string hwc1TransformString(int32_t transform)
-{
+static std::string hwc1TransformString(int32_t transform) {
switch (transform) {
case 0: return "None";
case HWC_TRANSFORM_FLIP_H: return "FlipH";
@@ -1475,8 +1348,7 @@
}
}
-static std::string hwc1BlendModeString(int32_t mode)
-{
+static std::string hwc1BlendModeString(int32_t mode) {
switch (mode) {
case HWC_BLENDING_NONE: return "None";
case HWC_BLENDING_PREMULT: return "Premultiplied";
@@ -1486,16 +1358,14 @@
}
}
-static std::string rectString(hwc_rect_t rect)
-{
+static std::string rectString(hwc_rect_t rect) {
std::stringstream output;
output << "[" << rect.left << ", " << rect.top << ", ";
output << rect.right << ", " << rect.bottom << "]";
return output.str();
}
-static std::string approximateFloatString(float f)
-{
+static std::string approximateFloatString(float f) {
if (static_cast<int32_t>(f) == f) {
return std::to_string(static_cast<int32_t>(f));
}
@@ -1508,8 +1378,7 @@
return std::string(buffer, bytesWritten);
}
-static std::string frectString(hwc_frect_t frect)
-{
+static std::string frectString(hwc_frect_t frect) {
std::stringstream output;
output << "[" << approximateFloatString(frect.left) << ", ";
output << approximateFloatString(frect.top) << ", ";
@@ -1518,8 +1387,7 @@
return output.str();
}
-static std::string colorString(hwc_color_t color)
-{
+static std::string colorString(hwc_color_t color) {
std::stringstream output;
output << "RGBA [";
output << static_cast<int32_t>(color.r) << ", ";
@@ -1529,8 +1397,7 @@
return output.str();
}
-static std::string alphaString(float f)
-{
+static std::string alphaString(float f) {
const size_t BUFFER_SIZE = 8;
char buffer[BUFFER_SIZE] = {};
auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f);
@@ -1538,8 +1405,7 @@
}
static std::string to_string(const hwc_layer_1_t& hwcLayer,
- int32_t hwc1MinorVersion)
-{
+ int32_t hwc1MinorVersion) {
const char* fill = " ";
std::stringstream output;
@@ -1599,8 +1465,7 @@
}
static std::string to_string(const hwc_display_contents_1_t& hwcContents,
- int32_t hwc1MinorVersion)
-{
+ int32_t hwc1MinorVersion) {
const char* fill = " ";
std::stringstream output;
@@ -1622,8 +1487,7 @@
return output.str();
}
-std::string HWC2On1Adapter::Display::dump() const
-{
+std::string HWC2On1Adapter::Display::dump() const {
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
std::stringstream output;
@@ -1663,10 +1527,7 @@
output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n';
}
- if (mHwc1ReceivedContents) {
- output << " Last received HWC1 state\n";
- output << to_string(*mHwc1ReceivedContents, mDevice.mHwc1MinorVersion);
- } else if (mHwc1RequestedContents) {
+ if (mHwc1RequestedContents) {
output << " Last requested HWC1 state\n";
output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion);
}
@@ -1674,28 +1535,46 @@
return output.str();
}
+hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) {
+ if (numRects == 0) {
+ return nullptr;
+ }
+
+ if (numRects > mNumAvailableRects) {
+ // This should NEVER happen since we calculated how many rects the
+ // display would need.
+ ALOGE("Rect allocation failure! SF is likely to crash soon!");
+ return nullptr;
+
+ }
+ hwc_rect_t* rects = mNextAvailableRect;
+ mNextAvailableRect += numRects;
+ mNumAvailableRects -= numRects;
+ return rects;
+}
+
+hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() {
+ return mHwc1RequestedContents.get();
+}
+
void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute,
- int32_t value)
-{
+ int32_t value) {
mAttributes[attribute] = value;
}
-int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const
-{
+int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const {
if (mAttributes.count(attribute) == 0) {
return -1;
}
return mAttributes.at(attribute);
}
-void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id)
-{
+void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) {
android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
mHwc1Ids.emplace(colorMode, id);
}
-bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const
-{
+bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const {
for (const auto& idPair : mHwc1Ids) {
if (id == idPair.second) {
return true;
@@ -1705,8 +1584,7 @@
}
Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
- uint32_t id, android_color_mode_t* outMode) const
-{
+ uint32_t id, android_color_mode_t* outMode) const {
for (const auto& idPair : mHwc1Ids) {
if (id == idPair.second) {
*outMode = idPair.first;
@@ -1718,8 +1596,7 @@
}
Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
- uint32_t* outId) const
-{
+ uint32_t* outId) const {
for (const auto& idPair : mHwc1Ids) {
if (mode == idPair.first) {
*outId = idPair.second;
@@ -1730,8 +1607,7 @@
return Error::BadParameter;
}
-bool HWC2On1Adapter::Display::Config::merge(const Config& other)
-{
+bool HWC2On1Adapter::Display::Config::merge(const Config& other) {
auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
HWC2::Attribute::DpiY};
@@ -1753,8 +1629,7 @@
return true;
}
-std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const
-{
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const {
std::set<android_color_mode_t> colorModes;
for (const auto& idPair : mHwc1Ids) {
colorModes.emplace(idPair.first);
@@ -1762,8 +1637,7 @@
return colorModes;
}
-std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const
-{
+std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const {
std::string output;
const size_t BUFFER_SIZE = 100;
@@ -1819,16 +1693,14 @@
}
std::shared_ptr<const HWC2On1Adapter::Display::Config>
- HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const
-{
+ HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const {
if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
return nullptr;
}
return mConfigs[configId];
}
-void HWC2On1Adapter::Display::populateColorModes()
-{
+void HWC2On1Adapter::Display::populateColorModes() {
mColorModes = mConfigs[0]->getColorModes();
for (const auto& config : mConfigs) {
std::set<android_color_mode_t> intersection;
@@ -1840,8 +1712,7 @@
}
}
-void HWC2On1Adapter::Display::initializeActiveConfig()
-{
+void HWC2On1Adapter::Display::initializeActiveConfig() {
if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
ALOGV("getActiveConfig is null, choosing config 0");
mActiveConfig = mConfigs[0];
@@ -1886,22 +1757,40 @@
}
-void HWC2On1Adapter::Display::reallocateHwc1Contents()
-{
- // Allocate an additional layer for the framebuffer target
+void HWC2On1Adapter::Display::allocateRequestedContents() {
+ // What needs to be allocated:
+ // 1 hwc_display_contents_1_t
+ // 1 hwc_layer_1_t for each layer
+ // 1 hwc_rect_t for each layer's surfaceDamage
+ // 1 hwc_rect_t for each layer's visibleRegion
+ // 1 hwc_layer_1_t for the framebuffer
+ // 1 hwc_rect_t for the framebuffer's visibleRegion
+
+ // Count # of surfaceDamage
+ size_t numSurfaceDamages = 0;
+ for (const auto& layer : mLayers) {
+ numSurfaceDamages += layer->getNumSurfaceDamages();
+ }
+
+ // Count # of visibleRegions (start at 1 for mandatory framebuffer target
+ // region)
+ size_t numVisibleRegion = 1;
+ for (const auto& layer : mLayers) {
+ numVisibleRegion += layer->getNumVisibleRegions();
+ }
+
+ size_t numRects = numVisibleRegion + numSurfaceDamages;
auto numLayers = mLayers.size() + 1;
size_t size = sizeof(hwc_display_contents_1_t) +
- sizeof(hwc_layer_1_t) * numLayers;
- ALOGV("[%" PRIu64 "] reallocateHwc1Contents creating %zd layer%s", mId,
- numLayers, numLayers != 1 ? "s" : "");
- auto contents =
- static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
- contents->numHwLayers = numLayers;
+ sizeof(hwc_layer_1_t) * numLayers +
+ sizeof(hwc_rect_t) * numRects;
+ auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
mHwc1RequestedContents.reset(contents);
+ mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]);
+ mNumAvailableRects = numRects;
}
-void HWC2On1Adapter::Display::assignHwc1LayerIds()
-{
+void HWC2On1Adapter::Display::assignHwc1LayerIds() {
mHwc1LayerMap.clear();
size_t nextHwc1Id = 0;
for (auto& layer : mLayers) {
@@ -1911,8 +1800,7 @@
}
void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer,
- const Layer& layer)
-{
+ const Layer& layer) {
auto layerId = layer.getId();
switch (hwc1Layer.compositionType) {
case HWC_FRAMEBUFFER:
@@ -1947,16 +1835,14 @@
}
void HWC2On1Adapter::Display::updateLayerRequests(
- const hwc_layer_1_t& hwc1Layer, const Layer& layer)
-{
+ const hwc_layer_1_t& hwc1Layer, const Layer& layer) {
if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) {
mChanges->addLayerRequest(layer.getId(),
LayerRequest::ClearClientTarget);
}
}
-void HWC2On1Adapter::Display::prepareFramebufferTarget()
-{
+void HWC2On1Adapter::Display::prepareFramebufferTarget() {
// We check that mActiveConfig is valid in Display::prepare
int32_t width = mActiveConfig->getAttribute(Attribute::Width);
int32_t height = mActiveConfig->getAttribute(Attribute::Height);
@@ -1976,8 +1862,9 @@
}
hwc1Target.displayFrame = {0, 0, width, height};
hwc1Target.planeAlpha = 255;
+
hwc1Target.visibleRegionScreen.numRects = 1;
- auto rects = static_cast<hwc_rect_t*>(std::malloc(sizeof(hwc_rect_t)));
+ hwc_rect_t* rects = GetRects(1);
rects[0].left = 0;
rects[0].top = 0;
rects[0].right = width;
@@ -1995,42 +1882,37 @@
HWC2On1Adapter::Layer::Layer(Display& display)
: mId(sNextId++),
mDisplay(display),
- mDirtyCount(0),
mBuffer(),
mSurfaceDamage(),
- mBlendMode(*this, BlendMode::None),
- mColor(*this, {0, 0, 0, 0}),
- mCompositionType(*this, Composition::Invalid),
- mDisplayFrame(*this, {0, 0, -1, -1}),
- mPlaneAlpha(*this, 0.0f),
- mSidebandStream(*this, nullptr),
- mSourceCrop(*this, {0.0f, 0.0f, -1.0f, -1.0f}),
- mTransform(*this, Transform::None),
- mVisibleRegion(*this, std::vector<hwc_rect_t>()),
+ mBlendMode(BlendMode::None),
+ mColor({0, 0, 0, 0}),
+ mCompositionType(Composition::Invalid),
+ mDisplayFrame({0, 0, -1, -1}),
+ mPlaneAlpha(0.0f),
+ mSidebandStream(nullptr),
+ mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}),
+ mTransform(Transform::None),
+ mVisibleRegion(),
mZ(0),
mReleaseFence(),
mHwc1Id(0),
- mHasUnsupportedPlaneAlpha(false),
- mHasUnsupportedBackgroundColor(false) {}
+ mHasUnsupportedPlaneAlpha(false) {}
bool HWC2On1Adapter::SortLayersByZ::operator()(
- const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs)
-{
+ const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) {
return lhs->getZ() < rhs->getZ();
}
Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer,
- int32_t acquireFence)
-{
+ int32_t acquireFence) {
ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId);
mBuffer.setBuffer(buffer);
mBuffer.setFence(acquireFence);
return Error::None;
}
-Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y)
-{
- if (mCompositionType.getValue() != Composition::Cursor) {
+Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) {
+ if (mCompositionType != Composition::Cursor) {
return Error::BadLayer;
}
@@ -2044,8 +1926,7 @@
return Error::None;
}
-Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage)
-{
+Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) {
// HWC1 supports surface damage starting only with version 1.5.
if (mDisplay.getDevice().mHwc1MinorVersion < 5) {
return Error::None;
@@ -2057,104 +1938,91 @@
// Layer state functions
-Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode)
-{
- mBlendMode.setPending(mode);
+Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) {
+ mBlendMode = mode;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setColor(hwc_color_t color)
-{
- mColor.setPending(color);
+Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) {
+ mColor = color;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setCompositionType(Composition type)
-{
- mCompositionType.setPending(type);
+Error HWC2On1Adapter::Layer::setCompositionType(Composition type) {
+ mCompositionType = type;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t)
-{
+Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) {
return Error::None;
}
-Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame)
-{
- mDisplayFrame.setPending(frame);
+Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) {
+ mDisplayFrame = frame;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha)
-{
- mPlaneAlpha.setPending(alpha);
+Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) {
+ mPlaneAlpha = alpha;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream)
-{
- mSidebandStream.setPending(stream);
+Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) {
+ mSidebandStream = stream;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop)
-{
- mSourceCrop.setPending(crop);
+Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) {
+ mSourceCrop = crop;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setTransform(Transform transform)
-{
- mTransform.setPending(transform);
+Error HWC2On1Adapter::Layer::setTransform(Transform transform) {
+ mTransform = transform;
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t rawVisible)
-{
- std::vector<hwc_rect_t> visible(rawVisible.rects,
- rawVisible.rects + rawVisible.numRects);
- mVisibleRegion.setPending(std::move(visible));
+Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) {
+ mVisibleRegion.resize(visible.numRects);
+ std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin());
+ mDisplay.markGeometryChanged();
return Error::None;
}
-Error HWC2On1Adapter::Layer::setZ(uint32_t z)
-{
+Error HWC2On1Adapter::Layer::setZ(uint32_t z) {
mZ = z;
return Error::None;
}
-void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd)
-{
+void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) {
ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId);
mReleaseFence.add(fenceFd);
}
-const sp<Fence>& HWC2On1Adapter::Layer::getReleaseFence() const
-{
+const sp<Fence>& HWC2On1Adapter::Layer::getReleaseFence() const {
return mReleaseFence.get();
}
-void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer,
- bool applyAllState)
-{
- applyCommonState(hwc1Layer, applyAllState);
- auto compositionType = mCompositionType.getPendingValue();
- if (compositionType == Composition::SolidColor) {
- applySolidColorState(hwc1Layer, applyAllState);
- } else if (compositionType == Composition::Sideband) {
- applySidebandState(hwc1Layer, applyAllState);
- } else {
- applyBufferState(hwc1Layer);
+void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) {
+ applyCommonState(hwc1Layer);
+ applyCompositionType(hwc1Layer);
+ switch (mCompositionType) {
+ case Composition::SolidColor : applySolidColorState(hwc1Layer); break;
+ case Composition::Sideband : applySidebandState(hwc1Layer); break;
+ default: applyBufferState(hwc1Layer); break;
}
- applyCompositionType(hwc1Layer, applyAllState);
}
-// Layer dump helpers
-
static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion,
- const std::vector<hwc_rect_t>& surfaceDamage)
-{
+ const std::vector<hwc_rect_t>& surfaceDamage) {
std::string regions;
regions += " Visible Region";
regions.resize(40, ' ');
@@ -2182,40 +2050,38 @@
return regions;
}
-std::string HWC2On1Adapter::Layer::dump() const
-{
+std::string HWC2On1Adapter::Layer::dump() const {
std::stringstream output;
const char* fill = " ";
- output << fill << to_string(mCompositionType.getPendingValue());
+ output << fill << to_string(mCompositionType);
output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " ";
output << "Z: " << mZ;
- if (mCompositionType.getValue() == HWC2::Composition::SolidColor) {
- output << " " << colorString(mColor.getValue());
- } else if (mCompositionType.getValue() == HWC2::Composition::Sideband) {
- output << " Handle: " << mSidebandStream.getValue() << '\n';
+ if (mCompositionType == HWC2::Composition::SolidColor) {
+ output << " " << colorString(mColor);
+ } else if (mCompositionType == HWC2::Composition::Sideband) {
+ output << " Handle: " << mSidebandStream << '\n';
} else {
output << " Buffer: " << mBuffer.getBuffer() << "/" <<
mBuffer.getFence() << '\n';
output << fill << " Display frame [LTRB]: " <<
- rectString(mDisplayFrame.getValue()) << '\n';
+ rectString(mDisplayFrame) << '\n';
output << fill << " Source crop: " <<
- frectString(mSourceCrop.getValue()) << '\n';
- output << fill << " Transform: " << to_string(mTransform.getValue());
- output << " Blend mode: " << to_string(mBlendMode.getValue());
- if (mPlaneAlpha.getValue() != 1.0f) {
+ frectString(mSourceCrop) << '\n';
+ output << fill << " Transform: " << to_string(mTransform);
+ output << " Blend mode: " << to_string(mBlendMode);
+ if (mPlaneAlpha != 1.0f) {
output << " Alpha: " <<
- alphaString(mPlaneAlpha.getValue()) << '\n';
+ alphaString(mPlaneAlpha) << '\n';
} else {
output << '\n';
}
- output << regionStrings(mVisibleRegion.getValue(), mSurfaceDamage);
+ output << regionStrings(mVisibleRegion, mSurfaceDamage);
}
return output.str();
}
-static int getHwc1Blending(HWC2::BlendMode blendMode)
-{
+static int getHwc1Blending(HWC2::BlendMode blendMode) {
switch (blendMode) {
case BlendMode::Coverage: return HWC_BLENDING_COVERAGE;
case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT;
@@ -2223,168 +2089,124 @@
}
}
-void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer,
- bool applyAllState)
-{
+void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) {
auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion();
- if (applyAllState || mBlendMode.isDirty()) {
- hwc1Layer.blending = getHwc1Blending(mBlendMode.getPendingValue());
- mBlendMode.latch();
- }
- if (applyAllState || mDisplayFrame.isDirty()) {
- hwc1Layer.displayFrame = mDisplayFrame.getPendingValue();
- mDisplayFrame.latch();
- }
- if (applyAllState || mPlaneAlpha.isDirty()) {
- auto pendingAlpha = mPlaneAlpha.getPendingValue();
- if (minorVersion < 2) {
- mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
- } else {
- hwc1Layer.planeAlpha =
- static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
- }
- mPlaneAlpha.latch();
- }
- if (applyAllState || mSourceCrop.isDirty()) {
- if (minorVersion < 3) {
- auto pending = mSourceCrop.getPendingValue();
- hwc1Layer.sourceCropi.left =
- static_cast<int32_t>(std::ceil(pending.left));
- hwc1Layer.sourceCropi.top =
- static_cast<int32_t>(std::ceil(pending.top));
- hwc1Layer.sourceCropi.right =
- static_cast<int32_t>(std::floor(pending.right));
- hwc1Layer.sourceCropi.bottom =
- static_cast<int32_t>(std::floor(pending.bottom));
- } else {
- hwc1Layer.sourceCropf = mSourceCrop.getPendingValue();
- }
- mSourceCrop.latch();
- }
- if (applyAllState || mTransform.isDirty()) {
- hwc1Layer.transform =
- static_cast<uint32_t>(mTransform.getPendingValue());
- mTransform.latch();
- }
- if (applyAllState || mVisibleRegion.isDirty()) {
- auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+ hwc1Layer.blending = getHwc1Blending(mBlendMode);
+ hwc1Layer.displayFrame = mDisplayFrame;
- std::free(const_cast<hwc_rect_t*>(hwc1VisibleRegion.rects));
+ auto pendingAlpha = mPlaneAlpha;
+ if (minorVersion < 2) {
+ mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
+ } else {
+ hwc1Layer.planeAlpha =
+ static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
+ }
- auto pending = mVisibleRegion.getPendingValue();
- hwc_rect_t* newRects = static_cast<hwc_rect_t*>(
- std::malloc(sizeof(hwc_rect_t) * pending.size()));
- std::copy(pending.begin(), pending.end(), newRects);
- hwc1VisibleRegion.rects = const_cast<const hwc_rect_t*>(newRects);
- hwc1VisibleRegion.numRects = pending.size();
- mVisibleRegion.latch();
+ if (minorVersion < 3) {
+ auto pending = mSourceCrop;
+ hwc1Layer.sourceCropi.left =
+ static_cast<int32_t>(std::ceil(pending.left));
+ hwc1Layer.sourceCropi.top =
+ static_cast<int32_t>(std::ceil(pending.top));
+ hwc1Layer.sourceCropi.right =
+ static_cast<int32_t>(std::floor(pending.right));
+ hwc1Layer.sourceCropi.bottom =
+ static_cast<int32_t>(std::floor(pending.bottom));
+ } else {
+ hwc1Layer.sourceCropf = mSourceCrop;
+ }
+
+ hwc1Layer.transform = static_cast<uint32_t>(mTransform);
+
+ auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+ hwc1VisibleRegion.numRects = mVisibleRegion.size();
+ hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects);
+ hwc1VisibleRegion.rects = rects;
+ for (size_t i = 0; i < mVisibleRegion.size(); i++) {
+ rects[i] = mVisibleRegion[i];
}
}
-void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer,
- bool applyAllState)
-{
- if (applyAllState || mColor.isDirty()) {
- // If the device does not support background color it is likely to make
- // assumption regarding backgroundColor and handle (both fields occupy
- // the same location in hwc_layer_1_t union).
- // To not confuse these devices we don't set background color and we
- // make sure handle is a null pointer.
- if (mDisplay.getDevice().supportsBackgroundColor()) {
- hwc1Layer.backgroundColor = mColor.getPendingValue();
- mHasUnsupportedBackgroundColor = false;
- } else {
- hwc1Layer.handle = nullptr;
- mHasUnsupportedBackgroundColor = true;
- }
- mColor.latch();
+void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) {
+ // If the device does not support background color it is likely to make
+ // assumption regarding backgroundColor and handle (both fields occupy
+ // the same location in hwc_layer_1_t union).
+ // To not confuse these devices we don't set background color and we
+ // make sure handle is a null pointer.
+ if (hasUnsupportedBackgroundColor()) {
+ hwc1Layer.handle = nullptr;
+ } else {
+ hwc1Layer.backgroundColor = mColor;
}
}
-void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer,
- bool applyAllState)
-{
- if (applyAllState || mSidebandStream.isDirty()) {
- hwc1Layer.sidebandStream = mSidebandStream.getPendingValue();
- mSidebandStream.latch();
- }
+void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) {
+ hwc1Layer.sidebandStream = mSidebandStream;
}
-void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer)
-{
+void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) {
hwc1Layer.handle = mBuffer.getBuffer();
hwc1Layer.acquireFenceFd = mBuffer.getFence();
}
-void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer,
- bool applyAllState)
-{
+void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) {
// HWC1 never supports color transforms or dataspaces and only sometimes
// supports plane alpha (depending on the version). These require us to drop
// some or all layers to client composition.
- ALOGV("applyCompositionType");
- ALOGV("mHasUnsupportedPlaneAlpha = %d", mHasUnsupportedPlaneAlpha);
- ALOGV("mDisplay.hasColorTransform() = %d", mDisplay.hasColorTransform());
- ALOGV("mHasUnsupportedBackgroundColor = %d", mHasUnsupportedBackgroundColor);
-
if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() ||
- mHasUnsupportedBackgroundColor) {
+ hasUnsupportedBackgroundColor()) {
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags = HWC_SKIP_LAYER;
return;
}
- if (applyAllState || mCompositionType.isDirty()) {
- hwc1Layer.flags = 0;
- switch (mCompositionType.getPendingValue()) {
- case Composition::Client:
+ hwc1Layer.flags = 0;
+ switch (mCompositionType) {
+ case Composition::Client:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ case Composition::Device:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ break;
+ case Composition::SolidColor:
+ // In theory the following line should work, but since the HWC1
+ // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
+ // devices may not work correctly. To be on the safe side, we
+ // fall back to client composition.
+ //
+ // hwc1Layer.compositionType = HWC_BACKGROUND;
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
+ case Composition::Cursor:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
+ hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
+ }
+ break;
+ case Composition::Sideband:
+ if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
+ hwc1Layer.compositionType = HWC_SIDEBAND;
+ } else {
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags |= HWC_SKIP_LAYER;
- break;
- case Composition::Device:
- hwc1Layer.compositionType = HWC_FRAMEBUFFER;
- break;
- case Composition::SolidColor:
- // In theory the following line should work, but since the HWC1
- // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1
- // devices may not work correctly. To be on the safe side, we
- // fall back to client composition.
- //
- // hwc1Layer.compositionType = HWC_BACKGROUND;
- hwc1Layer.compositionType = HWC_FRAMEBUFFER;
- hwc1Layer.flags |= HWC_SKIP_LAYER;
- break;
- case Composition::Cursor:
- hwc1Layer.compositionType = HWC_FRAMEBUFFER;
- if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
- hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
- }
- break;
- case Composition::Sideband:
- if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
- hwc1Layer.compositionType = HWC_SIDEBAND;
- } else {
- hwc1Layer.compositionType = HWC_FRAMEBUFFER;
- hwc1Layer.flags |= HWC_SKIP_LAYER;
- }
- break;
- default:
- hwc1Layer.compositionType = HWC_FRAMEBUFFER;
- hwc1Layer.flags |= HWC_SKIP_LAYER;
- break;
- }
- ALOGV("Layer %" PRIu64 " %s set to %d", mId,
- to_string(mCompositionType.getPendingValue()).c_str(),
- hwc1Layer.compositionType);
- ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping");
- mCompositionType.latch();
+ }
+ break;
+ default:
+ hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+ hwc1Layer.flags |= HWC_SKIP_LAYER;
+ break;
}
+ ALOGV("Layer %" PRIu64 " %s set to %d", mId,
+ to_string(mCompositionType).c_str(),
+ hwc1Layer.compositionType);
+ ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping");
}
// Adapter helpers
-void HWC2On1Adapter::populateCapabilities()
-{
+void HWC2On1Adapter::populateCapabilities() {
ALOGV("populateCapabilities");
if (mHwc1MinorVersion >= 3U) {
int supportedTypes = 0;
@@ -2412,8 +2234,7 @@
}
}
-HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id)
-{
+HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
auto display = mDisplays.find(id);
@@ -2425,8 +2246,7 @@
}
std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer(
- hwc2_display_t displayId, hwc2_layer_t layerId)
-{
+ hwc2_display_t displayId, hwc2_layer_t layerId) {
auto display = getDisplay(displayId);
if (!display) {
return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
@@ -2444,22 +2264,19 @@
return std::make_tuple(layer.get(), Error::None);
}
-void HWC2On1Adapter::populatePrimary()
-{
+void HWC2On1Adapter::populatePrimary() {
ALOGV("populatePrimary");
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
- auto display =
- std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+ auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId();
display->setHwc1Id(HWC_DISPLAY_PRIMARY);
display->populateConfigs();
mDisplays.emplace(display->getId(), std::move(display));
}
-bool HWC2On1Adapter::prepareAllDisplays()
-{
+bool HWC2On1Adapter::prepareAllDisplays() {
ATRACE_CALL();
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
@@ -2476,24 +2293,23 @@
return false;
}
+ // Build an array of hwc_display_contents_1 to call prepare() on HWC1.
+ mHwc1Contents.clear();
+
// Always push the primary display
- std::vector<HWC2On1Adapter::Display::HWC1Contents> requestedContents;
auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY];
auto& primaryDisplay = mDisplays[primaryDisplayId];
- auto primaryDisplayContents = primaryDisplay->cloneRequestedContents();
- requestedContents.push_back(std::move(primaryDisplayContents));
+ mHwc1Contents.push_back(primaryDisplay->getDisplayContents());
// Push the external display, if present
if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) {
auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL];
auto& externalDisplay = mDisplays[externalDisplayId];
- auto externalDisplayContents =
- externalDisplay->cloneRequestedContents();
- requestedContents.push_back(std::move(externalDisplayContents));
+ mHwc1Contents.push_back(externalDisplay->getDisplayContents());
} else {
// Even if an external display isn't present, we still need to send
// at least two displays down to HWC1
- requestedContents.push_back(nullptr);
+ mHwc1Contents.push_back(nullptr);
}
// Push the hardware virtual display, if supported and present
@@ -2501,17 +2317,13 @@
if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) {
auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL];
auto& virtualDisplay = mDisplays[virtualDisplayId];
- auto virtualDisplayContents =
- virtualDisplay->cloneRequestedContents();
- requestedContents.push_back(std::move(virtualDisplayContents));
+ mHwc1Contents.push_back(virtualDisplay->getDisplayContents());
} else {
- requestedContents.push_back(nullptr);
+ mHwc1Contents.push_back(nullptr);
}
}
- mHwc1Contents.clear();
- for (auto& displayContents : requestedContents) {
- mHwc1Contents.push_back(displayContents.get());
+ for (auto& displayContents : mHwc1Contents) {
if (!displayContents) {
continue;
}
@@ -2549,14 +2361,13 @@
auto displayId = mHwc1DisplayMap[hwc1Id];
auto& display = mDisplays[displayId];
- display->setReceivedContents(std::move(requestedContents[hwc1Id]));
+ display->generateChanges();
}
return true;
}
-Error HWC2On1Adapter::setAllDisplays()
-{
+Error HWC2On1Adapter::setAllDisplays() {
ATRACE_CALL();
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
@@ -2602,14 +2413,13 @@
return Error::None;
}
-void HWC2On1Adapter::hwc1Invalidate()
-{
+void HWC2On1Adapter::hwc1Invalidate() {
ALOGV("Received hwc1Invalidate");
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
// If the HWC2-side callback hasn't been registered yet, buffer this until
- // it is registered
+ // it is registered.
if (mCallbacks.count(Callback::Refresh) == 0) {
mHasPendingInvalidate = true;
return;
@@ -2621,7 +2431,7 @@
displays.emplace_back(displayPair.first);
}
- // Call back without the state lock held
+ // Call back without the state lock held.
lock.unlock();
auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer);
@@ -2630,14 +2440,13 @@
}
}
-void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp)
-{
+void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) {
ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp);
std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
// If the HWC2-side callback hasn't been registered yet, buffer this until
- // it is registered
+ // it is registered.
if (mCallbacks.count(Callback::Vsync) == 0) {
mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp);
return;
@@ -2651,15 +2460,14 @@
const auto& callbackInfo = mCallbacks[Callback::Vsync];
auto displayId = mHwc1DisplayMap[hwc1DisplayId];
- // Call back without the state lock held
+ // Call back without the state lock held.
lock.unlock();
auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
vsync(callbackInfo.data, displayId, timestamp);
}
-void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected)
-{
+void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) {
ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected);
if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) {
@@ -2714,5 +2522,4 @@
HWC2::Connection::Disconnected : HWC2::Connection::Connected;
hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected));
}
-
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index df33ec3..408bc41 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -134,11 +134,6 @@
const std::shared_ptr<Layer>& rhs);
};
- class DisplayContentsDeleter {
- public:
- void operator()(struct hwc_display_contents_1* contents);
- };
-
// The semantics of the fences returned by the device differ between
// hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h
// for more information.
@@ -193,9 +188,6 @@
class Display {
public:
- typedef std::unique_ptr<hwc_display_contents_1,
- DisplayContentsDeleter> HWC1Contents;
-
Display(HWC2On1Adapter& device, HWC2::DisplayType type);
hwc2_display_t getId() const { return mId; }
@@ -206,10 +198,6 @@
void setHwc1Id(int32_t id) { mHwc1Id = id; }
int32_t getHwc1Id() const { return mHwc1Id; }
- void incDirty() { ++mDirtyCount; }
- void decDirty() { --mDirtyCount; }
- bool isDirty() const { return mDirtyCount > 0 || mZIsDirty; }
-
// HWC2 Display functions
HWC2::Error acceptChanges();
HWC2::Error createLayer(hwc2_layer_t* outLayerId);
@@ -233,7 +221,14 @@
uint32_t* outNumElements, hwc2_layer_t* outLayers,
int32_t* outLayerRequests);
HWC2::Error getType(int32_t* outType);
+
+ // Since HWC1 "presents" (called "set" in HWC1) all Displays
+ // at once, the first call to any Display::present will trigger
+ // present() on all Displays in the Device. Subsequent calls without
+ // first calling validate() are noop (except for duping/returning
+ // the retire fence).
HWC2::Error present(int32_t* outRetireFence);
+
HWC2::Error setActiveConfig(hwc2_config_t configId);
HWC2::Error setClientTarget(buffer_handle_t target,
int32_t acquireFence, int32_t dataspace,
@@ -244,6 +239,10 @@
int32_t releaseFence);
HWC2::Error setPowerMode(HWC2::PowerMode mode);
HWC2::Error setVsyncEnabled(HWC2::Vsync enabled);
+
+ // Since HWC1 "validates" (called "prepare" in HWC1) all Displays
+ // at once, the first call to any Display::validate() will trigger
+ // validate() on all other Displays in the Device.
HWC2::Error validate(uint32_t* outNumTypes,
uint32_t* outNumRequests);
@@ -256,10 +255,9 @@
void populateConfigs(uint32_t width, uint32_t height);
bool prepare();
- HWC1Contents cloneRequestedContents() const;
// Called after hwc.prepare() with responses from the device.
- void setReceivedContents(HWC1Contents contents);
+ void generateChanges();
bool hasChanges() const;
HWC2::Error set(hwc_display_contents_1& hwcContents);
@@ -270,6 +268,13 @@
std::string dump() const;
+ // Return a rect from the pool allocated during validate()
+ hwc_rect_t* GetRects(size_t numRects);
+
+ hwc_display_contents_1* getDisplayContents();
+
+ void markGeometryChanged() { mGeometryChanged = true; }
+ void resetGeometryMarker() { mGeometryChanged = false;}
private:
class Config {
public:
@@ -314,7 +319,7 @@
std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
};
- // Store changes requested from the device upon calling prepare().
+ // Stores changes requested from the device upon calling prepare().
// Handles change request to:
// - Layer composition type.
// - Layer hints.
@@ -363,7 +368,9 @@
void populateColorModes();
void initializeActiveConfig();
- void reallocateHwc1Contents();
+ // Creates a bi-directional mapping between index in HWC1
+ // prepare/set array and Layer object. Stores mapping in
+ // mHwc1LayerMap and also updates Layer's attribute mHwc1Id.
void assignHwc1LayerIds();
// Called after a response to prepare() has been received:
@@ -376,13 +383,16 @@
void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
const Layer& layer);
+ // Set all fields in HWC1 comm array for layer containing the
+ // HWC_FRAMEBUFFER_TARGET (always the last layer).
void prepareFramebufferTarget();
+ // Display ID generator.
static std::atomic<hwc2_display_t> sNextId;
const hwc2_display_t mId;
- HWC2On1Adapter& mDevice;
- std::atomic<size_t> mDirtyCount;
+
+ HWC2On1Adapter& mDevice;
// The state of this display should only be modified from
// SurfaceFlinger's main loop, with the exception of when dump is
@@ -395,15 +405,18 @@
// which require locking.
mutable std::recursive_mutex mStateMutex;
- bool mZIsDirty;
+ // Allocate RAM able to store all layers and rects used for
+ // communication with HWC1. Place allocated RAM in variable
+ // mHwc1RequestedContents.
+ void allocateRequestedContents();
// Array of structs exchanged between client and hwc1 device.
- HWC1Contents mHwc1RequestedContents; // Sent to device upon calling prepare().
- HWC1Contents mHwc1ReceivedContents; // Returned by device after prepare().
-
+ // Sent to device upon calling prepare().
+ std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents;
+ private:
DeferredFence mRetireFence;
- // Will only be non-null after the layer has been validated but
+ // Will only be non-null after the Display has been validated and
// before it has been presented
std::unique_ptr<Changes> mChanges;
@@ -418,15 +431,34 @@
HWC2::PowerMode mPowerMode;
HWC2::Vsync mVsyncEnabled;
+ // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer
FencedBuffer mClientTarget;
+
+
FencedBuffer mOutputBuffer;
bool mHasColorTransform;
+ // All layers this Display is aware of.
std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+
+ // Mapping between layer index in array of hwc_display_contents_1*
+ // passed to HWC1 during validate/set and Layer object.
std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
+
+ // All communication with HWC1 via prepare/set is done with one
+ // alloc. This pointer is pointing to a pool of hwc_rect_t.
+ size_t mNumAvailableRects;
+ hwc_rect_t* mNextAvailableRect;
+
+ // True if any of the Layers contained in this Display have been
+ // updated with anything other than a buffer since last call to
+ // Display::set()
+ bool mGeometryChanged;
};
+ // Utility template calling a Display object method directly based on the
+ // hwc2_display_t displayId parameter.
template <typename ...Args>
static int32_t callDisplayFunction(hwc2_device_t* device,
hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...),
@@ -468,7 +500,8 @@
static int32_t setColorModeHook(hwc2_device_t* device,
hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
auto mode = static_cast<android_color_mode_t>(intMode);
- return callDisplayFunction(device, display, &Display::setColorMode, mode);
+ return callDisplayFunction(device, display, &Display::setColorMode,
+ mode);
}
static int32_t setPowerModeHook(hwc2_device_t* device,
@@ -485,46 +518,6 @@
enabled);
}
- // Layer functions
-
- template <typename T>
- class LatchedState {
- public:
- LatchedState(Layer& parent, T initialValue)
- : mParent(parent),
- mPendingValue(initialValue),
- mValue(initialValue) {}
-
- void setPending(T value) {
- if (value == mPendingValue) {
- return;
- }
- if (mPendingValue == mValue) {
- mParent.incDirty();
- } else if (value == mValue) {
- mParent.decDirty();
- }
- mPendingValue = value;
- }
-
- T getValue() const { return mValue; }
- T getPendingValue() const { return mPendingValue; }
-
- bool isDirty() const { return mPendingValue != mValue; }
-
- void latch() {
- if (isDirty()) {
- mValue = mPendingValue;
- mParent.decDirty();
- }
- }
-
- private:
- Layer& mParent;
- T mPendingValue;
- T mValue;
- };
-
class Layer {
public:
explicit Layer(Display& display);
@@ -535,10 +528,6 @@
hwc2_layer_t getId() const { return mId; }
Display& getDisplay() const { return mDisplay; }
- void incDirty() { if (mDirtyCount++ == 0) mDisplay.incDirty(); }
- void decDirty() { if (--mDirtyCount == 0) mDisplay.decDirty(); }
- bool isDirty() const { return mDirtyCount > 0; }
-
// HWC2 Layer functions
HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
HWC2::Error setCursorPosition(int32_t x, int32_t y);
@@ -558,7 +547,7 @@
HWC2::Error setZ(uint32_t z);
HWC2::Composition getCompositionType() const {
- return mCompositionType.getValue();
+ return mCompositionType;
}
uint32_t getZ() const { return mZ; }
@@ -568,47 +557,57 @@
void setHwc1Id(size_t id) { mHwc1Id = id; }
size_t getHwc1Id() const { return mHwc1Id; }
- void applyState(struct hwc_layer_1& hwc1Layer, bool applyAllState);
+ // Write state to HWC1 communication struct.
+ void applyState(struct hwc_layer_1& hwc1Layer);
std::string dump() const;
+ std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); }
+
+ std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); }
+
+ // True if a layer cannot be properly rendered by the device due
+ // to usage of SolidColor (a.k.a BackgroundColor in HWC1).
+ bool hasUnsupportedBackgroundColor() {
+ return (mCompositionType == HWC2::Composition::SolidColor &&
+ !mDisplay.getDevice().supportsBackgroundColor());
+ }
private:
- void applyCommonState(struct hwc_layer_1& hwc1Layer,
- bool applyAllState);
- void applySolidColorState(struct hwc_layer_1& hwc1Layer,
- bool applyAllState);
- void applySidebandState(struct hwc_layer_1& hwc1Layer,
- bool applyAllState);
+ void applyCommonState(struct hwc_layer_1& hwc1Layer);
+ void applySolidColorState(struct hwc_layer_1& hwc1Layer);
+ void applySidebandState(struct hwc_layer_1& hwc1Layer);
void applyBufferState(struct hwc_layer_1& hwc1Layer);
- void applyCompositionType(struct hwc_layer_1& hwc1Layer,
- bool applyAllState);
+ void applyCompositionType(struct hwc_layer_1& hwc1Layer);
static std::atomic<hwc2_layer_t> sNextId;
const hwc2_layer_t mId;
Display& mDisplay;
- size_t mDirtyCount;
FencedBuffer mBuffer;
std::vector<hwc_rect_t> mSurfaceDamage;
- LatchedState<HWC2::BlendMode> mBlendMode;
- LatchedState<hwc_color_t> mColor;
- LatchedState<HWC2::Composition> mCompositionType;
- LatchedState<hwc_rect_t> mDisplayFrame;
- LatchedState<float> mPlaneAlpha;
- LatchedState<const native_handle_t*> mSidebandStream;
- LatchedState<hwc_frect_t> mSourceCrop;
- LatchedState<HWC2::Transform> mTransform;
- LatchedState<std::vector<hwc_rect_t>> mVisibleRegion;
+ HWC2::BlendMode mBlendMode;
+ hwc_color_t mColor;
+ HWC2::Composition mCompositionType;
+ hwc_rect_t mDisplayFrame;
+ float mPlaneAlpha;
+ const native_handle_t* mSidebandStream;
+ hwc_frect_t mSourceCrop;
+ HWC2::Transform mTransform;
+ std::vector<hwc_rect_t> mVisibleRegion;
+
uint32_t mZ;
DeferredFence mReleaseFence;
size_t mHwc1Id;
bool mHasUnsupportedPlaneAlpha;
- bool mHasUnsupportedBackgroundColor;
};
+ // Utility tempate calling a Layer object method based on ID parameters:
+ // hwc2_display_t displayId
+ // and
+ // hwc2_layer_t layerId
template <typename ...Args>
static int32_t callLayerFunction(hwc2_device_t* device,
hwc2_display_t displayId, hwc2_layer_t layerId,
@@ -677,6 +676,7 @@
std::vector<struct hwc_display_contents_1*> mHwc1Contents;
HWC2::Error setAllDisplays();
+ // Callbacks
void hwc1Invalidate();
void hwc1Vsync(int hwc1DisplayId, int64_t timestamp);
void hwc1Hotplug(int hwc1DisplayId, int connected);
@@ -698,6 +698,8 @@
// callbacks or dump
std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+
+ // A HWC1 supports only one virtual display.
std::shared_ptr<Display> mHwc1VirtualDisplay;
// These are potentially accessed from multiple threads, and are protected
@@ -712,10 +714,19 @@
};
std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
bool mHasPendingInvalidate;
+
+ // There is a small gap between the time the HWC1 module is started and
+ // when the callbacks for vsync and hotplugs are registered by the
+ // HWC2on1Adapter. To prevent losing events they are stored in these arrays
+ // and fed to the callback as soon as possible.
std::vector<std::pair<int, int64_t>> mPendingVsyncs;
std::vector<std::pair<int, int>> mPendingHotplugs;
+ // Mapping between HWC1 display id and Display objects.
std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+
+ // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL,
+ // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects.
std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap;
};