1 /*
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"
18
19 #include "host/frontend/vnc_server/vnc_utils.h"
20 #include "host/libs/config/cuttlefish_config.h"
21
22 using cvd::vnc::SimulatedHWComposer;
23 using vsoc::screen::ScreenRegionView;
24
SimulatedHWComposer(BlackBoard * bb)25 SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
26 :
27 #ifdef FUZZ_TEST_VNC
28 engine_{std::random_device{}()},
29 #endif
30 bb_{bb},
31 stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements) {
32 stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
33 }
34
~SimulatedHWComposer()35 SimulatedHWComposer::~SimulatedHWComposer() {
36 close();
37 stripe_maker_.join();
38 }
39
GetNewStripe()40 cvd::vnc::Stripe SimulatedHWComposer::GetNewStripe() {
41 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
closed()52 bool SimulatedHWComposer::closed() {
53 std::lock_guard<std::mutex> guard(m_);
54 return closed_;
55 }
56
close()57 void 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.
EraseHalfOfElements(ThreadSafeQueue<Stripe>::QueueImpl * q)66 void SimulatedHWComposer::EraseHalfOfElements(
67 ThreadSafeQueue<Stripe>::QueueImpl* q) {
68 q->erase(q->begin(), std::next(q->begin(), kMaxQueueElements / 2));
69 }
70
MakeStripes()71 void 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();
78 int buffer_idx = screen_connector_->WaitForNewFrameSince(&previous_seq_num);
79 const char* frame_start =
80 static_cast<char*>(screen_connector_->GetBuffer(buffer_idx));
81 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();
106 s.stride = ActualScreenStride();
107 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
NumberOfStripes()116 int SimulatedHWComposer::NumberOfStripes() { return kNumStripes; }
117