| // 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. |
| |
| // WARNING: This file is machine generated by fidlc. |
| |
| #pragma once |
| |
| #include <ddk/protocol/display-controller.h> |
| #include <ddktl/device-internal.h> |
| #include <zircon/assert.h> |
| #include <zircon/compiler.h> |
| #include <zircon/device/audio.h> |
| #include <zircon/types.h> |
| |
| #include "display-controller-internal.h" |
| |
| // DDK display-controller-protocol support |
| // |
| // :: Proxies :: |
| // |
| // ddk::DisplayControllerProtocolProxy is a simple wrapper around |
| // display_controller_protocol_t. It does not own the pointers passed to it |
| // |
| // :: Mixins :: |
| // |
| // ddk::DisplayControllerProtocol is a mixin class that simplifies writing DDK drivers |
| // that implement the display-controller protocol. It doesn't set the base protocol. |
| // |
| // :: Examples :: |
| // |
| // // A driver that implements a ZX_PROTOCOL_DISPLAY_CONTROLLER device. |
| // class DisplayControllerDevice { |
| // using DisplayControllerDeviceType = ddk::Device<DisplayControllerDevice, /* ddk mixins */>; |
| // |
| // class DisplayControllerDevice : public DisplayControllerDeviceType, |
| // public ddk::DisplayControllerProtocol<DisplayControllerDevice> { |
| // public: |
| // DisplayControllerDevice(zx_device_t* parent) |
| // : DisplayControllerDeviceType("my-display-controller-protocol-device", parent) {} |
| // |
| // void DisplayControllerSetDisplayControllerInterface(const display_controller_interface_t* |
| // intf); |
| // |
| // zx_status_t DisplayControllerImportVmoImage(image_t* image, zx_handle_t vmo, size_t offset); |
| // |
| // void DisplayControllerReleaseImage(image_t* image); |
| // |
| // uint32_t DisplayControllerCheckConfiguration(const display_config_t** display_config_list, |
| // size_t display_config_count, uint32_t** out_layer_cfg_result_list, size_t* |
| // layer_cfg_result_count); |
| // |
| // void DisplayControllerApplyConfiguration(const display_config_t** display_config_list, size_t |
| // display_config_count); |
| // |
| // uint32_t DisplayControllerComputeLinearStride(uint32_t width, zx_pixel_format_t |
| // pixel_format); |
| // |
| // zx_status_t DisplayControllerAllocateVmo(uint64_t size, zx_handle_t* out_vmo); |
| // |
| // ... |
| // }; |
| |
| namespace ddk { |
| |
| // The client will not make any `ZX_PROTOCOL_DISPLAY_CONTROLLER_IMPL` calls into the device |
| // during these callbacks. |
| template <typename D> |
| class DisplayControllerInterface : public internal::base_mixin { |
| public: |
| DisplayControllerInterface() { |
| internal::CheckDisplayControllerInterfaceSubclass<D>(); |
| display_controller_interface_ops_.on_displays_changed = |
| DisplayControllerInterfaceOnDisplaysChanged; |
| display_controller_interface_ops_.on_display_vsync = |
| DisplayControllerInterfaceOnDisplayVsync; |
| display_controller_interface_ops_.get_audio_format = |
| DisplayControllerInterfaceGetAudioFormat; |
| } |
| |
| protected: |
| display_controller_interface_ops_t display_controller_interface_ops_ = {}; |
| |
| private: |
| // Callbacks which are invoked when displays are added or removed. |added_display_list| and |
| // |removed_display_list| point to arrays of the display ids which were added and removed. If |
| // |added_display_count| or |removed_display_count| is 0, the corresponding array can be NULL. |
| // The driver must be done accessing any images which were on the removed displays. |
| // The driver should call this function when the callback is registered if any displays |
| // are present. |
| static void DisplayControllerInterfaceOnDisplaysChanged( |
| void* ctx, const added_display_args_t* added_display_list, size_t added_display_count, |
| const uint64_t* removed_display_list, size_t removed_display_count, |
| added_display_info_t* out_display_info_list, size_t display_info_count, |
| size_t* out_display_info_actual) { |
| static_cast<D*>(ctx)->DisplayControllerInterfaceOnDisplaysChanged( |
| added_display_list, added_display_count, removed_display_list, removed_display_count, |
| out_display_info_list, display_info_count, out_display_info_actual); |
| } |
| // |timestamp| is the ZX_CLOCK_MONOTONIC timestamp at which the vsync occurred. |
| // |handles| points to an array of image handles of each framebuffer being |
| // displayed, in increasing z-order. |
| static void DisplayControllerInterfaceOnDisplayVsync(void* ctx, uint64_t display_id, |
| int64_t timestamp, |
| const uint64_t* handle_list, |
| size_t handle_count) { |
| static_cast<D*>(ctx)->DisplayControllerInterfaceOnDisplayVsync(display_id, timestamp, |
| handle_list, handle_count); |
| } |
| static zx_status_t |
| DisplayControllerInterfaceGetAudioFormat(void* ctx, uint64_t display_id, uint32_t fmt_idx, |
| audio_stream_format_range_t* out_fmt) { |
| return static_cast<D*>(ctx)->DisplayControllerInterfaceGetAudioFormat(display_id, fmt_idx, |
| out_fmt); |
| } |
| }; |
| |
| class DisplayControllerInterfaceProxy { |
| public: |
| DisplayControllerInterfaceProxy() : ops_(nullptr), ctx_(nullptr) {} |
| DisplayControllerInterfaceProxy(const display_controller_interface_t* proto) |
| : ops_(proto->ops), ctx_(proto->ctx) {} |
| |
| void GetProto(display_controller_interface_t* proto) { |
| proto->ctx = ctx_; |
| proto->ops = ops_; |
| } |
| bool is_valid() { return ops_ != nullptr; } |
| void clear() { |
| ctx_ = nullptr; |
| ops_ = nullptr; |
| } |
| // Callbacks which are invoked when displays are added or removed. |added_display_list| and |
| // |removed_display_list| point to arrays of the display ids which were added and removed. If |
| // |added_display_count| or |removed_display_count| is 0, the corresponding array can be NULL. |
| // The driver must be done accessing any images which were on the removed displays. |
| // The driver should call this function when the callback is registered if any displays |
| // are present. |
| void OnDisplaysChanged(const added_display_args_t* added_display_list, |
| size_t added_display_count, const uint64_t* removed_display_list, |
| size_t removed_display_count, |
| added_display_info_t* out_display_info_list, size_t display_info_count, |
| size_t* out_display_info_actual) { |
| ops_->on_displays_changed(ctx_, added_display_list, added_display_count, |
| removed_display_list, removed_display_count, |
| out_display_info_list, display_info_count, |
| out_display_info_actual); |
| } |
| // |timestamp| is the ZX_CLOCK_MONOTONIC timestamp at which the vsync occurred. |
| // |handles| points to an array of image handles of each framebuffer being |
| // displayed, in increasing z-order. |
| void OnDisplayVsync(uint64_t display_id, int64_t timestamp, const uint64_t* handle_list, |
| size_t handle_count) { |
| ops_->on_display_vsync(ctx_, display_id, timestamp, handle_list, handle_count); |
| } |
| zx_status_t GetAudioFormat(uint64_t display_id, uint32_t fmt_idx, |
| audio_stream_format_range_t* out_fmt) { |
| return ops_->get_audio_format(ctx_, display_id, fmt_idx, out_fmt); |
| } |
| |
| private: |
| display_controller_interface_ops_t* ops_; |
| void* ctx_; |
| }; |
| |
| // The client guarantees that check_configuration and apply_configuration are always |
| // made from a single thread. The client makes no other threading guarantees. |
| template <typename D> |
| class DisplayControllerProtocol : public internal::base_mixin { |
| public: |
| DisplayControllerProtocol() { |
| internal::CheckDisplayControllerProtocolSubclass<D>(); |
| display_controller_protocol_ops_.set_display_controller_interface = |
| DisplayControllerSetDisplayControllerInterface; |
| display_controller_protocol_ops_.import_vmo_image = DisplayControllerImportVmoImage; |
| display_controller_protocol_ops_.release_image = DisplayControllerReleaseImage; |
| display_controller_protocol_ops_.check_configuration = DisplayControllerCheckConfiguration; |
| display_controller_protocol_ops_.apply_configuration = DisplayControllerApplyConfiguration; |
| display_controller_protocol_ops_.compute_linear_stride = |
| DisplayControllerComputeLinearStride; |
| display_controller_protocol_ops_.allocate_vmo = DisplayControllerAllocateVmo; |
| } |
| |
| protected: |
| display_controller_protocol_ops_t display_controller_protocol_ops_ = {}; |
| |
| private: |
| // The function will only be called once, and it will be called before any other |
| // functions are called. |
| static void |
| DisplayControllerSetDisplayControllerInterface(void* ctx, |
| const display_controller_interface_t* intf) { |
| static_cast<D*>(ctx)->DisplayControllerSetDisplayControllerInterface(intf); |
| } |
| // Imports a VMO backed image into the driver. The driver should set image->handle. The |
| // driver does not own the vmo handle passed to this function. |
| static zx_status_t DisplayControllerImportVmoImage(void* ctx, image_t* image, zx_handle_t vmo, |
| size_t offset) { |
| return static_cast<D*>(ctx)->DisplayControllerImportVmoImage(image, vmo, offset); |
| } |
| // Releases any driver state associated with the given image. The client guarantees that |
| // any images passed to apply_config will not be released until a vsync occurs with a |
| // more recent image. |
| static void DisplayControllerReleaseImage(void* ctx, image_t* image) { |
| static_cast<D*>(ctx)->DisplayControllerReleaseImage(image); |
| } |
| // Validates the given configuration. |
| // The configuration may not include all displays. Omiteed displays should be treated as |
| // whichever of off or displaying a blank screen results in a more premissive validation. |
| // All displays in a configuration will have at least one layer. The layers will be |
| // arranged in increasing z-order, and their z_index fields will be set consecutively. |
| // Whether or not the driver can accept the configuration cannot depend on the |
| // particular image handles, as it must always be possible to present a new image in |
| // place of another image with a matching configuration. It also cannot depend on the |
| // cursor position, as that can be updated without another call to check_configuration. |
| // display_cfg_result should be set to a CONFIG_DISPLAY_* error if the combination of |
| // display modes is not supported. |
| // layer_cfg_result points to an array of arrays. The primary length is display_count, the |
| // secondary lengths are the corresponding display_cfg's layer_count. If display_cfg_result |
| // is CONFIG_DISPLAY_OK, any errors in layer configuration should be returned as a CLIENT* |
| // flag in the corresponding layer_cfg_result entry. |
| // The driver must not retain references to the configuration after this function returns. |
| // TODO: Fix me... |
| static uint32_t DisplayControllerCheckConfiguration( |
| void* ctx, const display_config_t** display_config_list, size_t display_config_count, |
| uint32_t** out_layer_cfg_result_list, size_t* layer_cfg_result_count) { |
| return static_cast<D*>(ctx)->DisplayControllerCheckConfiguration( |
| display_config_list, display_config_count, out_layer_cfg_result_list, |
| layer_cfg_result_count); |
| } |
| // Applies the configuration. |
| // All configurations passed to this function will be derived from configurations which |
| // have been succesfully validated, with the only differences either being omitted layers |
| // or different image handles. To account for any layers which are not present, the driver |
| // must use the z_index values of the present layers to configure them as if the whole |
| // configuration was present. |
| // Unlike with check_configuration, displays included in the configuration are not |
| // guaranteed to include any layers. Both omitted displays and displays with no layers |
| // can either be turned off or set to display a blank screen, but for displays with no |
| // layers there is a strong preference to display a blank screen instead of turn them off. |
| // In either case, the driver must drop all references to old images and invoke the vsync |
| // callback after doing so. |
| // The driver must not retain references to the configuration after this function returns. |
| static void DisplayControllerApplyConfiguration(void* ctx, |
| const display_config_t** display_config_list, |
| size_t display_config_count) { |
| static_cast<D*>(ctx)->DisplayControllerApplyConfiguration(display_config_list, |
| display_config_count); |
| } |
| // Computes the stride (in pixels) necessary for a linear image with the given width |
| // and pixel format. Returns 0 on error. |
| static uint32_t DisplayControllerComputeLinearStride(void* ctx, uint32_t width, |
| zx_pixel_format_t pixel_format) { |
| return static_cast<D*>(ctx)->DisplayControllerComputeLinearStride(width, pixel_format); |
| } |
| // Allocates a VMO of the requested size which can be used for images. |
| static zx_status_t DisplayControllerAllocateVmo(void* ctx, uint64_t size, |
| zx_handle_t* out_vmo) { |
| return static_cast<D*>(ctx)->DisplayControllerAllocateVmo(size, out_vmo); |
| } |
| }; |
| |
| class DisplayControllerProtocolProxy { |
| public: |
| DisplayControllerProtocolProxy() : ops_(nullptr), ctx_(nullptr) {} |
| DisplayControllerProtocolProxy(const display_controller_protocol_t* proto) |
| : ops_(proto->ops), ctx_(proto->ctx) {} |
| |
| void GetProto(display_controller_protocol_t* proto) { |
| proto->ctx = ctx_; |
| proto->ops = ops_; |
| } |
| bool is_valid() { return ops_ != nullptr; } |
| void clear() { |
| ctx_ = nullptr; |
| ops_ = nullptr; |
| } |
| // The function will only be called once, and it will be called before any other |
| // functions are called. |
| void SetDisplayControllerInterface(const display_controller_interface_t* intf) { |
| ops_->set_display_controller_interface(ctx_, intf); |
| } |
| // Imports a VMO backed image into the driver. The driver should set image->handle. The |
| // driver does not own the vmo handle passed to this function. |
| zx_status_t ImportVmoImage(image_t* image, zx_handle_t vmo, size_t offset) { |
| return ops_->import_vmo_image(ctx_, image, vmo, offset); |
| } |
| // Releases any driver state associated with the given image. The client guarantees that |
| // any images passed to apply_config will not be released until a vsync occurs with a |
| // more recent image. |
| void ReleaseImage(image_t* image) { ops_->release_image(ctx_, image); } |
| // Validates the given configuration. |
| // The configuration may not include all displays. Omiteed displays should be treated as |
| // whichever of off or displaying a blank screen results in a more premissive validation. |
| // All displays in a configuration will have at least one layer. The layers will be |
| // arranged in increasing z-order, and their z_index fields will be set consecutively. |
| // Whether or not the driver can accept the configuration cannot depend on the |
| // particular image handles, as it must always be possible to present a new image in |
| // place of another image with a matching configuration. It also cannot depend on the |
| // cursor position, as that can be updated without another call to check_configuration. |
| // display_cfg_result should be set to a CONFIG_DISPLAY_* error if the combination of |
| // display modes is not supported. |
| // layer_cfg_result points to an array of arrays. The primary length is display_count, the |
| // secondary lengths are the corresponding display_cfg's layer_count. If display_cfg_result |
| // is CONFIG_DISPLAY_OK, any errors in layer configuration should be returned as a CLIENT* |
| // flag in the corresponding layer_cfg_result entry. |
| // The driver must not retain references to the configuration after this function returns. |
| // TODO: Fix me... |
| uint32_t CheckConfiguration(const display_config_t** display_config_list, |
| size_t display_config_count, uint32_t** out_layer_cfg_result_list, |
| size_t* layer_cfg_result_count) { |
| return ops_->check_configuration(ctx_, display_config_list, display_config_count, |
| out_layer_cfg_result_list, layer_cfg_result_count); |
| } |
| // Applies the configuration. |
| // All configurations passed to this function will be derived from configurations which |
| // have been succesfully validated, with the only differences either being omitted layers |
| // or different image handles. To account for any layers which are not present, the driver |
| // must use the z_index values of the present layers to configure them as if the whole |
| // configuration was present. |
| // Unlike with check_configuration, displays included in the configuration are not |
| // guaranteed to include any layers. Both omitted displays and displays with no layers |
| // can either be turned off or set to display a blank screen, but for displays with no |
| // layers there is a strong preference to display a blank screen instead of turn them off. |
| // In either case, the driver must drop all references to old images and invoke the vsync |
| // callback after doing so. |
| // The driver must not retain references to the configuration after this function returns. |
| void ApplyConfiguration(const display_config_t** display_config_list, |
| size_t display_config_count) { |
| ops_->apply_configuration(ctx_, display_config_list, display_config_count); |
| } |
| // Computes the stride (in pixels) necessary for a linear image with the given width |
| // and pixel format. Returns 0 on error. |
| uint32_t ComputeLinearStride(uint32_t width, zx_pixel_format_t pixel_format) { |
| return ops_->compute_linear_stride(ctx_, width, pixel_format); |
| } |
| // Allocates a VMO of the requested size which can be used for images. |
| zx_status_t AllocateVmo(uint64_t size, zx_handle_t* out_vmo) { |
| return ops_->allocate_vmo(ctx_, size, out_vmo); |
| } |
| |
| private: |
| display_controller_protocol_ops_t* ops_; |
| void* ctx_; |
| }; |
| |
| } // namespace ddk |