#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_ #define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_ #include <pdx/file_handle.h> #include <pdx/service.h> #include <private/dvr/buffer_hub_queue_client.h> #include <private/dvr/display_protocol.h> #include <private/dvr/ring_buffer.h> #include <functional> #include <iterator> #include <memory> #include <string> #include <vector> #include "acquired_buffer.h" namespace android { namespace dvr { class DisplayService; enum class SurfaceType { Direct, Application, }; class DisplaySurface : public pdx::Channel { public: static pdx::Status<std::shared_ptr<DisplaySurface>> Create( DisplayService* service, int surface_id, int process_id, int user_id, const display::SurfaceAttributes& attributes); ~DisplaySurface() override; DisplayService* service() const { return service_; } SurfaceType surface_type() const { return surface_type_; } int surface_id() const { return surface_id_; } int process_id() const { return process_id_; } int user_id() const { return user_id_; } bool visible() const { return visible_; } int z_order() const { return z_order_; } const display::SurfaceAttributes& attributes() const { return attributes_; } display::SurfaceUpdateFlags update_flags() const { return update_flags_; } virtual std::vector<int32_t> GetQueueIds() const { return {}; } bool IsUpdatePending() const { return update_flags_.value() != display::SurfaceUpdateFlags::None; } protected: DisplaySurface(DisplayService* service, SurfaceType surface_type, int surface_id, int process_id, int user_id, const display::SurfaceAttributes& attributes); // Utility to retrieve a shared pointer to this channel as the desired derived // type. template < typename T = DisplaySurface, typename = std::enable_if_t<std::is_base_of<DisplaySurface, T>::value>> std::shared_ptr<T> Self() { return std::static_pointer_cast<T>(shared_from_this()); } virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue( pdx::Message& message, size_t meta_size_bytes) = 0; // Registers a consumer queue with the event dispatcher in DisplayService. The // OnQueueEvent callback below is called to handle queue events. pdx::Status<void> RegisterQueue( const std::shared_ptr<ConsumerQueue>& consumer_queue); pdx::Status<void> UnregisterQueue( const std::shared_ptr<ConsumerQueue>& consumer_queue); // Called by the event dispatcher in DisplayService when a registered queue // event triggers. Executes on the event dispatcher thread. virtual void OnQueueEvent( const std::shared_ptr<ConsumerQueue>& consumer_queue, int events); void SurfaceUpdated(display::SurfaceUpdateFlags update_flags); void ClearUpdate(); // Synchronizes access to mutable state below between message dispatch thread // and frame post thread. mutable std::mutex lock_; private: friend class DisplayService; friend class DisplayManagerService; // Dispatches display surface messages to the appropriate handlers. This // handler runs on the VrFlinger message dispatch thread. pdx::Status<void> HandleMessage(pdx::Message& message); pdx::Status<void> OnSetAttributes( pdx::Message& message, const display::SurfaceAttributes& attributes); pdx::Status<display::SurfaceInfo> OnGetSurfaceInfo(pdx::Message& message); DisplayService* service_; SurfaceType surface_type_; int surface_id_; int process_id_; int user_id_; display::SurfaceAttributes attributes_; display::SurfaceUpdateFlags update_flags_ = display::SurfaceUpdateFlags::None; // Subset of attributes that may be interpreted by the display service. bool visible_ = false; int z_order_ = 0; DisplaySurface(const DisplaySurface&) = delete; void operator=(const DisplaySurface&) = delete; }; class ApplicationDisplaySurface : public DisplaySurface { public: ApplicationDisplaySurface(DisplayService* service, int surface_id, int process_id, int user_id, const display::SurfaceAttributes& attributes) : DisplaySurface(service, SurfaceType::Application, surface_id, process_id, user_id, attributes) {} std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id); std::vector<int32_t> GetQueueIds() const override; private: pdx::Status<pdx::LocalChannelHandle> OnCreateQueue( pdx::Message& message, size_t meta_size_bytes) override; void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) override; std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_; }; class DirectDisplaySurface : public DisplaySurface { public: DirectDisplaySurface(DisplayService* service, int surface_id, int process_id, int user_id, const display::SurfaceAttributes& attributes) : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id, user_id, attributes), acquired_buffers_(kMaxPostedBuffers) {} bool IsBufferAvailable(); bool IsBufferPosted(); AcquiredBuffer AcquireCurrentBuffer(); // Get the newest buffer. Up to one buffer will be skipped. If a buffer is // skipped, it will be stored in skipped_buffer if non null. AcquiredBuffer AcquireNewestAvailableBuffer(AcquiredBuffer* skipped_buffer); private: pdx::Status<pdx::LocalChannelHandle> OnCreateQueue( pdx::Message& message, size_t meta_size_bytes) override; void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) override; // The capacity of the pending buffer queue. Should be enough to hold all the // buffers of this DisplaySurface, although in practice only 1 or 2 frames // will be pending at a time. static constexpr int kSurfaceBufferMaxCount = 4; static constexpr int kSurfaceViewMaxCount = 4; static constexpr int kMaxPostedBuffers = kSurfaceBufferMaxCount * kSurfaceViewMaxCount; // Returns whether a frame is available without locking the mutex. bool IsFrameAvailableNoLock() const; // Dequeue all available buffers from the consumer queue. void DequeueBuffersLocked(); // In a triple-buffered surface, up to kMaxPostedBuffers buffers may be // posted and pending. RingBuffer<AcquiredBuffer> acquired_buffers_; std::shared_ptr<ConsumerQueue> direct_queue_; }; } // namespace dvr } // namespace android #endif // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_