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 
     22 using cvd::vnc::SimulatedHWComposer;
     23 using vsoc::screen::ScreenRegionView;
     24 
     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 
     35 SimulatedHWComposer::~SimulatedHWComposer() {
     36   close();
     37   stripe_maker_.join();
     38 }
     39 
     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 
     52 bool SimulatedHWComposer::closed() {
     53   std::lock_guard<std::mutex> guard(m_);
     54   return closed_;
     55 }
     56 
     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.
     66 void SimulatedHWComposer::EraseHalfOfElements(
     67     ThreadSafeQueue<Stripe>::QueueImpl* q) {
     68   q->erase(q->begin(), std::next(q->begin(), kMaxQueueElements / 2));
     69 }
     70 
     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 
    116 int SimulatedHWComposer::NumberOfStripes() { return kNumStripes; }
    117