• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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