diff --git a/config.yaml b/config.yaml index b718a11..9d20bb5 100644 --- a/config.yaml +++ b/config.yaml @@ -1,14 +1,9 @@ -path: /apps/ # Directory to the app. NOTE: It's the path in docker. EX: /apps/Diablo II -appFile: Notepad.exe # File Name of the app in the directory -windowTitle: Notepad # Window Title: not to show, it's the substring of title to help specify the running program in OS -pageTitle: "Notepad - A Cloud Morph Demo" # Page Title: To display on webpage -appName: Notepad # App name: to show in discovery +path: /apps/RetroBlockGame3D_Data # Directory to the app. NOTE: It's the path in docker. EX: /apps/Diablo II +appFile: RetroBlockGame3D.exe # File Name of the app in the directory +windowTitle: RetroBlockGame3D # Window Title: not to show, it's the substring of title to help specify the running program in OS +pageTitle: "RetroBlockGame3D" # Page Title: To display on webpage +appName: RetroBlockGame3D # App name: to show in discovery appMode: collaborative # app mode: collaborative/single (ex. collaborative: multiple user using same game session) hasChat: true # Turn on chat -# hardwareKey: false # Some game using DirectX needs hardward key. Turn this flag on to receive the input -# screenWidth: 480 # Optional: Default to be: 800 -# screenHeight: 320 # Optional: Default to be: 600 -# isWindowMode: false # Optional: Default to be true. Full screen Windowed or Fullscreen. Up to app -# discoveryHost: http://discovery.cloudmorph.io # Optional: to be discoverable if you plug-in to the discovery server -# instanceAddr: clouddiablo.com # Address of a cloud service instance, discovery can find -# +hardwareKey: true # Some game using DirectX needs hardward key. Turn this flag on to receive the input +gpuAccelerated: true # GPU acceleration with VirtualGL to replace Software Rendering with XVFB. Better performance diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index e4c85f1..e040160 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -16,6 +16,7 @@ type Config struct { // To help WinAPI search the app WindowTitle string `yaml:"windowTitle"` HWKey bool `yaml:"hardwareKey"` + GPUAcc bool `yaml:"gpuAccelerated"` AppMode string `yaml:"appMode"` AppName string `yaml:"appName"` ScreenWidth int `yaml:"screenWidth"` diff --git a/pkg/core/go/cloudapp/cloudapp.go b/pkg/core/go/cloudapp/cloudapp.go index fafca59..ea6eacb 100644 --- a/pkg/core/go/cloudapp/cloudapp.go +++ b/pkg/core/go/cloudapp/cloudapp.go @@ -181,6 +181,12 @@ func (c *ccImpl) launchAppVM(curVideoRTPPort int, curAudioRTPPort int, cfg confi } else { params = append(params, "") } + if cfg.GPUAcc { + fmt.Println("using vgl run") + params = append(params, "vglrun ") + } else { + params = append(params, "") + } runApp(params) // update flag diff --git a/run-wine.sh b/run-wine.sh index 551aadf..786589d 100755 --- a/run-wine.sh +++ b/run-wine.sh @@ -2,10 +2,15 @@ cd winvm docker build -t syncwine . docker rm -f appvm + +# Sync local wine +#docker run -v ~/.wine:/rpath/wine --volume winecfg:/root/.wine syncwine bash -c 'cp -rf /rpath/wine/* /root/.wine' +#docker run -v ~/.wine:/rpath --volume winecfg:/root/.wine syncwine bash -c 'bash -c' + if [ $(uname -s) == "Darwin" ] then echo "Spawn container on Mac" - docker run -d --privileged --rm --name "appvm" \ + docker run -d --privileged --name "appvm" \ --mount type=bind,source="$(pwd)"/apps,target=/apps \ --mount type=bind,source="$(pwd)"/supervisord.conf,target=/etc/supervisor/conf.d/supervisord.conf \ --env "apppath=$1" \ @@ -15,12 +20,36 @@ then --env "screenwidth=$5" \ --env "screenheight=$6" \ --env "wineoptions=$7" \ + --env "vglrun=$8" \ --env "dockerhost=host.docker.internal" \ --env "DISPLAY=:99" \ + --env "VGL_DISPLAY=:1" \ + --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ + --volume="/usr/lib/x86_64-linux-gnu/libXv.so.1:/usr/lib/x86_64-linux-gnu/libXv.so.1" \ --volume "winecfg:/root/.wine" syncwine supervisord else echo "Spawn container on Linux" - docker run -t -d --privileged --rm --name "appvm" \ + + XAUTH=/tmp/.docker.xauth + if [ ! -f $XAUTH ] + then + xauth_list=$(xauth nlist :0 | sed -e 's/^..../ffff/') + if [ ! -z "$xauth_list" ] + then + echo $xauth_list | xauth -f $XAUTH nmerge - + else + touch $XAUTH + fi + chmod a+r $XAUTH + fi + + xhost +local:root + nvidia-docker run -t -d --privileged --rm --name "appvm" \ + --runtime=nvidia \ + --env NVIDIA_DRIVER_CAPABILITIES=all \ + --env="XAUTHORITY=$XAUTH" \ + --volume="$XAUTH:$XAUTH" \ + --env="QT_X11_NO_MITSHM=1" \ --mount type=bind,source="$(pwd)"/apps,target=/apps \ --mount type=bind,source="$(pwd)"/supervisord.conf,target=/etc/supervisor/conf.d/supervisord.conf \ --network=host \ @@ -31,7 +60,37 @@ else --env "screenwidth=$5" \ --env "screenheight=$6" \ --env "wineoptions=$7" \ + --env "vglrun=$8" \ --env "dockerhost=127.0.0.1" \ --env "DISPLAY=:99" \ + --env "VGL_DISPLAY=:1" \ + --env NVIDIA_DISABLE_REQUIRE=1 \ + --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ + --volume="/usr/lib/x86_64-linux-gnu/libXv.so.1:/usr/lib/x86_64-linux-gnu/libXv.so.1" \ --volume "winecfg:/root/.wine" syncwine supervisord + #xhost -local:root # resetting permissions fi + + #nvidia-docker run -it --privileged --rm --name "appvm" \ + #--runtime=nvidia \ + #--env NVIDIA_DRIVER_CAPABILITIES=all \ + #--env="XAUTHORITY=$XAUTH" \ + #--volume="$XAUTH:$XAUTH" \ + #--env="QT_X11_NO_MITSHM=1" \ + #--mount type=bind,source="$(pwd)"/apps,target=/apps \ + #--mount type=bind,source="$(pwd)"/supervisord.conf,target=/etc/supervisor/conf.d/supervisord.conf \ + #--network=host \ + #--env "apppath=/apps/RetroBlockGame3D_Data" \ + #--env "appfile=RetroBlockGame3D.exe" \ + #--env "appname=Retro" \ + #--env "hwkey=game" \ + #--env NVIDIA_DISABLE_REQUIRE=1 \ + #--env "screenwidth=800" \ + #--env "screenheight=600" \ + #--env "wineoptions=-w" \ + #--env "vglrun=vglrun" \ + #--env "dockerhost=127.0.0.1" \ + #--env "DISPLAY=:99" \ + #--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ + #--volume="/usr/lib/x86_64-linux-gnu/libXv.so.1:/usr/lib/x86_64-linux-gnu/libXv.so.1" \ + #--volume "winecfg:/root/.wine" syncwine supervisord diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..bb69880 --- /dev/null +++ b/test.sh @@ -0,0 +1,33 @@ +docker rm -f apptest + +#nvidia-docker run -it --privileged --rm --name "appvm" \ +#--runtime=nvidia \ +#-e XAUTHORITY -e NVIDIA_DRIVER_CAPABILITIES=all \ +#--env "DISPLAY=$DISPLAY" \ +#--network=host \ +#--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ +#--volume="/usr/lib/x86_64-linux-gnu/libXv.so.1:/usr/lib/x86_64-linux-gnu/libXv.so.1" \ +#--volume "winecfg:/root/.wine" syncwine bash + +#[/ C:/7554/7554.exe 7554 game 800 600 -w vglrun ] +nvidia-docker run -it --privileged --rm --name "apptest" \ +--runtime=nvidia \ +-e XAUTHORITY -e NVIDIA_DRIVER_CAPABILITIES=all \ +--network=host \ +--env "apppath=/" \ +--env "appfile=C:/7554/7554.exe" \ +--env "appname=7554" \ +--env "hwkey=game" \ +--env "screenwidth=800" \ +--env "screenheight=600" \ +--env "wineoptions=-w" \ +--env "vglrun=vglrun" \ +--env "dockerhost=127.0.0.1" \ +--env "DISPLAY=:99" \ +--env NVIDIA_DISABLE_REQUIRE=1 \ +--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ +--volume="/usr/lib/x86_64-linux-gnu/libXv.so.1:/usr/lib/x86_64-linux-gnu/libXv.so.1" \ +--volume "winecfg:/root/.wine" syncwine vglrun glxinfo | grep vendor +#xhost -local:root # resetting permissions +#--mount type=bind,source="$(pwd)"/apps,target=/apps \ +#--mount type=bind,source="$(pwd)"/supervisord.conf,target=/etc/supervisor/conf.d/supervisord.conf \ diff --git a/winvm/Dockerfile b/winvm/Dockerfile index d1cb883..c80de0c 100644 --- a/winvm/Dockerfile +++ b/winvm/Dockerfile @@ -1,7 +1,9 @@ #FROM golang:1.14 #FROM ubuntu:18.04 -FROM ubuntu:20.04 -#FROM debian:10-slim +FROM nvidia/cudagl:11.3.1-base-ubuntu20.04 +ENV DEBIAN_FRONTEND=noninteractive +ENV NVIDIA_VISIBLE_DEVICES all +ENV NVIDIA_DRIVER_CAPABILITIES compute,graphics,utility,video RUN apt update RUN apt-get update -y @@ -26,11 +28,25 @@ RUN winetricks d3dx9_43 # uncomment it for lutris game #RUN winetricks --force -q dotnet48 +ENV VIRTUALGL_VERSION 2.5.2 # Download gecko and mono installers COPY download_gecko_and_mono.sh /root/download_gecko_and_mono.sh RUN chmod +x /root/download_gecko_and_mono.sh \ && /root/download_gecko_and_mono.sh "$(dpkg -s wine-stable | grep "^Version:\s" | awk '{print $2}' | sed -E 's/~.*$//')" +RUN apt-get update && apt-get install -y --no-install-recommends \ + libglu1-mesa-dev mesa-utils curl ca-certificates xterm && \ + curl -sSL https://downloads.sourceforge.net/project/virtualgl/"${VIRTUALGL_VERSION}"/virtualgl_"${VIRTUALGL_VERSION}"_amd64.deb -o virtualgl_"${VIRTUALGL_VERSION}"_amd64.deb && \ + dpkg -i virtualgl_*_amd64.deb && \ + /opt/VirtualGL/bin/vglserver_config -config +s +f -t && \ + rm virtualgl_*_amd64.deb && \ + apt-get clean && \ + apt-get remove -y curl ca-certificates && \ + rm -rf /var/lib/apt/lists/* +LABEL com.nvidia.volumes.needed="nvidia_driver" +ENV PATH /usr/local/nvidia/bin:/opt/VirtualGL/bin:${PATH} +ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64:${LD_LIBRARY_PATH}/lists/* + RUN mkdir -p /winevm WORKDIR /winevm COPY ./ ./ diff --git a/winvm/supervisord.conf b/winvm/supervisord.conf index f3ca642..3b8d455 100644 --- a/winvm/supervisord.conf +++ b/winvm/supervisord.conf @@ -5,9 +5,8 @@ loglevel=debug logfile_maxbytes=0 [program:wineapp] -command=wine %(ENV_appfile)s %(ENV_wineoptions)s +command=%(ENV_vglrun)swine %(ENV_appfile)s %(ENV_wineoptions)s directory=%(ENV_apppath)s -environment=DISPLAY=:99 autostart=true autorestart=true startsecs=5 @@ -16,7 +15,7 @@ stdout_logfile=/winevm/wineapp_out stderr_logfile=/winevm/wineapp_err [program:Xvfb] -command=/usr/bin/Xvfb :99 -screen 0 800x600x16 +command=/usr/bin/Xvfb :99 -screen 0 800x600x24+32 +extension GLX +render -noreset autostart=true autorestart=true startsecs=5 @@ -26,7 +25,6 @@ stderr_logfile=/winevm/xvfb_err [program:pulseaudio] command=pulseaudio --exit-idle-time=-1 -/*command=pulseaudio --disallow-exit --disallow-module-loading --exit-idle-time=-1*/ autostart=true autorestart=true startsecs=5 @@ -35,7 +33,7 @@ stdout_logfile=/winevm/pulse_audio_out stderr_logfile=/winevm/pulse_audio_err [program:syncinput] -command=wine syncinput.exe %(ENV_appname)s \"%(ENV_hwkey)s\" %(ENV_dockerhost)s +command=wine syncinput.exe %(ENV_appname)s %(ENV_hwkey)s %(ENV_dockerhost)s directory=/winevm/ autostart=true autorestart=true diff --git a/winvm/syncinput.cpp b/winvm/syncinput.cpp index a33491c..18b1cee 100644 --- a/winvm/syncinput.cpp +++ b/winvm/syncinput.cpp @@ -85,7 +85,7 @@ void getDesktopResolution(int &width, int &height) HWND getWindowByTitle(char *pattern) { - HWND hwnd = NULL; + HWND hwnd = 0; do { @@ -263,8 +263,12 @@ Mouse parseMousePayload(string stPos) return Mouse{isLeft, state, x, y, w, h}; } -void formatWindow(HWND hwnd) +void formatWindow(HWND hwnd, bool isWindowedMode) { + // deprecated, should run with window mode only + if (!isWindowedMode) { + return; + } SetWindowPos(hwnd, NULL, 0, 0, 800, 600, 0); SetWindowLong(hwnd, GWL_STYLE, 0); cout << "Window formated" << endl; @@ -298,7 +302,7 @@ void *thwndupdate(void *args) hwnd = getWindowByTitle(winTitle); if (hwnd != oldhwnd) { - formatWindow(hwnd); + formatWindow(hwnd, false); cout << "Updated HWND: " << hwnd << endl; oldhwnd = hwnd; } @@ -339,6 +343,7 @@ int main(int argc, char *argv[]) { if (strcmp(argv[2], "game") == 0) { + cout << "Running DX Game" << endl; isDxGame = true; } } @@ -356,7 +361,7 @@ int main(int argc, char *argv[]) << "height " << screenHeight << endl; cout << "Docker host" << dockerHost << endl; - formatWindow(hwnd); + formatWindow(hwnd, false); // setup socket watcher. TODO: How to check if a socket pipe is broken? done = false;