1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_THREAD_H_
6 #define UI_OZONE_PLATFORM_DRM_GPU_DRM_THREAD_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 
12 #include "base/files/file.h"
13 #include "base/files/scoped_file.h"
14 #include "base/macros.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/threading/thread.h"
17 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
18 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
19 #include "mojo/public/cpp/bindings/pending_receiver.h"
20 #include "mojo/public/cpp/bindings/receiver_set.h"
21 #include "ui/display/types/display_configuration_params.h"
22 #include "ui/gfx/native_pixmap_handle.h"
23 #include "ui/gfx/native_widget_types.h"
24 #include "ui/gfx/vsync_provider.h"
25 #include "ui/ozone/platform/drm/common/display_types.h"
26 #include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
27 #include "ui/ozone/public/mojom/device_cursor.mojom.h"
28 #include "ui/ozone/public/mojom/drm_device.mojom.h"
29 #include "ui/ozone/public/overlay_surface_candidate.h"
30 #include "ui/ozone/public/swap_completion_callback.h"
31 
32 namespace base {
33 class FilePath;
34 }
35 
36 namespace display {
37 struct GammaRampRGBEntry;
38 }  // namespace display
39 
40 namespace gfx {
41 class Point;
42 class Rect;
43 }  // namespace gfx
44 
45 namespace ui {
46 
47 class DrmDeviceManager;
48 class DrmFramebuffer;
49 class DrmGpuDisplayManager;
50 class GbmBuffer;
51 class ScreenManager;
52 
53 struct DrmOverlayPlane;
54 
55 // Holds all the DRM related state and performs all DRM related operations.
56 //
57 // The DRM thread is used to insulate DRM operations from potential blocking
58 // behaviour on the GPU main thread in order to reduce the potential for jank
59 // (for example jank in the cursor if the GPU main thread is performing heavy
60 // operations). The inverse is also true as blocking operations on the DRM
61 // thread (such as modesetting) no longer block the GPU main thread.
62 class DrmThread : public base::Thread,
63                   public ozone::mojom::DeviceCursor,
64                   public ozone::mojom::DrmDevice {
65  public:
66   using OverlayCapabilitiesCallback =
67       base::OnceCallback<void(gfx::AcceleratedWidget,
68                               const std::vector<OverlaySurfaceCandidate>&,
69                               const std::vector<OverlayStatus>&)>;
70 
71   DrmThread();
72   ~DrmThread() override;
73 
74   void Start(base::OnceClosure receiver_completer,
75              std::unique_ptr<DrmDeviceGenerator> device_generator);
76 
77   // Runs |task| once a DrmDevice is registered. |done|
78   // will be signaled if it's not null.
79   void RunTaskAfterDeviceReady(base::OnceClosure task,
80                                base::WaitableEvent* done);
81 
82   // Must be called on the DRM thread. All methods for use from the GPU thread.
83   // DrmThreadProxy (on GPU)thread) is the client for these methods.
84   void CreateBuffer(gfx::AcceleratedWidget widget,
85                     const gfx::Size& size,
86                     const gfx::Size& framebuffer_size,
87                     gfx::BufferFormat format,
88                     gfx::BufferUsage usage,
89                     uint32_t flags,
90                     std::unique_ptr<GbmBuffer>* buffer,
91                     scoped_refptr<DrmFramebuffer>* framebuffer);
92   using CreateBufferAsyncCallback =
93       base::OnceCallback<void(std::unique_ptr<GbmBuffer>,
94                               scoped_refptr<DrmFramebuffer>)>;
95   void CreateBufferAsync(gfx::AcceleratedWidget widget,
96                          const gfx::Size& size,
97                          gfx::BufferFormat format,
98                          gfx::BufferUsage usage,
99                          uint32_t flags,
100                          CreateBufferAsyncCallback callback);
101   void CreateBufferFromHandle(gfx::AcceleratedWidget widget,
102                               const gfx::Size& size,
103                               gfx::BufferFormat format,
104                               gfx::NativePixmapHandle handle,
105                               std::unique_ptr<GbmBuffer>* buffer,
106                               scoped_refptr<DrmFramebuffer>* framebuffer);
107   void SetClearOverlayCacheCallback(base::RepeatingClosure callback);
108   void AddDrmDeviceReceiver(
109       mojo::PendingReceiver<ozone::mojom::DrmDevice> receiver);
110 
111   void SetColorSpace(gfx::AcceleratedWidget widget,
112                      const gfx::ColorSpace& color_space);
113 
114   // Verifies if the display controller can successfully scanout the given set
115   // of OverlaySurfaceCandidates and return the status associated with each
116   // candidate.
117   void CheckOverlayCapabilities(
118       gfx::AcceleratedWidget widget,
119       const std::vector<OverlaySurfaceCandidate>& candidates,
120       OverlayCapabilitiesCallback callback);
121 
122   // Similar to CheckOverlayCapabilities() but stores the result in |result|
123   // instead of running a callback.
124   void CheckOverlayCapabilitiesSync(
125       gfx::AcceleratedWidget widget,
126       const std::vector<OverlaySurfaceCandidate>& candidates,
127       std::vector<OverlayStatus>* result);
128 
129   // DrmWindowProxy (on GPU thread) is the client for these methods.
130   void SchedulePageFlip(gfx::AcceleratedWidget widget,
131                         std::vector<DrmOverlayPlane> planes,
132                         SwapCompletionOnceCallback submission_callback,
133                         PresentationOnceCallback presentation_callback);
134 
135   void IsDeviceAtomic(gfx::AcceleratedWidget widget, bool* is_atomic);
136 
137   // ozone::mojom::DrmDevice
138   void CreateWindow(gfx::AcceleratedWidget widget,
139                     const gfx::Rect& initial_bounds) override;
140   void DestroyWindow(gfx::AcceleratedWidget widget) override;
141   void SetWindowBounds(gfx::AcceleratedWidget widget,
142                        const gfx::Rect& bounds) override;
143   void TakeDisplayControl(base::OnceCallback<void(bool)> callback) override;
144   void RelinquishDisplayControl(
145       base::OnceCallback<void(bool)> callback) override;
146   void RefreshNativeDisplays(
147       base::OnceCallback<void(MovableDisplaySnapshots)> callback) override;
148   void AddGraphicsDevice(const base::FilePath& path, base::File file) override;
149   void RemoveGraphicsDevice(const base::FilePath& path) override;
150   void ConfigureNativeDisplays(
151       const std::vector<display::DisplayConfigurationParams>& config_requests,
152       ConfigureNativeDisplaysCallback callback) override;
153   void GetHDCPState(int64_t display_id,
154                     base::OnceCallback<void(int64_t,
155                                             bool,
156                                             display::HDCPState,
157                                             display::ContentProtectionMethod)>
158                         callback) override;
159   void SetHDCPState(int64_t display_id,
160                     display::HDCPState state,
161                     display::ContentProtectionMethod protection_method,
162                     base::OnceCallback<void(int64_t, bool)> callback) override;
163   void SetColorMatrix(int64_t display_id,
164                       const std::vector<float>& color_matrix) override;
165   void SetGammaCorrection(
166       int64_t display_id,
167       const std::vector<display::GammaRampRGBEntry>& degamma_lut,
168       const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
169   void SetPrivacyScreen(int64_t display_id, bool enabled) override;
170   void GetDeviceCursor(
171       mojo::PendingAssociatedReceiver<ozone::mojom::DeviceCursor> receiver)
172       override;
173 
174   // ozone::mojom::DeviceCursor
175   void SetCursor(gfx::AcceleratedWidget widget,
176                  const std::vector<SkBitmap>& bitmaps,
177                  const gfx::Point& location,
178                  int32_t frame_delay_ms) override;
179   void MoveCursor(gfx::AcceleratedWidget widget,
180                   const gfx::Point& location) override;
181 
182   // base::Thread:
183   void Init() override;
184 
185  private:
186   struct TaskInfo {
187     base::OnceClosure task;
188     base::WaitableEvent* done;
189 
190     TaskInfo(base::OnceClosure task, base::WaitableEvent* done);
191     TaskInfo(TaskInfo&& other);
192     ~TaskInfo();
193   };
194 
195   void OnPlanesReadyForPageFlip(gfx::AcceleratedWidget widget,
196                                 SwapCompletionOnceCallback submission_callback,
197                                 PresentationOnceCallback presentation_callback,
198                                 std::vector<DrmOverlayPlane> planes);
199 
200   // Called when a DrmDevice or DrmWindow is created. Runs tasks that are now
201   // unblocked.
202   void ProcessPendingTasks();
203 
204   std::unique_ptr<DrmDeviceManager> device_manager_;
205   std::unique_ptr<ScreenManager> screen_manager_;
206   std::unique_ptr<DrmGpuDisplayManager> display_manager_;
207 
208   base::OnceClosure complete_early_receiver_requests_;
209 
210   // The mojo implementation requires an AssociatedReceiverSet because the
211   // DrmThread serves requests from two different client threads.
212   mojo::AssociatedReceiverSet<ozone::mojom::DeviceCursor> cursor_receivers_;
213 
214   // This is a ReceiverSet because the regular Receiver causes the sequence
215   // checker in InterfaceEndpointClient to fail during teardown.
216   // TODO(samans): Figure out why.
217   mojo::ReceiverSet<ozone::mojom::DrmDevice> drm_receivers_;
218 
219   // The AcceleratedWidget from the last call to CreateWindow.
220   gfx::AcceleratedWidget last_created_window_ = gfx::kNullAcceleratedWidget;
221 
222   // The tasks that are blocked on a DrmDevice becoming available.
223   std::vector<TaskInfo> pending_tasks_;
224 
225   // Holds the DrmDeviceGenerator that DrmDeviceManager will use. Will be passed
226   // on to DrmDeviceManager after the thread starts.
227   std::unique_ptr<DrmDeviceGenerator> device_generator_;
228 
229   base::WeakPtrFactory<DrmThread> weak_ptr_factory_{this};
230 
231   DISALLOW_COPY_AND_ASSIGN(DrmThread);
232 };
233 
234 }  // namespace ui
235 
236 #endif  // UI_OZONE_PLATFORM_DRM_GPU_DRM_THREAD_H_
237