blob: cd8d25ea83139e0a0bf3a4820fec31f38c68e11d [file] [log] [blame] [edit]
// 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_COORDINATOR_IMAGE_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_COORDINATOR_IMAGE_H_
#include <lib/inspect/cpp/inspect.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <fbl/intrusive_container_utils.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include "src/graphics/display/drivers/coordinator/client-id.h"
#include "src/graphics/display/drivers/coordinator/id-map.h"
#include "src/graphics/display/lib/api-types/cpp/config-stamp.h"
#include "src/graphics/display/lib/api-types/cpp/driver-config-stamp.h"
#include "src/graphics/display/lib/api-types/cpp/driver-image-id.h"
#include "src/graphics/display/lib/api-types/cpp/image-id.h"
#include "src/graphics/display/drivers/coordinator/image-lifecycle-listener.h"
#include "src/graphics/display/lib/api-types/cpp/image-metadata.h"
namespace display_coordinator {
class Image;
// Manages the lifetime of an imported sysmem pixel buffer.
//
// Instances are not thread-safe. Concurrent access must be synchronized
// externally.
class Image : public fbl::RefCounted<Image>,
public IdMappable<fbl::RefPtr<Image>, display::ImageId> {
private:
// Private forward declaration.
template <typename PtrType, typename TagType>
struct DoublyLinkedListTraits;
// Private typename aliases for DoublyLinkedList definition.
using DoublyLinkedListPointer = fbl::RefPtr<Image>;
using DefaultDoublyLinkedListTraits =
DoublyLinkedListTraits<DoublyLinkedListPointer, fbl::DefaultObjectTag>;
public:
// This defines the specific type of fbl::DoublyLinkedList that an Image can
// be placed into. Any intrusive container that can hold an Image must be of
// type Image::DoublyLinkedList.
//
// Note that the default fbl::DoublyLinkedList doesn't work in this case, due
// to the intrusive linked list node is guarded by a mutex.
using DoublyLinkedList = fbl::DoublyLinkedList<DoublyLinkedListPointer, fbl::DefaultObjectTag,
fbl::SizeOrder::N, DefaultDoublyLinkedListTraits>;
// `lifecycle_listener` must be non-null, and must outlive the Image.
Image(ImageLifecycleListener* listener, const display::ImageMetadata& metadata, display::ImageId id,
display::DriverImageId driver_id, inspect::Node* parent_node, ClientId client_id);
Image(const Image&) = delete;
Image(Image&&) = delete;
Image& operator=(const Image&) = delete;
Image& operator=(Image&&) = delete;
~Image();
display::DriverImageId driver_id() const { return driver_id_; }
const display::ImageMetadata& metadata() const { return metadata_; }
// The client that owns the image.
ClientId client_id() const { return client_id_; }
void set_latest_driver_config_stamp(display::DriverConfigStamp driver_config_stamp) {
latest_driver_config_stamp_ = driver_config_stamp;
}
display::DriverConfigStamp latest_driver_config_stamp() const {
return latest_driver_config_stamp_;
}
void set_latest_client_config_stamp(display::ConfigStamp stamp) {
latest_client_config_stamp_ = stamp;
}
display::ConfigStamp latest_client_config_stamp() const { return latest_client_config_stamp_; }
// Disposed images do not release engine driver-side resources on destruction.
//
// This state is necessary for safely shutting down an engine driver. When
// that happens, the driver may still be presenting some images. We want to
// clear out our data structures, but cannot call ReleaseImage() on those
// images.
void MarkDisposed() { disposed_ = true; }
// Checks if the Image is in a DoublyLinkedList container.
// TODO(https://fxbug.dev/317914671): investigate whether storing Images in doubly-linked lists
// continues to be desirable.
bool InDoublyLinkedList() const;
// Removes the Image from the DoublyLinkedList. The Image must be in a
// DoublyLinkedList when this is called.
DoublyLinkedListPointer RemoveFromDoublyLinkedList();
private:
// This defines the node trait used by the fbl::DoublyLinkedList that an Image
// can be placed in. PointerType and TagType are required for template
// argument resolution purpose in `fbl::DoublyLinkedList`.
template <typename PointerType, typename TagType>
struct DoublyLinkedListTraits {
public:
static auto& node_state(Image& obj) { return obj.doubly_linked_list_node_state_; }
};
friend DoublyLinkedListTraits<DoublyLinkedListPointer, fbl::DefaultObjectTag>;
void InitializeInspect(inspect::Node* parent_node);
// This NodeState allows the Image to be placed in an intrusive
// Image::DoublyLinkedList which can be either a Client's waiting image
// list, or 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.
fbl::DoublyLinkedListNodeState<DoublyLinkedListPointer,
fbl::NodeOptions::AllowRemoveFromContainer>
doubly_linked_list_node_state_;
const display::DriverImageId driver_id_;
const display::ImageMetadata metadata_;
ImageLifecycleListener& lifecycle_listener_;
const ClientId client_id_;
// Stamp of the latest applied display configuration that uses this image.
display::DriverConfigStamp latest_driver_config_stamp_ = display::kInvalidDriverConfigStamp;
// Stamp of the latest display configuration in Client (the DisplayController
// FIDL service) that uses this image.
//
// Note that for an image, it is possible that its |latest_client_config_stamp_|
// doesn't match the |latest_controller_config_stamp_|. This could happen when
// a client configuration sets a new layer image but the new image is not
// ready yet, so the controller has to keep using the old image.
display::ConfigStamp latest_client_config_stamp_ = display::kInvalidConfigStamp;
// If true, ReleaseImage() will not be called on image destruction.
bool disposed_ = false;
inspect::Node node_;
inspect::ValueList properties_;
inspect::BoolProperty presenting_property_;
inspect::BoolProperty retiring_property_;
};
} // namespace display_coordinator
#endif // SRC_GRAPHICS_DISPLAY_DRIVERS_COORDINATOR_IMAGE_H_