You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
6.5 KiB
189 lines
6.5 KiB
#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);
|
|
|
|
// 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, const ProducerQueueConfig& config) = 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)
|
|
: DisplaySurface(service, SurfaceType::Application, surface_id,
|
|
process_id, user_id) {}
|
|
|
|
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, const ProducerQueueConfig& config) override;
|
|
void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue,
|
|
int events) override;
|
|
|
|
// Accessed by both message dispatch thread and epoll event thread.
|
|
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)
|
|
: DisplaySurface(service, SurfaceType::Direct, surface_id, process_id,
|
|
user_id),
|
|
acquired_buffers_(kMaxPostedBuffers),
|
|
metadata_(nullptr) {}
|
|
std::vector<int32_t> GetQueueIds() const override;
|
|
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, const ProducerQueueConfig& config) 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_;
|
|
|
|
// Stores metadata when it dequeue buffers from consumer queue.
|
|
std::unique_ptr<uint8_t[]> metadata_;
|
|
};
|
|
|
|
} // namespace dvr
|
|
} // namespace android
|
|
|
|
#endif // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_
|