• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #include "base_composer.h"
18 
19 #include <string.h>
20 
21 #include <cutils/properties.h>
22 #include <hardware/gralloc.h>
23 #include <log/log.h>
24 
25 #include <common/libs/utils/size_utils.h>
26 #include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h"
27 
28 namespace cvd {
29 
BaseComposer(int64_t vsync_base_timestamp)30 BaseComposer::BaseComposer(int64_t vsync_base_timestamp)
31     : vsync_base_timestamp_(vsync_base_timestamp) {
32   vsync_period_ns_ = 1000000000 / frame_buffer_.refresh_rate();
33   hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
34                 reinterpret_cast<const hw_module_t**>(&gralloc_module_));
35 }
36 
~BaseComposer()37 BaseComposer::~BaseComposer() {}
38 
Dump(char * buff __unused,int buff_len __unused)39 void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {}
40 
PostFrameBufferTarget(buffer_handle_t buffer_handle)41 int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) {
42   int fb_index = frame_buffer_.NextScreenBuffer();
43   void* frame_buffer = frame_buffer_.GetBuffer(fb_index);
44   const private_handle_t* p_handle =
45       reinterpret_cast<const private_handle_t*>(buffer_handle);
46   void* buffer;
47   int retval = gralloc_module_->lock(gralloc_module_, buffer_handle,
48                                      GRALLOC_USAGE_SW_READ_OFTEN, 0, 0,
49                                      p_handle->x_res, p_handle->y_res, &buffer);
50   if (retval != 0) {
51     ALOGE("Got error code %d from lock function", retval);
52     return -1;
53   }
54   memcpy(frame_buffer, buffer, frame_buffer_.buffer_size());
55   frame_buffer_.Broadcast(fb_index);
56   return 0;
57 }  // namespace cvd
58 
PrepareLayers(size_t num_layers,vsoc_hwc_layer * layers)59 int BaseComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) {
60   // find unsupported overlays
61   for (size_t i = 0; i < num_layers; i++) {
62     if (IS_TARGET_FRAMEBUFFER(layers[i].compositionType)) {
63       continue;
64     }
65     layers[i].compositionType = HWC_FRAMEBUFFER;
66   }
67   return 0;
68 }
69 
SetLayers(size_t num_layers,vsoc_hwc_layer * layers)70 int BaseComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) {
71   for (size_t idx = 0; idx < num_layers; idx++) {
72     if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) {
73       return PostFrameBufferTarget(layers[idx].handle);
74     }
75   }
76   return -1;
77 }
78 
FrameBuffer()79 FrameBuffer::FrameBuffer()
80     : screen_server_(cvd::SharedFD::VsockClient(
81           2, property_get_int32("ro.boot.vsock_frames_port", 5580),
82           SOCK_STREAM)),
83       broadcast_thread_([this]() { BroadcastLoop(); }) {
84   if (screen_server_->IsOpen()) {
85     // TODO(b/128842613): Get this info from the configuration server
86     int32_t screen_params[4];
87     auto res = screen_server_->Read(screen_params, sizeof(screen_params));
88     if (res == sizeof(screen_params)) {
89       x_res_ = screen_params[0];
90       y_res_ = screen_params[1];
91       dpi_ = screen_params[2];
92       refresh_rate_ = screen_params[3];
93     } else {
94       LOG(ERROR) << "Unable to get screen configuration parameters from screen "
95                  << "server (" << res << "): " << screen_server_->StrError();
96     }
97   } else {
98     LOG(ERROR) << "Unable to connect to screen server: "
99                << screen_server_->StrError();
100   }
101   // This needs to happen no matter what, otherwise there won't be a buffer for
102   // the set calls to compose on.
103   inner_buffer_ = std::vector<char>(FrameBuffer::buffer_size() * 8);
104 }
105 
~FrameBuffer()106 FrameBuffer::~FrameBuffer() {
107   running_ = false;
108   broadcast_thread_.join();
109 }
110 
NextScreenBuffer()111 int FrameBuffer::NextScreenBuffer() {
112   int num_buffers = inner_buffer_.size() / buffer_size();
113   last_frame_buffer_ =
114       num_buffers > 0 ? (last_frame_buffer_ + 1) % num_buffers : -1;
115   return last_frame_buffer_;
116 }
117 
BroadcastLoop()118 void FrameBuffer::BroadcastLoop() {
119   if (!screen_server_->IsOpen()) {
120     LOG(ERROR) << "Broadcaster thread exiting due to no connection to screen"
121                << " server. Compositions will occur, but frames won't be sent"
122                << " anywhere";
123     return;
124   }
125   int32_t current_seq = 0;
126   int32_t current_offset;
127   while (running_) {
128     {
129       std::unique_lock<std::mutex> lock(mutex_);
130       while (current_seq == current_seq_) {
131         cond_var_.wait(lock);
132       }
133       current_offset = current_offset_;
134       current_seq = current_seq_;
135     }
136     int32_t size = buffer_size();
137     screen_server_->Write(&size, sizeof(size));
138     auto buff = static_cast<char*>(GetBuffer(current_offset));
139     while (size > 0) {
140       auto written = screen_server_->Write(buff, size);
141       size -= written;
142       buff += written;
143     }
144   }
145 }
146 
Broadcast(int32_t offset)147 void FrameBuffer::Broadcast(int32_t offset) {
148   std::lock_guard<std::mutex> lock(mutex_);
149   current_offset_ = offset;
150   current_seq_++;
151   cond_var_.notify_all();
152 }
GetBuffer(int fb_index)153 void* FrameBuffer::GetBuffer(int fb_index) {
154   return &inner_buffer_[buffer_size() * fb_index];
155 }
buffer_size()156 size_t FrameBuffer::buffer_size() {
157   return (line_length() * y_res()) + 4;
158 }
x_res()159 int32_t FrameBuffer::x_res() { return x_res_; }
y_res()160 int32_t FrameBuffer::y_res() { return y_res_; }
line_length()161 int32_t FrameBuffer::line_length() {
162   return cvd::AlignToPowerOf2(x_res() * bytes_per_pixel(), 4);
163 }
bytes_per_pixel()164 int32_t FrameBuffer::bytes_per_pixel() { return 4; }
dpi()165 int32_t FrameBuffer::dpi() { return dpi_; }
refresh_rate()166 int32_t FrameBuffer::refresh_rate() { return refresh_rate_; }
167 
168 }  // namespace cvd
169