1 #include <X11/Xlib.h>
2 
3 #include <thread>
4 #include <mutex>
5 #include <vector>
6 #include <cstring>
7 #if defined(__linux__)
8 #include <sys/capability.h>
9 #endif
10 
11 #include <unistd.h>
12 
13 #include "main.hpp"
14 #include "steamcompmgr.hpp"
15 #include "drm.hpp"
16 #include "rendervulkan.hpp"
17 #include "sdlwindow.hpp"
18 #include "wlserver.hpp"
19 
20 int ac;
21 char **av;
22 
23 int g_nNestedWidth = 1280;
24 int g_nNestedHeight = 720;
25 int g_nNestedRefresh = 0;
26 int g_nNestedUnfocusedRefresh = 0;
27 
28 uint32_t g_nOutputWidth = 1280;
29 uint32_t g_nOutputHeight = 720;
30 int g_nOutputRefresh = 60;
31 
32 bool g_bFullscreen = false;
33 
34 bool g_bIsNested = false;
35 
36 bool g_bFilterGameWindow = true;
37 
38 bool g_bBorderlessOutputWindow = false;
39 
40 bool g_bTakeScreenshot = false;
41 
42 bool g_bNiceCap = false;
43 int g_nOldNice = 0;
44 int g_nNewNice = 0;
45 
46 uint32_t g_nSubCommandArg = 0;
47 
BIsNested()48 int BIsNested()
49 {
50 	return g_bIsNested == true;
51 }
52 
main(int argc,char ** argv)53 int main(int argc, char **argv)
54 {
55 	// Grab the starting position of a potential command that follows "--" in argv
56 	// Do it before getopt can reorder anything, for use later
57 	for ( int i = 0; i < argc; i++ )
58 	{
59 		if ( strcmp( "--", argv[ i ] ) == 0 && i + 1 < argc )
60 		{
61 			g_nSubCommandArg = i + 1;
62 			break;
63 		}
64 	}
65 
66 	int o;
67 	ac = argc;
68 	av = argv;
69 
70 	bool bSleepAtStartup = false;
71 
72 	while ((o = getopt (argc, argv, ":R:T:w:h:W:H:r:o:NFSvVecsdlnbf")) != -1)
73 	{
74 		switch (o) {
75 			case 'w':
76 				g_nNestedWidth = atoi( optarg );
77 				break;
78 			case 'h':
79 				g_nNestedHeight = atoi( optarg );
80 				break;
81 			case 'W':
82 				g_nOutputWidth = atoi( optarg );
83 				break;
84 			case 'H':
85 				g_nOutputHeight = atoi( optarg );
86 				break;
87 			case 'r':
88 				g_nNestedRefresh = atoi( optarg );
89 				break;
90 			case 'o':
91 				g_nNestedUnfocusedRefresh = atoi( optarg );
92 				break;
93 			case 's':
94 				bSleepAtStartup = true;
95 				break;
96 			case 'l':
97 				g_bUseLayers = true;
98 				break;
99 			case 'd':
100 				g_bDebugLayers = true;
101 				break;
102 			case 'n':
103 				g_bFilterGameWindow = false;
104 				break;
105 			case 'b':
106 				g_bBorderlessOutputWindow = true;
107 				break;
108 			case 'f':
109 				g_bFullscreen = true;
110 				break;
111 			default:
112 				break;
113 		}
114 	}
115 
116 	// If we're going to execute something monolithic, might as well set this since it'll extend to our clients
117 	if ( g_nSubCommandArg != 0 )
118 	{
119 		const char *pchR600Debug = getenv( "R600_DEBUG" );
120 
121 		if ( pchR600Debug == nullptr )
122 		{
123 			setenv( "R600_DEBUG", "nodcc", 1 );
124 		}
125 		else if ( strstr( pchR600Debug, "nodcc" ) == nullptr )
126 		{
127 			std::string strPreviousR600Debug = pchR600Debug;
128 			strPreviousR600Debug.append( ",nodcc" );
129 			setenv( "R600_DEBUG", strPreviousR600Debug.c_str(), 1 );
130 		}
131 	}
132 
133 #if defined(__linux__)
134 	cap_t caps;
135 	caps = cap_get_proc();
136 	cap_flag_value_t nicecapvalue = CAP_CLEAR;
137 
138 	if ( caps != nullptr )
139 	{
140 		cap_get_flag( caps, CAP_SYS_NICE, CAP_EFFECTIVE, &nicecapvalue );
141 
142 		if ( nicecapvalue == CAP_SET )
143 		{
144 			g_bNiceCap = true;
145 
146 			errno = 0;
147 			int nOldNice = nice( 0 );
148 			if ( nOldNice != -1 && errno == 0 )
149 			{
150 				g_nOldNice = nOldNice;
151 			}
152 
153 			errno = 0;
154 			int nNewNice = nice( -20 );
155 			if ( nNewNice != -1 && errno == 0 )
156 			{
157 				g_nNewNice = nNewNice;
158 			}
159 		}
160 	}
161 
162 	if ( g_bNiceCap == false )
163 	{
164 		fprintf( stderr, "No CAP_SYS_NICE, falling back to regular-priority compute and threads.\nPerformance will be affected.\n" );
165 	}
166 #endif
167 
168 	if ( bSleepAtStartup == true )
169 	{
170 	 	sleep( 2 );
171 	}
172 
173 	XInitThreads();
174 
175 	if ( getenv("DISPLAY") != NULL )
176 	{
177 		g_bIsNested = true;
178 	}
179 
180 	wlserver_init(argc, argv, g_bIsNested == true );
181 
182 	if ( initOutput() != 0 )
183 	{
184 		fprintf( stderr, "Failed to initialize output\n" );
185 		return 1;
186 	}
187 
188 	wlserver_run();
189 }
190 
steamCompMgrThreadRun(void)191 void steamCompMgrThreadRun(void)
192 {
193 	steamcompmgr_main( ac, av );
194 }
195 
startSteamCompMgr(void)196 void startSteamCompMgr(void)
197 {
198 	std::thread steamCompMgrThread( steamCompMgrThreadRun );
199 	steamCompMgrThread.detach();
200 
201 	return;
202 }
203 
initOutput(void)204 int initOutput(void)
205 {
206 	if ( g_bIsNested == true )
207 	{
208 		return sdlwindow_init() == false;
209 	}
210 	else
211 	{
212 		return init_drm( &g_DRM, nullptr, nullptr, 0 );
213 	}
214 }
215 
wayland_commit(struct wlr_surface * surf,struct wlr_buffer * buf)216 void wayland_commit(struct wlr_surface *surf, struct wlr_buffer *buf)
217 {
218 	{
219 		std::lock_guard<std::mutex> lock( wayland_commit_lock );
220 
221 		ResListEntry_t newEntry = {
222 			.surf = surf,
223 			.buf = buf,
224 		};
225 		wayland_commit_queue.push_back( newEntry );
226 	}
227 
228 	nudge_steamcompmgr();
229 }
230