Home | History | Annotate | Download | only in vnc_server
      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 #include "common/vsoc/lib/screen_region_view.h"
     22 
     23 using cvd::vnc::SimulatedHWComposer;
     24 using vsoc::screen::ScreenRegionView;
     25 
     26 SimulatedHWComposer::SimulatedHWComposer(BlackBoard* bb)
     27     :
     28 #ifdef FUZZ_TEST_VNC
     29       engine_{std::random_device{}()},
     30 #endif
     31       bb_{bb},
     32       stripes_(kMaxQueueElements, &SimulatedHWComposer::EraseHalfOfElements) {
     33   stripe_maker_ = std::thread(&SimulatedHWComposer::MakeStripes, this);
     34 }
     35 
     36 SimulatedHWComposer::~SimulatedHWComposer() {
     37   close();
     38   stripe_maker_.join();
     39 }
     40 
     41 cvd::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 
     53 bool SimulatedHWComposer::closed() {
     54   std::lock_guard<std::mutex> guard(m_);
     55   return closed_;
     56 }
     57 
     58 void 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.
     67 void SimulatedHWComposer::EraseHalfOfElements(
     68     ThreadSafeQueue<Stripe>::QueueImpl* q) {
     69   q->erase(q->begin(), std::next(q->begin(), kMaxQueueElements / 2));
     70 }
     71 
     72 void 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   auto screen_view = ScreenRegionView::GetInstance(vsoc::GetDomain().c_str());
     78   while (!closed()) {
     79     bb_->WaitForAtLeastOneClientConnection();
     80     int buffer_idx = screen_view->WaitForNewFrameSince(&previous_seq_num);
     81     const char* frame_start =
     82         static_cast<char*>(screen_view->GetBuffer(buffer_idx));
     83     raw_screen.assign(frame_start, frame_start + ScreenSizeInBytes());
     84 
     85     for (int i = 0; i < kNumStripes; ++i) {
     86       ++stripe_seq_num;
     87       std::uint16_t y = (screen_height / kNumStripes) * i;
     88 
     89       // Last frames on the right and/or bottom handle extra pixels
     90       // when a screen dimension is not evenly divisible by Frame::kNumSlots.
     91       std::uint16_t height =
     92           screen_height / kNumStripes +
     93           (i + 1 == kNumStripes ? screen_height % kNumStripes : 0);
     94       const auto* raw_start =
     95           &raw_screen[y * ActualScreenWidth() * BytesPerPixel()];
     96       const auto* raw_end =
     97           raw_start + (height * ActualScreenWidth() * BytesPerPixel());
     98       // creating a named object and setting individual data members in order
     99       // to make klp happy
    100       // TODO (haining) construct this inside the call when not compiling
    101       // on klp
    102       Stripe s{};
    103       s.index = i;
    104       s.frame_id = previous_seq_num;
    105       s.x = 0;
    106       s.y = y;
    107       s.width = ActualScreenWidth();
    108       s.height = height;
    109       s.raw_data.assign(raw_start, raw_end);
    110       s.seq_number = StripeSeqNumber{stripe_seq_num};
    111       s.orientation = ScreenOrientation::Portrait;
    112       stripes_.Push(std::move(s));
    113     }
    114   }
    115 }
    116 
    117 int SimulatedHWComposer::NumberOfStripes() { return kNumStripes; }
    118