/* * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_HW_EMU_HWC2_H #define ANDROID_HW_EMU_HWC2_H #define HWC2_INCLUDE_STRINGIFICATION #define HWC2_USE_CPP11 #include #undef HWC2_INCLUDE_STRINGIFICATION #undef HWC2_USE_CPP11 #include #include #include #include #include #include #include #include #include "gralloc_cb.h" #include "MiniFence.h" #include "HostConnection.h" namespace android { class EmuHWC2 : public hwc2_device_t { public: EmuHWC2(); int populatePrimary(); private: static inline EmuHWC2* getHWC2(hwc2_device_t* device) { return static_cast(device); } static int closeHook(hw_device_t* device) { EmuHWC2 *ctx = reinterpret_cast(device); delete ctx; return 0; } // getCapabilities void doGetCapabilities(uint32_t* outCount, int32_t* outCapabilities); static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount, int32_t* outCapabilities) { getHWC2(device)->doGetCapabilities(outCount, outCapabilities); } // getFunction hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor); static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device, int32_t desc) { auto descriptor = static_cast(desc); return getHWC2(device)->doGetFunction(descriptor); } // Device functions HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height, int32_t* format, hwc2_display_t* outDisplay); static int32_t createVirtualDisplayHook(hwc2_device_t* device, uint32_t width, uint32_t height, int32_t* format, hwc2_display_t* outDisplay) { auto error = getHWC2(device)->createVirtualDisplay(width, height, format, outDisplay); return static_cast(error); } HWC2::Error destroyVirtualDisplay(hwc2_display_t display); static int32_t destroyVirtualDisplayHook(hwc2_device_t* device, hwc2_display_t display) { auto error = getHWC2(device)->destroyVirtualDisplay(display); return static_cast(error); } std::string mDumpString; void dump(uint32_t* outSize, char* outBuffer); static void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) { getHWC2(device)->dump(outSize, outBuffer); } uint32_t getMaxVirtualDisplayCount(); static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) { return getHWC2(device)->getMaxVirtualDisplayCount(); } HWC2::Error registerCallback(HWC2::Callback descriptor, hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer); static int32_t registerCallbackHook(hwc2_device_t* device, int32_t intDesc, hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { auto descriptor = static_cast(intDesc); auto error = getHWC2(device)->registerCallback(descriptor, callbackData, pointer); return static_cast(error); } class Layer; class SortLayersByZ { public: bool operator()(const std::shared_ptr& lhs, const std::shared_ptr& rhs) const; }; // SurfaceFlinger sets the ColorBuffer and its Fence handler for each // layer. This class is a container for these two. class FencedBuffer { public: FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {} void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; } void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); } buffer_handle_t getBuffer() const { return mBuffer; } int getFence() const { return mFence->dup(); } private: buffer_handle_t mBuffer; sp mFence; }; class GrallocModule { public: GrallocModule(); ~GrallocModule(); framebuffer_device_t* getFb() { return mFbDev; } uint32_t getTargetCb(); private: const hw_module_t* mHw = nullptr; const gralloc_module_t* mGralloc = nullptr; alloc_device_t* mAllocDev = nullptr; framebuffer_device_t* mFbDev = nullptr; buffer_handle_t mHandle = nullptr; }; typedef struct compose_layer { uint32_t cbHandle; hwc2_composition_t composeMode; hwc_rect_t displayFrame; hwc_frect_t crop; int32_t blendMode; float alpha; hwc_color_t color; hwc_transform_t transform; } ComposeLayer; typedef struct compose_device { uint32_t version; uint32_t targetHandle; uint32_t numLayers; struct compose_layer layer[0]; } ComposeDevice; class ComposeMsg { public: ComposeMsg(uint32_t layerCnt = 0) : mData(sizeof(ComposeDevice) + layerCnt * sizeof(ComposeLayer)) { mComposeDevice = reinterpret_cast(mData.data()); mLayerCnt = layerCnt; } ComposeDevice* get() { return mComposeDevice; } uint32_t getLayerCnt() { return mLayerCnt; } private: std::vector mData; uint32_t mLayerCnt; ComposeDevice* mComposeDevice; }; class Display { public: Display(EmuHWC2& device, HWC2::DisplayType type); hwc2_display_t getId() const {return mId;} // HWC2 Display functions HWC2::Error acceptChanges(); HWC2::Error createLayer(hwc2_layer_t* outLayerId); HWC2::Error destroyLayer(hwc2_layer_t layerId); HWC2::Error getActiveConfig(hwc2_config_t* outConfigId); HWC2::Error getDisplayAttribute(hwc2_config_t configId, int32_t attribute, int32_t* outValue); HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes); HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); HWC2::Error getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigIds); HWC2::Error getDozeSupport(int32_t* outSupport); HWC2::Error getHdrCapabilities(uint32_t* outNumTypes, int32_t* outTypes, float* outMaxLuminance, float* outMaxAverageLuminance, float* outMinLuminance); HWC2::Error getName(uint32_t* outSize, char* outName); HWC2::Error getReleaseFences(uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outFences); HWC2::Error getRequests(int32_t* outDisplayRequests, uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outLayerRequests); HWC2::Error getType(int32_t* outType); HWC2::Error present(int32_t* outRetireFence); HWC2::Error setActiveConfig(hwc2_config_t configId); HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence, int32_t dataspace, hwc_region_t damage); HWC2::Error setColorMode(int32_t mode); HWC2::Error setColorTransform(const float* matrix, int32_t hint); HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence); HWC2::Error setPowerMode(int32_t mode); HWC2::Error setVsyncEnabled(int32_t enabled); HWC2::Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests); HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z); HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height, int32_t format, int32_t dataspace); // Read configs from PRIMARY Display int populatePrimaryConfigs(); private: class Config { public: Config(Display& display) : mDisplay(display), mId(0), mAttributes() {} bool isOnDisplay(const Display& display) const { return display.getId() == mDisplay.getId(); } void setAttribute(HWC2::Attribute attribute, int32_t value); int32_t getAttribute(HWC2::Attribute attribute) const; void setId(hwc2_config_t id) {mId = id; } hwc2_config_t getId() const {return mId; } std::string toString() const; private: Display& mDisplay; hwc2_config_t mId; std::unordered_map mAttributes; }; // Stores changes requested from the device upon calling prepare(). // Handles change request to: // - Layer composition type. // - Layer hints. class Changes { public: uint32_t getNumTypes() const { return static_cast(mTypeChanges.size()); } uint32_t getNumLayerRequests() const { return static_cast(mLayerRequests.size()); } const std::unordered_map& getTypeChanges() const { return mTypeChanges; } const std::unordered_map& getLayerRequests() const { return mLayerRequests; } void addTypeChange(hwc2_layer_t layerId, HWC2::Composition type) { mTypeChanges.insert({layerId, type}); } void clearTypeChanges() { mTypeChanges.clear(); } void addLayerRequest(hwc2_layer_t layerId, HWC2::LayerRequest request) { mLayerRequests.insert({layerId, request}); } private: std::unordered_map mTypeChanges; std::unordered_map mLayerRequests; }; // Generate sw vsync signal class VsyncThread : public Thread { public: VsyncThread(Display& display) : mDisplay(display) {} virtual ~VsyncThread() {} private: Display& mDisplay; bool threadLoop() final; }; private: EmuHWC2& mDevice; // Display ID generator. static std::atomic sNextId; const hwc2_display_t mId; std::string mName; HWC2::DisplayType mType; HWC2::PowerMode mPowerMode; HWC2::Vsync mVsyncEnabled; uint32_t mVsyncPeriod; VsyncThread mVsyncThread; FencedBuffer mClientTarget; // Will only be non-null after the Display has been validated and // before it has been presented std::unique_ptr mChanges; // All layers this Display is aware of. std::multiset, SortLayersByZ> mLayers; std::vector mReleaseLayerIds; std::vector mReleaseFences; std::vector> mConfigs; std::shared_ptr mActiveConfig; std::set mColorModes; android_color_mode_t mActiveColorMode; bool mSetColorTransform; // The state of this display should only be modified from // SurfaceFlinger's main loop, with the exception of when dump is // called. To prevent a bad state from crashing us during a dump // call, all public calls into Display must acquire this mutex. mutable std::mutex mStateMutex; std::unique_ptr mGralloc; std::unique_ptr mComposeMsg; int mSyncDeviceFd; }; template static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId, Args... args) { auto display = getHWC2(device)->getDisplay(displayId); if (!display) { return static_cast(HWC2::Error::BadDisplay); } auto error = ((*display).*memFunc)(std::forward(args)...); return static_cast(error); } class Layer { public: explicit Layer(Display& display); Display& getDisplay() const {return mDisplay;} hwc2_layer_t getId() const {return mId;} bool operator==(const Layer& other) { return mId == other.mId; } bool operator!=(const Layer& other) { return !(*this == other); } // HWC2 Layer functions HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence); HWC2::Error setCursorPosition(int32_t x, int32_t y); HWC2::Error setSurfaceDamage(hwc_region_t damage); // HWC2 Layer state functions HWC2::Error setBlendMode(int32_t mode); HWC2::Error setColor(hwc_color_t color); HWC2::Error setCompositionType(int32_t type); HWC2::Error setDataspace(int32_t dataspace); HWC2::Error setDisplayFrame(hwc_rect_t frame); HWC2::Error setPlaneAlpha(float alpha); HWC2::Error setSidebandStream(const native_handle_t* stream); HWC2::Error setSourceCrop(hwc_frect_t crop); HWC2::Error setTransform(int32_t transform); HWC2::Error setVisibleRegion(hwc_region_t visible); HWC2::Error setZ(uint32_t z); HWC2::Composition getCompositionType() const { return mCompositionType; } hwc_color_t getColor() {return mColor; } uint32_t getZ() {return mZ; } std::size_t getNumVisibleRegions() {return mVisibleRegion.size(); } FencedBuffer& getLayerBuffer() {return mBuffer; } int32_t getBlendMode() {return (int32_t)mBlendMode; } float getPlaneAlpha() {return mPlaneAlpha; } hwc_frect_t getSourceCrop() {return mSourceCrop; } hwc_rect_t getDisplayFrame() {return mDisplayFrame; } hwc_transform_t getTransform() {return (hwc_transform_t)mTransform; } private: static std::atomic sNextId; const hwc2_layer_t mId; Display& mDisplay; FencedBuffer mBuffer; std::vector mSurfaceDamage; 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 mVisibleRegion; uint32_t mZ; }; template static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId, hwc2_layer_t layerId, Args... args) { auto result = getHWC2(device)->getLayer(displayId, layerId); auto error = std::get(result); if (error == HWC2::Error::None) { auto layer = std::get(result); error = ((*layer).*memFunc)(std::forward(args)...); } return static_cast(error); } // helpers void populateCapabilities(); Display* getDisplay(hwc2_display_t id); std::tuple getLayer(hwc2_display_t displayId, hwc2_layer_t layerId); std::unordered_set mCapabilities; // These are potentially accessed from multiple threads, and are protected // by this mutex. std::mutex mStateMutex; struct CallbackInfo { hwc2_callback_data_t data; hwc2_function_pointer_t pointer; }; std::unordered_map mCallbacks; std::unordered_map> mDisplays; std::unordered_map> mLayers; }; } #endif