#include "include/dvr/dvr_hardware_composer_client.h" #include #include #include #include #include #include struct DvrHwcFrame { android::dvr::ComposerView::Frame frame; }; namespace { class HwcCallback : public android::dvr::BnVrComposerCallback { public: explicit HwcCallback(DvrHwcOnFrameCallback callback, void* client_state); ~HwcCallback() override; std::unique_ptr DequeueFrame(); private: // android::dvr::BnVrComposerCallback: android::binder::Status onNewFrame( const android::dvr::ParcelableComposerFrame& frame, android::dvr::ParcelableUniqueFd* fence) override; DvrHwcOnFrameCallback callback_; void* client_state_; HwcCallback(const HwcCallback&) = delete; void operator=(const HwcCallback&) = delete; }; HwcCallback::HwcCallback(DvrHwcOnFrameCallback callback, void* client_state) : callback_(callback), client_state_(client_state) {} HwcCallback::~HwcCallback() {} android::binder::Status HwcCallback::onNewFrame( const android::dvr::ParcelableComposerFrame& frame, android::dvr::ParcelableUniqueFd* fence) { std::unique_ptr dvr_frame(new DvrHwcFrame()); dvr_frame->frame = frame.frame(); fence->set_fence(android::base::unique_fd(callback_(client_state_, dvr_frame.release()))); return android::binder::Status::ok(); } } // namespace struct DvrHwcClient { android::sp composer; android::sp callback; }; DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) { std::unique_ptr client(new DvrHwcClient()); android::sp sm(android::defaultServiceManager()); client->composer = android::interface_cast( sm->getService(android::dvr::IVrComposer::SERVICE_NAME())); if (!client->composer.get()) return nullptr; client->callback = new HwcCallback(callback, data); android::binder::Status status = client->composer->registerObserver( client->callback); if (!status.isOk()) return nullptr; return client.release(); } void dvrHwcClientDestroy(DvrHwcClient* client) { delete client; } void dvrHwcFrameDestroy(DvrHwcFrame* frame) { delete frame; } DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) { return frame->frame.display_id; } int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame) { return frame->frame.display_width; } int32_t dvrHwcFrameGetDisplayHeight(DvrHwcFrame* frame) { return frame->frame.display_height; } bool dvrHwcFrameGetDisplayRemoved(DvrHwcFrame* frame) { return frame->frame.removed; } size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame) { return frame->frame.layers.size(); } uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame) { return static_cast(frame->frame.active_config); } uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame) { return static_cast(frame->frame.color_mode); } void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix, int32_t* out_hint) { *out_hint = frame->frame.color_transform_hint; memcpy(out_matrix, frame->frame.color_transform, sizeof(frame->frame.color_transform)); } uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame) { return static_cast(frame->frame.power_mode); } uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame) { return static_cast(frame->frame.vsync_enabled); } DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].id; } AHardwareBuffer* dvrHwcFrameGetLayerBuffer(DvrHwcFrame* frame, size_t layer_index) { AHardwareBuffer* buffer = android::AHardwareBuffer_from_GraphicBuffer( frame->frame.layers[layer_index].buffer.get()); AHardwareBuffer_acquire(buffer); return buffer; } int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].fence->dup(); } DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index) { return DvrHwcRecti{ frame->frame.layers[layer_index].display_frame.left, frame->frame.layers[layer_index].display_frame.top, frame->frame.layers[layer_index].display_frame.right, frame->frame.layers[layer_index].display_frame.bottom, }; } DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) { return DvrHwcRectf{ frame->frame.layers[layer_index].crop.left, frame->frame.layers[layer_index].crop.top, frame->frame.layers[layer_index].crop.right, frame->frame.layers[layer_index].crop.bottom, }; } DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index) { return static_cast( frame->frame.layers[layer_index].blend_mode); } float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].alpha; } uint32_t dvrHwcFrameGetLayerType(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].type; } uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].app_id; } uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].z_order; } void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index, int32_t* out_x, int32_t* out_y) { *out_x = frame->frame.layers[layer_index].cursor_x; *out_y = frame->frame.layers[layer_index].cursor_y; } uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].transform; } uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].dataspace; } uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index) { const auto& color = frame->frame.layers[layer_index].color; return color.r | (static_cast(color.g) << 8) | (static_cast(color.b) << 16) | (static_cast(color.a) << 24); } uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].visible_regions.size(); } DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame, size_t layer_index, size_t index) { return DvrHwcRecti{ frame->frame.layers[layer_index].visible_regions[index].left, frame->frame.layers[layer_index].visible_regions[index].top, frame->frame.layers[layer_index].visible_regions[index].right, frame->frame.layers[layer_index].visible_regions[index].bottom, }; } uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame, size_t layer_index) { return frame->frame.layers[layer_index].damaged_regions.size(); } DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame, size_t layer_index, size_t index) { return DvrHwcRecti{ frame->frame.layers[layer_index].damaged_regions[index].left, frame->frame.layers[layer_index].damaged_regions[index].top, frame->frame.layers[layer_index].damaged_regions[index].right, frame->frame.layers[layer_index].damaged_regions[index].bottom, }; }