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