МАРСОХОД

Open Source Hardware Project

Копирование экрана виртуальной машины на терминал USBTerm



Только что прошел еще один очень важный этап в своем проекте USBTerm.

Поскольку я собираюсь отображать на своем графическом терминале экран виртуальной машины VMWare, то мне принципиально важно понять, как я это буду делать. И вообще, возможно ли это в принципе.

Я собираюсь копировать изображение декстопа виртуальной машины на USB терминал, но как сделать это с минимальными издержками, с максимальной производительностью? Понятно, что нужно переносить по шине USB только изменения на экране, ведь изменений, как правило, не очень много. Если удастся копировать только изменившиеся участки экрана, то производительность обещает быть приемлимой.

Поскольку мы высококвалифицированные программисты, то нам удалось нагуглить некоторое решение. :-)

Цель проекта USBTerm - создание недорогого терминала, тонкого клиента, на базе платы Марсоход3bis для работы в среде Windows 8.1 или Windows 10. Выбор Windows - как самой распространенной ОС. Поэтому, я веду поиск решения именно для Windows.

Вот.. Для Windows когда-то майкрософт предлагала писать дисплейный драйвер mirror - зеркало. Этот дисплейный драйвер mirror принимал копии всех вызовов к основному дисплейному драйверу. Сейчас, для Windows 8 и выше, этот метод похоже уже не работает.

Взамен драйверам mirror, компания microsoft теперь предлагает пользоваться специальным Desktop Duplication API https://msdn.microsoft.com/en-us/library/windows/desktop/hh404487(v=vs.85).aspx(v=vs.85).aspx

Это API интенсивно использует DirectX и позволяет:

  • получить текущее изображение с экрана компьютера функцией IDXGIOutputDuplication::AcquireNextFrame;
  • получить координаты прямоугольных областей экрана, которые были изменены, IDXGIOutputDuplication::GetFrameDirtyRects;
  • получить координаты прямоугольных областей экрана, которые были перемещены, IDXGIOutputDuplication::GetFrameMoveRects;
  • получить изображение и местоположение указателя мыши функцией IDXGIOutputDuplication::GetFramePointerShape.

К сожалению, я не являюсь знатоком DIrectX, так что пришлось изрядно потрудиться, чтобы все это понять, переосмыслить и применить к моему терминалу. Мне требовалось доказать хотя бы самом себе, что проект идет в правильном направлении.

Microsoft предлагает исходный код проекта, который демонстрирует возможности DesktopDuplication API вот здесь: можно просто взять и пробовать https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a Однако, мне этот пример не совсем подходит. Точнее, совсем не подходит, так как он хватает содержимое дисплея, но отображает его в windows окне программы. В этом примере получается как-то вот так:

display duplication API sample

Мне вообще не нужно никакого моего окна на экране. И мне нужно получить попиксельный доступ изменившимся областям иэображения экрана. Из-за этого мне пришлось взять исходный пример майкрософта и значительно его переработать.

В DirectX, как я понял, изображения размещаются в текстурах ID3D11Texture2D. И размещаться они, эти текстуры, могут либо в памяти видеоадаптера (графического ускорителя), либо в системной памяти. Если в системной памяти - тогда можно получить доступ процессора к памяти текстуры, если сделать ID3D11DeviceContext.Map(...).

Вот и приходится получить новый фрейм и список прямоугольных участков, которые были изменены на экране, потом копировать текстуру из фрейма в мою текстуру, находящуюся в системной памяти, делать Map() и получать доступ к пикселам. Уж потом формировать блоки команд для USBTerm и посылать фрагменты изображения не терминал.

Вот сделал простейшую демонстрацию этой всей системы.

Исходники, конечно, на GITHUB:  https://github.com/marsohod4you/UsbHwThinClient4Vm/tree/master/cpp/test

Плата Марсоход3bis с зашитым в ПЛИС проектом терминала подключается к ноутбуку. На ноутбуке запускаю VMWare Player, который запускает виртуальную машину с ОС Windows 8.1. В виртуальную машину пробрасываю подключенное устройство USB FTDI с платы Марсоход3bis.

vmimg

Теперь в виртуальной машине запускаю свою тестовую программу test.exe, которая копирует экран виртуальной машина в плату.
Виртуальную машину можно свернуть в иконку и делать на ноутбуке какую-то свою работу, на терминале - свой экран, своя виндовс и свое рабочее место. На видео демонстрации в начале этой статьи все это видно.

Ну пока это только предварительные тесты. Тестовая программа очень далека от совершенства. Ее нужно оформить в виде сервиса Windows, она должна уметь переключаться между десктопами (в виндовс как минимум всегда два десктопа: первый, где выполняется логин пользователя, второй - рабочий десктоп), нужно, чтобы программа не ломалась, когда меняется разрешение на экране виртуальной машины, ну и с производительностью еще нужно поработать, я сейчас пользуюсь функцией ID3D11DeviceContext::CopyResource(..) для копирования текстур, а нужно использовать ID3D11DeviceContext::CopyResourceRegion(..)

В общем работа еще много. Ну и теперь, когда я понял, что с виртуальной машиной задумка верная, займусь подключением USB мыши и USB клавиатуры к плате Marsohod3bis.

Комментарии  

0 #5 _alex 07.02.2016 14:51
Простой подсчёт.
1920х1080х4(YRGB)х60fps=497664000 байт=474.609375 Мбайт * 8bps= 3796.875 Mbps.
Если сделать компрессию в программе на компьютере, то поток можно уменьшить. Однако, придётся делать хардверный декомпрессор картинки на плате марсохода.
0 #4 nckm 07.02.2016 11:08
Цитирую _alex:
Как я понимаю плата марсоход в этом проекте не будет использовать АРМ ядро, а только отображать картинку и отсылать клики клавиатуры и положение мыши. Следовательно данные, как пикселы для экрана, должны быть подготовлены в программе на компьютере и посланы готовым к использованию пакетом через транспорт. Плате марсохода только и останется, что переслать пиксели из пакета в буфер для экрана. Хватит ли скорости USB для такого потока?

скорость передачи можно получить чуть больше 30Мбайт в секунду. Для офисных приложений - хватит.
0 #3 _alex 06.02.2016 18:32
Как я понимаю плата марсоход в этом проекте не будет использовать АРМ ядро, а только отображать картинку и отсылать клики клавиатуры и положение мыши. Следовательно данные, как пикселы для экрана, должны быть подготовлены в программе на компьютере и посланы готовым к использованию пакетом через транспорт. Плате марсохода только и останется, что переслать пиксели из пакета в буфер для экрана. Хватит ли скорости USB для такого потока?
0 #2 nckm 03.02.2016 19:40
Цитирую alman:
Протокол будете документировать? Например, если кому-то понадобится не копию виртуального экрана передавать, а рисовать что-то на экране Марсохода-3 из консольной программы.

обязательно буду документировать .. к сожалению пока нет времени на это..
0 #1 alman 03.02.2016 17:22
Протокол будете документировать ? Например, если кому-то понадобится не копию виртуального экрана передавать, а рисовать что-то на экране Марсохода-3 из консольной программы.

Добавить комментарий


Защитный код
Обновить


GitHub YouTube Twitter
Вы здесь: Начало Проект графического терминала USBTerm Копирование экрана виртуальной машины на терминал USBTerm