blob: 001006bf7a446d54ba9f32a367e2e66813d49a58 [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
Greg Hartmanca7fb192017-09-28 16:14:12 -070019#include "common/vsoc/lib/typed_region_view.h"
Jorge E. Moreiraccd57452017-09-29 15:19:07 -070020#include "host/frontend/vnc_server/vnc_utils.h"
Greg Hartmand072a342017-12-05 20:27:40 -080021#include "host/libs/config/host_config.h"
22#include "host/vsoc/lib/gralloc_buffer_region_view.h"
Greg Hartmanca7fb192017-09-28 16:14:12 -070023
Greg Hartman153b1062017-11-11 12:09:21 -080024using cvd::vnc::SimulatedHWComposer;
Greg Hartmand072a342017-12-05 20:27:40 -080025using vsoc::gralloc::GrallocBufferRegionView;
Jorge E. Moreira24307012017-09-22 14:35:21 -070026
27SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
28 :
29#ifdef FUZZ_TEST_VNC
30 engine_{std::random_device{}()},
31#endif
Jorge E. Moreira24307012017-09-22 14:35:21 -070032 bb_{bb},
33 stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements) {
Greg Hartmand072a342017-12-05 20:27:40 -080034 stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
Jorge E. Moreira24307012017-09-22 14:35:21 -070035}
36
37SimulatedHWComposer::~SimulatedHWComposer() {
38 close();
39 stripe_maker_.join();
Jorge E. Moreira24307012017-09-22 14:35:21 -070040}
41
Greg Hartman153b1062017-11-11 12:09:21 -080042cvd::vnc::Stripe SimulatedHWComposer::GetNewStripe() {
Jorge E. Moreira24307012017-09-22 14:35:21 -070043 auto s = stripes_.Pop();
44#ifdef FUZZ_TEST_VNC
45 if (random_(engine_)) {
46 usleep(7000);
47 stripes_.Push(std::move(s));
48 s = stripes_.Pop();
49 }
50#endif
51 return s;
52}
53
54bool SimulatedHWComposer::closed() {
55 std::lock_guard<std::mutex> guard(m_);
56 return closed_;
57}
58
59void SimulatedHWComposer::close() {
60 std::lock_guard<std::mutex> guard(m_);
61 closed_ = true;
62}
63
64// Assuming the number of stripes is less than half the size of the queue
65// this will be safe as the newest stripes won't be lost. In the real
66// hwcomposer, where stripes are coming in a different order, the full
67// queue case would probably need a different approach to be safe.
68void SimulatedHWComposer::EraseHalfOfElements(
69 ThreadSafeQueue<Stripe>::QueueImpl* q) {
70 q->erase(q->begin(), std::next(q->begin(), kMaxQueueElements / 2));
71}
72
73void SimulatedHWComposer::MakeStripes() {
74 std::uint32_t previous_seq_num{};
75 auto screen_height = ActualScreenHeight();
76 Message raw_screen;
77 std::uint64_t stripe_seq_num = 1;
78 while (!closed()) {
79 bb_->WaitForAtLeastOneClientConnection();
Greg Hartmanca7fb192017-09-28 16:14:12 -070080 vsoc_reg_off_t buffer_offset =
Greg Hartman86b114a2017-11-03 21:04:14 -070081 GetFBBroadcastRegionView()->WaitForNewFrameSince(&previous_seq_num);
Jorge E. Moreira24307012017-09-22 14:35:21 -070082
83 const auto* frame_start =
Greg Hartmand072a342017-12-05 20:27:40 -080084 GrallocBufferRegionView::GetInstance(vsoc::GetDomain().c_str())
85 ->OffsetToBufferPtr(buffer_offset);
Jorge E. Moreira24307012017-09-22 14:35:21 -070086 raw_screen.assign(frame_start, frame_start + ScreenSizeInBytes());
87
88 for (int i = 0; i < kNumStripes; ++i) {
89 ++stripe_seq_num;
90 std::uint16_t y = (screen_height / kNumStripes) * i;
91
92 // Last frames on the right and/or bottom handle extra pixels
93 // when a screen dimension is not evenly divisible by Frame::kNumSlots.
94 std::uint16_t height =
95 screen_height / kNumStripes +
96 (i + 1 == kNumStripes ? screen_height % kNumStripes : 0);
97 const auto* raw_start =
98 &raw_screen[y * ActualScreenWidth() * BytesPerPixel()];
99 const auto* raw_end =
100 raw_start + (height * ActualScreenWidth() * BytesPerPixel());
101 // creating a named object and setting individual data members in order
102 // to make klp happy
103 // TODO (haining) construct this inside the call when not compiling
104 // on klp
105 Stripe s{};
106 s.index = i;
107 s.frame_id = previous_seq_num;
108 s.x = 0;
109 s.y = y;
110 s.width = ActualScreenWidth();
111 s.height = height;
112 s.raw_data.assign(raw_start, raw_end);
113 s.seq_number = StripeSeqNumber{stripe_seq_num};
114 s.orientation = ScreenOrientation::Portrait;
115 stripes_.Push(std::move(s));
116 }
117 }
118}
119
Greg Hartman70753782017-09-28 16:12:43 -0700120int SimulatedHWComposer::NumberOfStripes() { return kNumStripes; }