| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_GRAPHICS_DISPLAY_DRIVERS_SIMPLE_SIMPLE_DISPLAY_H_ |
| #define SRC_GRAPHICS_DISPLAY_DRIVERS_SIMPLE_SIMPLE_DISPLAY_H_ |
| |
| #include <lib/ddk/driver.h> |
| #include <zircon/compiler.h> |
| #include <zircon/errors.h> |
| |
| #include <fbl/mutex.h> |
| |
| #include "src/graphics/display/lib/api-types-cpp/config-stamp.h" |
| #include "src/graphics/display/lib/api-types-cpp/driver-buffer-collection-id.h" |
| |
| #if __cplusplus |
| |
| #include <fidl/fuchsia.hardware.sysmem/cpp/wire.h> |
| #include <fidl/fuchsia.images2/cpp/wire.h> |
| #include <fidl/fuchsia.sysmem/cpp/wire.h> |
| #include <fidl/fuchsia.sysmem2/cpp/wire.h> |
| #include <fuchsia/hardware/display/controller/cpp/banjo.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/fidl/cpp/wire/server.h> |
| #include <lib/fit/function.h> |
| #include <lib/mmio/mmio.h> |
| #include <lib/zircon-internal/thread_annotations.h> |
| #include <lib/zx/clock.h> |
| #include <lib/zx/vmo.h> |
| |
| #include <atomic> |
| #include <memory> |
| |
| #include <ddktl/device.h> |
| |
| class SimpleDisplay; |
| using DeviceType = ddk::Device<SimpleDisplay>; |
| using HeapServer = fidl::WireServer<fuchsia_hardware_sysmem::Heap>; |
| using BufferKey = std::pair<uint64_t, uint32_t>; |
| class SimpleDisplay : public DeviceType, |
| public HeapServer, |
| public ddk::DisplayControllerImplProtocol<SimpleDisplay, ddk::base_protocol> { |
| public: |
| SimpleDisplay(zx_device_t* parent, |
| fidl::WireSyncClient<fuchsia_hardware_sysmem::Sysmem> hardware_sysmem, |
| fidl::WireSyncClient<fuchsia_sysmem2::Allocator> sysmem, |
| fdf::MmioBuffer framebuffer_mmio, uint32_t width, uint32_t height, uint32_t stride, |
| fuchsia_images2::wire::PixelFormat format); |
| ~SimpleDisplay() = default; |
| |
| void DdkRelease(); |
| zx_status_t Bind(const char* name, std::unique_ptr<SimpleDisplay>* controller_ptr); |
| |
| void AllocateVmo(AllocateVmoRequestView request, AllocateVmoCompleter::Sync& completer) override; |
| void DeleteVmo(DeleteVmoRequestView request, DeleteVmoCompleter::Sync& completer) override; |
| |
| void DisplayControllerImplSetDisplayControllerInterface( |
| const display_controller_interface_protocol_t* intf); |
| void DisplayControllerImplResetDisplayControllerInterface(); |
| zx_status_t DisplayControllerImplImportBufferCollection( |
| uint64_t banjo_driver_buffer_collection_id, zx::channel collection_token); |
| zx_status_t DisplayControllerImplReleaseBufferCollection( |
| uint64_t banjo_driver_buffer_collection_id); |
| zx_status_t DisplayControllerImplImportImage(const image_metadata_t* image_metadata, |
| uint64_t banjo_driver_buffer_collection_id, |
| uint32_t index, uint64_t* out_image_handle); |
| zx_status_t DisplayControllerImplImportImageForCapture(uint64_t banjo_driver_buffer_collection_id, |
| uint32_t index, |
| uint64_t* out_capture_handle) { |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| void DisplayControllerImplReleaseImage(uint64_t image_handle); |
| config_check_result_t DisplayControllerImplCheckConfiguration( |
| const display_config_t* display_configs, size_t display_count, |
| client_composition_opcode_t* out_client_composition_opcodes_list, |
| size_t client_composition_opcodes_count, size_t* out_client_composition_opcodes_actual); |
| void DisplayControllerImplApplyConfiguration(const display_config_t* display_config, |
| size_t display_count, |
| const config_stamp_t* banjo_config_stamp); |
| void DisplayControllerImplSetEld(uint64_t display_id, const uint8_t* raw_eld_list, |
| size_t raw_eld_count) {} // No ELD required for non-HDA systems. |
| zx_status_t DisplayControllerImplSetBufferCollectionConstraints( |
| const image_buffer_usage_t* usage, uint64_t banjo_driver_buffer_collection_id); |
| zx_status_t DisplayControllerImplSetDisplayPower(uint64_t display_id, bool power_on) { |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| bool DisplayControllerImplIsCaptureSupported() { return false; } |
| zx_status_t DisplayControllerImplStartCapture(uint64_t capture_handle) { |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| zx_status_t DisplayControllerImplReleaseCapture(uint64_t capture_handle) { |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| bool DisplayControllerImplIsCaptureCompleted() { return false; } |
| zx_status_t DisplayControllerImplSetMinimumRgb(uint8_t minimum_rgb) { |
| return ZX_ERR_NOT_SUPPORTED; |
| } |
| |
| const std::unordered_map<display::DriverBufferCollectionId, |
| fidl::WireSyncClient<fuchsia_sysmem2::BufferCollection>>& |
| GetBufferCollectionsForTesting() const { |
| return buffer_collections_; |
| } |
| |
| private: |
| void OnPeriodicVSync(); |
| |
| fidl::WireSyncClient<fuchsia_hardware_sysmem::Sysmem> hardware_sysmem_; |
| |
| // The sysmem allocator client used to bind incoming buffer collection tokens. |
| fidl::WireSyncClient<fuchsia_sysmem2::Allocator> sysmem_; |
| |
| // Imported sysmem buffer collections. |
| std::unordered_map<display::DriverBufferCollectionId, |
| fidl::WireSyncClient<fuchsia_sysmem2::BufferCollection>> |
| buffer_collections_; |
| |
| async::Loop loop_; |
| |
| // protects only framebuffer_key_ |
| fbl::Mutex framebuffer_key_mtx_; |
| std::optional<BufferKey> framebuffer_key_ TA_GUARDED(framebuffer_key_mtx_); |
| |
| static_assert(std::atomic<bool>::is_always_lock_free); |
| std::atomic<bool> has_image_; |
| |
| // A lock is required to ensure the atomicity when setting |config_stamp| in |
| // |ApplyConfiguration()| and passing |&config_stamp_| to |OnDisplayVsync()|. |
| fbl::Mutex mtx_; |
| display::ConfigStamp config_stamp_ TA_GUARDED(mtx_) = display::kInvalidConfigStamp; |
| |
| const fdf::MmioBuffer framebuffer_mmio_; |
| const uint32_t width_; |
| const uint32_t height_; |
| const uint32_t stride_; |
| const fuchsia_images2::wire::PixelFormat format_; |
| |
| const fuchsia_images2::wire::PixelFormatModifier kFormatModifier = |
| fuchsia_images2::wire::PixelFormatModifier::kLinear; |
| |
| // Only used on the vsync thread. |
| zx::time next_vsync_time_; |
| ddk::DisplayControllerInterfaceProtocolClient intf_; |
| }; |
| |
| #endif // __cplusplus |
| |
| __BEGIN_CDECLS |
| zx_status_t bind_simple_pci_display(zx_device_t* dev, const char* name, uint32_t bar, |
| uint32_t width, uint32_t height, uint32_t stride, |
| fuchsia_images2::wire::PixelFormat format); |
| |
| zx_status_t bind_simple_fidl_pci_display(zx_device_t* dev, const char* name, uint32_t bar, |
| uint32_t width, uint32_t height, uint32_t stride, |
| fuchsia_images2::wire::PixelFormat format); |
| |
| zx_status_t bind_simple_pci_display_bootloader(zx_device_t* dev, const char* name, uint32_t bar, |
| bool use_fidl); |
| __END_CDECLS |
| |
| #endif // SRC_GRAPHICS_DISPLAY_DRIVERS_SIMPLE_SIMPLE_DISPLAY_H_ |