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