blob: 7a94454b503bd3b2b6e27302523fb17e5c5abc51 [file] [log] [blame]
Jorge E. Moreiraccd57452017-09-29 15:19:07 -07001/*
2 * Copyright (C) 2017 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 "host/frontend/vnc_server/simulated_hw_composer.h"
Jorge E. Moreira24307012017-09-22 14:35:21 -070018
Jorge E. Moreiraccd57452017-09-29 15:19:07 -070019#include "host/frontend/vnc_server/vnc_utils.h"
Jorge E. Moreira08ea9e42018-05-24 14:17:51 -070020#include "host/libs/config/cuttlefish_config.h"
Greg Hartmanca7fb192017-09-28 16:14:12 -070021
Greg Hartman153b1062017-11-11 12:09:21 -080022using cvd::vnc::SimulatedHWComposer;
Cody Schuffelen134ff032019-11-22 00:25:32 -080023using vsoc::screen::ScreenRegionView;
Jorge E. Moreira24307012017-09-22 14:35:21 -070024
25SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
26 :
27#ifdef FUZZ_TEST_VNC
28 engine_{std::random_device{}()},
29#endif
Jorge E. Moreira24307012017-09-22 14:35:21 -070030 bb_{bb},
31 stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements) {
Greg Hartmand072a342017-12-05 20:27:40 -080032 stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
Jorge E. Moreira24307012017-09-22 14:35:21 -070033}
34
35SimulatedHWComposer::~SimulatedHWComposer() {
36 close();
37 stripe_maker_.join();
Jorge E. Moreira24307012017-09-22 14:35:21 -070038}
39
Greg Hartman153b1062017-11-11 12:09:21 -080040cvd::vnc::Stripe SimulatedHWComposer::GetNewStripe() {
Jorge E. Moreira24307012017-09-22 14:35:21 -070041 auto s = stripes_.Pop();
42#ifdef FUZZ_TEST_VNC
43 if (random_(engine_)) {
44 usleep(7000);
45 stripes_.Push(std::move(s));
46 s = stripes_.Pop();
47 }
48#endif
49 return s;
50}
51
52bool SimulatedHWComposer::closed() {
53 std::lock_guard<std::mutex> guard(m_);
54 return closed_;
55}
56
57void SimulatedHWComposer::close() {
58 std::lock_guard<std::mutex> guard(m_);
59 closed_ = true;
60}
61
62// Assuming the number of stripes is less than half the size of the queue
63// this will be safe as the newest stripes won't be lost. In the real
64// hwcomposer, where stripes are coming in a different order, the full
65// queue case would probably need a different approach to be safe.
66void SimulatedHWComposer::EraseHalfOfElements(
67 ThreadSafeQueue<Stripe>::QueueImpl* q) {
68 q->erase(q->begin(), std::next(q->begin(), kMaxQueueElements / 2));
69}
70
71void SimulatedHWComposer::MakeStripes() {
72 std::uint32_t previous_seq_num{};
73 auto screen_height = ActualScreenHeight();
74 Message raw_screen;
75 std::uint64_t stripe_seq_num = 1;
76 while (!closed()) {
77 bb_->WaitForAtLeastOneClientConnection();
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -080078 int buffer_idx = screen_connector_->WaitForNewFrameSince(&previous_seq_num);
Jorge E. Moreiraa5810902018-02-13 11:50:34 -080079 const char* frame_start =
Jorge E. Moreirac87c2c72019-03-06 16:12:23 -080080 static_cast<char*>(screen_connector_->GetBuffer(buffer_idx));
Jorge E. Moreira24307012017-09-22 14:35:21 -070081 raw_screen.assign(frame_start, frame_start + ScreenSizeInBytes());
82
83 for (int i = 0; i < kNumStripes; ++i) {
84 ++stripe_seq_num;
85 std::uint16_t y = (screen_height / kNumStripes) * i;
86
87 // Last frames on the right and/or bottom handle extra pixels
88 // when a screen dimension is not evenly divisible by Frame::kNumSlots.
89 std::uint16_t height =
90 screen_height / kNumStripes +
91 (i + 1 == kNumStripes ? screen_height % kNumStripes : 0);
92 const auto* raw_start =
93 &raw_screen[y * ActualScreenWidth() * BytesPerPixel()];
94 const auto* raw_end =
95 raw_start + (height * ActualScreenWidth() * BytesPerPixel());
96 // creating a named object and setting individual data members in order
97 // to make klp happy
98 // TODO (haining) construct this inside the call when not compiling
99 // on klp
100 Stripe s{};
101 s.index = i;
102 s.frame_id = previous_seq_num;
103 s.x = 0;
104 s.y = y;
105 s.width = ActualScreenWidth();
Jorge E. Moreiraf1630092019-04-05 16:14:03 -0700106 s.stride = ActualScreenStride();
Jorge E. Moreira24307012017-09-22 14:35:21 -0700107 s.height = height;
108 s.raw_data.assign(raw_start, raw_end);
109 s.seq_number = StripeSeqNumber{stripe_seq_num};
110 s.orientation = ScreenOrientation::Portrait;
111 stripes_.Push(std::move(s));
112 }
113 }
114}
115
Greg Hartman70753782017-09-28 16:12:43 -0700116int SimulatedHWComposer::NumberOfStripes() { return kNumStripes; }