• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <map>
20 
21 #include "common/libs/fs/shared_fd.h"
22 #include "common/libs/utils/result.h"
23 
24 namespace cuttlefish {
25 
26 // This header is allocated / placed at start of IPC ringbuffer. Intention of
27 // elements here is to allow to compute the valid read/write address for
28 // current frame from an external process.
29 struct DisplayRingBufferHeader {
30   volatile std::uint32_t display_width_;
31   volatile std::uint32_t display_height_;
32   volatile std::uint32_t bpp_;
33   std::atomic<std::uint32_t> last_valid_frame_index_;
34 
35   void set(std::uint32_t w, std::uint32_t h, std::uint32_t bpp,
36            std::uint32_t index);
37 };
38 
39 class DisplayRingBuffer {
40  public:
41   ~DisplayRingBuffer();
42   static Result<std::unique_ptr<DisplayRingBuffer>> Create(
43       const std::string& name, int size);
44   // Allowing optional in the case the buffer doesn't yet exist.
45   static std::optional<std::unique_ptr<DisplayRingBuffer>> ShmemGet(
46       const std::string& name, int size);
47 
48   void* GetAddress();
49 
50   std::uint8_t* WriteNextFrame(std::uint8_t* frame_data, int size);
51   std::uint8_t* CurrentFrame();
52   std::uint8_t* ComputeFrameAddressForIndex(std::uint32_t index);
53 
54  private:
55   DisplayRingBuffer(void* addr, std::string name, bool owned, ScopedMMap shm);
56 
57   DisplayRingBufferHeader* header_;
58   void* addr_;
59   std::string name_;
60   bool owned_;
61   ScopedMMap shm_;
62 };
63 
64 class DisplayRingBufferManager {
65  public:
66   DisplayRingBufferManager(int vm_index, std::string group_uuid);
67   Result<void> CreateLocalDisplayBuffer(int vm_index, int display_index,
68                                         int display_width, int display_height);
69   std::uint8_t* WriteFrame(int vm_index, int display_index,
70                            std::uint8_t* frame_data, int size);
71   std::uint8_t* ReadFrame(int vm_index, int display_index, int frame_width,
72                           int frame_height);
73 
74  private:
75   std::string MakeLayerName(int display_index, int vm_index = -1);
76   int local_group_index_;  // Index of the current process in the cluster of VMs
77   std::string group_uuid_;  // Unique identifier for entire VM cluster
78   // All IPC buffers are cached here for speed, to prevent OS from
79   // continually remapping RAM every read/write request.
80   std::map<std::pair<int, int>, std::unique_ptr<DisplayRingBuffer>>
81       display_buffer_cache_;
82 };
83 
84 }  // namespace cuttlefish