| // 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. |
| |
| #pragma once |
| |
| #include <ddk/protocol/display/controller.h> |
| #include <fbl/ref_counted.h> |
| #include <fbl/ref_ptr.h> |
| #include <lib/zx/vmo.h> |
| #include <zircon/listnode.h> |
| |
| #include <atomic> |
| |
| #include "fence.h" |
| #include "fuchsia/hardware/display/c/fidl.h" |
| #include "id-map.h" |
| |
| namespace display { |
| |
| class Controller; |
| |
| typedef struct image_node { |
| list_node_t link; |
| fbl::RefPtr<class Image> self; |
| } image_node_t; |
| |
| class Image : public fbl::RefCounted<Image>, public IdMappable<fbl::RefPtr<Image>> { |
| public: |
| Image(Controller* controller, const image_t& info, zx::vmo vmo); |
| ~Image(); |
| |
| image_t& info() { return info_; } |
| // Marks the image as in use. |
| bool Acquire(); |
| // Marks the image as not in use. Should only be called before PrepareFences. |
| void DiscardAcquire(); |
| // Called to set this image's fences and prepare the image to be displayed. |
| void PrepareFences(fbl::RefPtr<FenceReference>&& wait, |
| fbl::RefPtr<FenceReference>&& signal); |
| // Called to immediately retire the image if StartPresent hasn't been called yet. |
| void EarlyRetire(); |
| // Called when the image is passed to the display hardware. |
| void StartPresent(); |
| // Called when another image is presented after this one. |
| void StartRetire(); |
| // Called on vsync after StartRetire has been called. |
| void OnRetire(); |
| |
| // Called on all waiting images when any fence fires. |
| void OnFenceReady(FenceReference* fence); |
| |
| // Called to reset fences when client releases the image. Releasing fences |
| // is independent of the rest of the image lifecycle. |
| void ResetFences(); |
| |
| bool IsReady() const { return wait_fence_ == nullptr; } |
| |
| bool HasSameConfig(const image_t& config) const { |
| for (uint32_t i = 0; i < countof(info_.planes); i++) { |
| if (info_.planes[i].bytes_per_row != config.planes[i].bytes_per_row || |
| info_.planes[i].byte_offset != config.planes[i].byte_offset) { |
| return false; |
| } |
| } |
| |
| return info_.width == config.width |
| && info_.height == config.height |
| && info_.pixel_format == config.pixel_format |
| && info_.type == config.type; |
| } |
| bool HasSameConfig(const Image& other) const { return HasSameConfig(other.info_); } |
| |
| const zx::vmo& vmo() { return vmo_; } |
| |
| void set_z_index(uint32_t z_index) { z_index_ = z_index; } |
| uint32_t z_index() const { return z_index_; } |
| |
| // The node alternates between a client's waiting image list and the controller's |
| // presented image list. The presented image list is protected with the controller mutex, |
| // and the waiting list is only accessed on the loop and thus is not generally |
| // protected. However, transfers between the lists are protected by the controller mutex. |
| image_node_t node = { |
| .link = LIST_INITIAL_CLEARED_VALUE, |
| .self = nullptr, |
| }; |
| |
| private: |
| image_t info_; |
| Controller* const controller_; |
| |
| // z_index is set/read by controller.cpp under its lock |
| uint32_t z_index_; |
| |
| // Only ever accessed on loop thread, so no synchronization |
| fbl::RefPtr<FenceReference> wait_fence_ = nullptr; |
| // signal_fence_ is only accessed on the loop. armed_signal_fence_ is accessed |
| // under the controller mutex. See comment in ::OnRetire for more details. |
| fbl::RefPtr<FenceReference> signal_fence_ = nullptr; |
| fbl::RefPtr<FenceReference> armed_signal_fence_ = nullptr; |
| |
| // Flag which indicates that the image is currently in some display configuration. |
| std::atomic_bool in_use_ = {}; |
| // Flag indicating that the image is being managed by the display hardware. Only |
| // accessed under the controller mutex. |
| bool presenting_ = false; |
| // Flag indicating that the image has started the process of retiring and will be free after |
| // the next vsync. This is distinct from presenting_ due to multiplexing the display between |
| // multiple clients. Only accessed under the controller mutex. |
| bool retiring_ = false; |
| |
| const zx::vmo vmo_; |
| }; |
| |
| } // namespace display |