Browse code

Switch back to single thread for handling redraws.

This reverts commit a283264df27c2a886de41d23841dfe3e92b4b2c1 while
keeping the enhancements made later on (detection of overlong
execution).

This change fixes compatibility for learn-uxn and current npe.

Andrew Alderwick authored on 10/06/2022 05:31:07
Showing 1 changed files
... ...
@@ -36,7 +36,8 @@ WITH REGARD TO THIS SOFTWARE.
36 36
 #define WIDTH 64 * 8
37 37
 #define HEIGHT 40 * 8
38 38
 #define PAD 4
39
-#define TIMEOUT_FRAMES 20
39
+#define TIMEOUT_MS 334
40
+#define BENCH 0
40 41
 
41 42
 static SDL_Window *gWindow;
42 43
 static SDL_Texture *gTexture;
... ...
@@ -49,7 +50,8 @@ static SDL_Thread *stdin_thread;
49 50
 
50 51
 static Device *devscreen, *devmouse, *devctrl, *devaudio0;
51 52
 static Uint8 zoom = 1;
52
-static Uint32 stdin_event, audio0_event, redraw_event, interrupt_event;
53
+static Uint32 stdin_event, audio0_event;
54
+static Uint64 exec_deadline, deadline_interval, ms_interval;
53 55
 
54 56
 static int
55 57
 error(char *msg, const char *err)
... ...
@@ -93,26 +95,6 @@ stdin_handler(void *p)
93 95
 	(void)p;
94 96
 }
95 97
 
96
-static int
97
-redraw_handler(void *p)
98
-{
99
-	int dropped_frames = 0, stop = 0;
100
-	SDL_Event event, interrupt;
101
-	event.type = redraw_event;
102
-	interrupt.type = interrupt_event;
103
-	while(!stop) {
104
-		SDL_Delay(16);
105
-		if(SDL_HasEvent(redraw_event) == SDL_FALSE) {
106
-			stop = SDL_PushEvent(&event) < 0;
107
-			dropped_frames = 0;
108
-		} else if(++dropped_frames == TIMEOUT_FRAMES) {
109
-			stop = SDL_PushEvent(&interrupt) < 0;
110
-		}
111
-	}
112
-	return 0;
113
-	(void)p;
114
-}
115
-
116 98
 static void
117 99
 set_window_size(SDL_Window *window, int w, int h)
118 100
 {
... ...
@@ -181,13 +163,12 @@ init(void)
181 163
 		error("sdl_joystick", SDL_GetError());
182 164
 	stdin_event = SDL_RegisterEvents(1);
183 165
 	audio0_event = SDL_RegisterEvents(POLYPHONY);
184
-	redraw_event = SDL_RegisterEvents(1);
185
-	interrupt_event = SDL_RegisterEvents(1);
186 166
 	SDL_DetachThread(stdin_thread = SDL_CreateThread(stdin_handler, "stdin", NULL));
187
-	SDL_DetachThread(SDL_CreateThread(redraw_handler, "redraw", NULL));
188 167
 	SDL_StartTextInput();
189 168
 	SDL_ShowCursor(SDL_DISABLE);
190 169
 	SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
170
+	ms_interval = SDL_GetPerformanceFrequency() / 1000;
171
+	deadline_interval = ms_interval * TIMEOUT_MS;
191 172
 	return 1;
192 173
 }
193 174
 
... ...
@@ -290,6 +271,7 @@ start(Uxn *u, char *rom)
290 271
 	/* unused   */ uxn_port(u, 0xd, nil_dei, nil_deo);
291 272
 	/* unused   */ uxn_port(u, 0xe, nil_dei, nil_deo);
292 273
 	/* unused   */ uxn_port(u, 0xf, nil_dei, nil_deo);
274
+	exec_deadline = SDL_GetPerformanceCounter() + deadline_interval;
293 275
 	if(!uxn_eval(u, PAGE_PROGRAM))
294 276
 		return error("Boot", "Failed to start rom.");
295 277
 	return 1;
... ...
@@ -392,15 +374,10 @@ console_input(Uxn *u, char c)
392 374
 }
393 375
 
394 376
 static int
395
-run(Uxn *u)
377
+handle_events(Uxn *u)
396 378
 {
397 379
 	SDL_Event event;
398
-	Device *devsys = &u->dev[0];
399
-	redraw();
400
-	while(SDL_WaitEvent(&event)) {
401
-		/* .System/halt */
402
-		if(devsys->dat[0xf])
403
-			return error("Run", "Ended.");
380
+	while(SDL_PollEvent(&event)) {
404 381
 		/* Window */
405 382
 		if(event.type == SDL_QUIT)
406 383
 			return error("Run", "Quit.");
... ...
@@ -439,13 +416,8 @@ run(Uxn *u)
439 416
 			else
440 417
 				do_shortcut(u, &event);
441 418
 			ksym = event.key.keysym.sym;
442
-			while(SDL_PeepEvents(&event, 1, SDL_PEEKEVENT, redraw_event, redraw_event) == 0) {
443
-				SDL_Delay(4);
444
-				SDL_PumpEvents();
445
-			}
446 419
 			if(SDL_PeepEvents(&event, 1, SDL_PEEKEVENT, SDL_KEYUP, SDL_KEYUP) == 1 && ksym == event.key.keysym.sym) {
447
-				SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_KEYUP, SDL_KEYUP);
448
-				SDL_PushEvent(&event);
420
+				return 1;
449 421
 			}
450 422
 		} else if(event.type == SDL_KEYUP)
451 423
 			controller_up(devctrl, get_button(&event));
... ...
@@ -462,11 +434,30 @@ run(Uxn *u)
462 434
 		/* Console */
463 435
 		else if(event.type == stdin_event)
464 436
 			console_input(u, event.cbutton.button);
465
-		/* .Screen/vector and redraw */
466
-		else if(event.type == redraw_event) {
467
-			uxn_eval(u, GETVECTOR(devscreen));
468
-			if(uxn_screen.fg.changed || uxn_screen.bg.changed)
469
-				redraw();
437
+	}
438
+	return 1;
439
+}
440
+
441
+static int
442
+run(Uxn *u)
443
+{
444
+	Device *devsys = &u->dev[0];
445
+	Uint64 now = SDL_GetPerformanceCounter(), frame_end, frame_interval = SDL_GetPerformanceFrequency() / 60;
446
+	for(;;) {
447
+		/* .System/halt */
448
+		if(devsys->dat[0xf])
449
+			return error("Run", "Ended.");
450
+		frame_end = now + frame_interval;
451
+		exec_deadline = now + deadline_interval;
452
+		if(!handle_events(u))
453
+			return 0;
454
+		uxn_eval(u, GETVECTOR(devscreen));
455
+		if(uxn_screen.fg.changed || uxn_screen.bg.changed)
456
+			redraw();
457
+		now = SDL_GetPerformanceCounter();
458
+		if(!BENCH && ((Sint64)(frame_end - now)) > 0) {
459
+			SDL_Delay((frame_end - now) / ms_interval);
460
+			now = frame_end;
470 461
 		}
471 462
 	}
472 463
 	return error("SDL_WaitEvent", SDL_GetError());
... ...
@@ -475,7 +466,7 @@ run(Uxn *u)
475 466
 int
476 467
 uxn_interrupt(void)
477 468
 {
478
-	return SDL_PeepEvents(NULL, 1, SDL_GETEVENT, interrupt_event, interrupt_event) < 1;
469
+	return ((Sint64)(exec_deadline - SDL_GetPerformanceCounter())) > 0;
479 470
 }
480 471
 
481 472
 int