1 // Copyright 2019 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_BASE_X_X11_SHM_IMAGE_POOL_H_
6 #define UI_BASE_X_X11_SHM_IMAGE_POOL_H_
7 
8 #include <cstring>
9 #include <list>
10 #include <vector>
11 
12 #include "base/callback_forward.h"
13 #include "base/component_export.h"
14 #include "base/macros.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/sequence_checker.h"
17 #include "third_party/skia/include/core/SkBitmap.h"
18 #include "third_party/skia/include/core/SkCanvas.h"
19 #include "ui/base/x/x11_util.h"
20 #include "ui/events/platform/x11/x11_event_source.h"
21 #include "ui/gfx/geometry/size.h"
22 #include "ui/gfx/x/event.h"
23 #include "ui/gfx/x/shm.h"
24 
25 namespace ui {
26 
27 // Creates XImages backed by shared memory that will be shared with the X11
28 // server for processing.
COMPONENT_EXPORT(UI_BASE_X)29 class COMPONENT_EXPORT(UI_BASE_X) XShmImagePool : public XEventDispatcher {
30  public:
31   XShmImagePool(x11::Connection* connection,
32                 x11::Drawable drawable,
33                 x11::VisualId visual,
34                 int depth,
35                 std::size_t max_frames_pending,
36                 bool enable_multibuffering);
37 
38   ~XShmImagePool() override;
39 
40   bool Resize(const gfx::Size& pixel_size);
41 
42   // Is XSHM supported by the server and are the shared buffers ready for use?
43   bool Ready();
44 
45   // Obtain state for the current frame.
46   SkBitmap& CurrentBitmap();
47   SkCanvas* CurrentCanvas();
48   x11::Shm::Seg CurrentSegment();
49 
50   // Switch to the next cached frame.  CurrentBitmap() and CurrentImage() will
51   // change to reflect the new frame.
52   void SwapBuffers(base::OnceCallback<void(const gfx::Size&)> callback);
53 
54  protected:
55   void DispatchShmCompletionEvent(x11::Shm::CompletionEvent event);
56 
57  private:
58   friend class base::RefCountedThreadSafe<XShmImagePool>;
59 
60   struct FrameState {
61     FrameState();
62     ~FrameState();
63 
64     x11::Shm::Seg shmseg{};
65     int shmid = 0;
66     void* shmaddr = nullptr;
67     bool shmem_attached_to_server = false;
68     SkBitmap bitmap;
69     std::unique_ptr<SkCanvas> canvas;
70   };
71 
72   struct SwapClosure {
73     SwapClosure();
74     ~SwapClosure();
75 
76     base::OnceClosure closure;
77     x11::Shm::Seg shmseg{};
78   };
79 
80   // XEventDispatcher:
81   bool DispatchXEvent(x11::Event* xev) override;
82 
83   void Cleanup();
84 
85   x11::Connection* const connection_;
86   const x11::Drawable drawable_;
87   const x11::VisualId visual_;
88   const int depth_;
89   const bool enable_multibuffering_;
90 
91   bool ready_ = false;
92   gfx::Size pixel_size_;
93   std::size_t frame_bytes_ = 0;
94   std::vector<FrameState> frame_states_;
95   std::size_t current_frame_index_ = 0;
96   std::list<SwapClosure> swap_closures_;
97 
98   SEQUENCE_CHECKER(sequence_checker_);
99 
100   DISALLOW_COPY_AND_ASSIGN(XShmImagePool);
101 };
102 
103 }  // namespace ui
104 
105 #endif  // UI_BASE_X_X11_SHM_IMAGE_POOL_H_
106