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.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;
};