@@ -156,6 +156,43 @@ get_initial_optimal_size(struct size content_size, uint16_t req_width,
156
156
return window_size ;
157
157
}
158
158
159
+ static void
160
+ screen_update_content_rect (struct screen * screen ) {
161
+ int dw ;
162
+ int dh ;
163
+ SDL_GL_GetDrawableSize (screen -> window , & dw , & dh );
164
+
165
+ struct size content_size = screen -> content_size ;
166
+ // The drawable size is the window size * the HiDPI scale
167
+ struct size drawable_size = {dw , dh };
168
+
169
+ SDL_Rect * rect = & screen -> rect ;
170
+
171
+ if (is_optimal_size (drawable_size , content_size )) {
172
+ rect -> x = 0 ;
173
+ rect -> y = 0 ;
174
+ rect -> w = drawable_size .width ;
175
+ rect -> h = drawable_size .height ;
176
+ return ;
177
+ }
178
+
179
+ bool keep_width = content_size .width * drawable_size .height
180
+ > content_size .height * drawable_size .width ;
181
+ if (keep_width ) {
182
+ rect -> x = 0 ;
183
+ rect -> w = drawable_size .width ;
184
+ rect -> h = drawable_size .width * content_size .height
185
+ / content_size .width ;
186
+ rect -> y = (drawable_size .height - rect -> h ) / 2 ;
187
+ } else {
188
+ rect -> y = 0 ;
189
+ rect -> h = drawable_size .height ;
190
+ rect -> w = drawable_size .height * content_size .width
191
+ / content_size .height ;
192
+ rect -> x = (drawable_size .width - rect -> w ) / 2 ;
193
+ }
194
+ }
195
+
159
196
void
160
197
screen_init (struct screen * screen ) {
161
198
* screen = (struct screen ) SCREEN_INITIALIZER ;
@@ -245,13 +282,6 @@ screen_init_rendering(struct screen *screen, const char *window_title,
245
282
const char * renderer_name = r ? NULL : renderer_info .name ;
246
283
LOGI ("Renderer: %s" , renderer_name ? renderer_name : "(unknown)" );
247
284
248
- if (SDL_RenderSetLogicalSize (screen -> renderer , content_size .width ,
249
- content_size .height )) {
250
- LOGE ("Could not set renderer logical size: %s" , SDL_GetError ());
251
- screen_destroy (screen );
252
- return false;
253
- }
254
-
255
285
// starts with "opengl"
256
286
screen -> use_opengl = renderer_name && !strncmp (renderer_name , "opengl" , 6 );
257
287
if (screen -> use_opengl ) {
@@ -295,6 +325,8 @@ screen_init_rendering(struct screen *screen, const char *window_title,
295
325
return false;
296
326
}
297
327
328
+ screen_update_content_rect (screen );
329
+
298
330
return true;
299
331
}
300
332
@@ -365,40 +397,30 @@ screen_set_rotation(struct screen *screen, unsigned rotation) {
365
397
struct size new_content_size =
366
398
get_rotated_size (screen -> frame_size , rotation );
367
399
368
- if (SDL_RenderSetLogicalSize (screen -> renderer ,
369
- new_content_size .width ,
370
- new_content_size .height )) {
371
- LOGE ("Could not set renderer logical size: %s" , SDL_GetError ());
372
- return ;
373
- }
374
-
375
400
set_content_size (screen , new_content_size );
401
+
376
402
screen -> rotation = rotation ;
377
403
LOGI ("Display rotation set to %u" , rotation );
378
404
379
- screen_render (screen );
405
+ screen_render (screen , true );
380
406
}
381
407
382
408
// recreate the texture and resize the window if the frame size has changed
383
409
static bool
384
410
prepare_for_frame (struct screen * screen , struct size new_frame_size ) {
385
411
if (screen -> frame_size .width != new_frame_size .width
386
412
|| screen -> frame_size .height != new_frame_size .height ) {
387
- struct size new_content_size =
388
- get_rotated_size (new_frame_size , screen -> rotation );
389
- if (SDL_RenderSetLogicalSize (screen -> renderer ,
390
- new_content_size .width ,
391
- new_content_size .height )) {
392
- LOGE ("Could not set renderer logical size: %s" , SDL_GetError ());
393
- return false;
394
- }
395
-
396
413
// frame dimension changed, destroy texture
397
414
SDL_DestroyTexture (screen -> texture );
398
415
399
- set_content_size (screen , new_content_size );
400
416
screen -> frame_size = new_frame_size ;
401
417
418
+ struct size new_content_size =
419
+ get_rotated_size (new_frame_size , screen -> rotation );
420
+ set_content_size (screen , new_content_size );
421
+
422
+ screen_update_content_rect (screen );
423
+
402
424
LOGI ("New texture: %" PRIu16 "x%" PRIu16 ,
403
425
screen -> frame_size .width , screen -> frame_size .height );
404
426
screen -> texture = create_texture (screen );
@@ -439,15 +461,19 @@ screen_update_frame(struct screen *screen, struct video_buffer *vb) {
439
461
update_texture (screen , frame );
440
462
mutex_unlock (vb -> mutex );
441
463
442
- screen_render (screen );
464
+ screen_render (screen , false );
443
465
return true;
444
466
}
445
467
446
468
void
447
- screen_render (struct screen * screen ) {
469
+ screen_render (struct screen * screen , bool update_content_rect ) {
470
+ if (update_content_rect ) {
471
+ screen_update_content_rect (screen );
472
+ }
473
+
448
474
SDL_RenderClear (screen -> renderer );
449
475
if (screen -> rotation == 0 ) {
450
- SDL_RenderCopy (screen -> renderer , screen -> texture , NULL , NULL );
476
+ SDL_RenderCopy (screen -> renderer , screen -> texture , NULL , & screen -> rect );
451
477
} else {
452
478
// rotation in RenderCopyEx() is clockwise, while screen->rotation is
453
479
// counterclockwise (to be consistent with --lock-video-orientation)
@@ -457,12 +483,14 @@ screen_render(struct screen *screen) {
457
483
SDL_Rect * dstrect = NULL ;
458
484
SDL_Rect rect ;
459
485
if (screen -> rotation & 1 ) {
460
- struct size size = screen -> content_size ;
461
- rect .x = (size .width - size .height ) / 2 ;
462
- rect .y = (size .height - size .width ) / 2 ;
463
- rect .w = size .height ;
464
- rect .h = size .width ;
486
+ rect .x = screen -> rect .x + (screen -> rect .w - screen -> rect .h ) / 2 ;
487
+ rect .y = screen -> rect .y + (screen -> rect .h - screen -> rect .w ) / 2 ;
488
+ rect .w = screen -> rect .h ;
489
+ rect .h = screen -> rect .w ;
465
490
dstrect = & rect ;
491
+ } else {
492
+ assert (screen -> rotation == 2 );
493
+ dstrect = & screen -> rect ;
466
494
}
467
495
468
496
SDL_RenderCopyEx (screen -> renderer , screen -> texture , NULL , dstrect ,
@@ -485,7 +513,7 @@ screen_switch_fullscreen(struct screen *screen) {
485
513
}
486
514
487
515
LOGD ("Switched to %s mode" , screen -> fullscreen ? "fullscreen" : "windowed" );
488
- screen_render (screen );
516
+ screen_render (screen , true );
489
517
}
490
518
491
519
void
@@ -523,10 +551,10 @@ screen_handle_window_event(struct screen *screen,
523
551
const SDL_WindowEvent * event ) {
524
552
switch (event -> event ) {
525
553
case SDL_WINDOWEVENT_EXPOSED :
526
- screen_render (screen );
554
+ screen_render (screen , true );
527
555
break ;
528
556
case SDL_WINDOWEVENT_SIZE_CHANGED :
529
- screen_render (screen );
557
+ screen_render (screen , true );
530
558
break ;
531
559
case SDL_WINDOWEVENT_MAXIMIZED :
532
560
screen -> maximized = true;
@@ -552,6 +580,13 @@ screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) {
552
580
553
581
int32_t w = screen -> content_size .width ;
554
582
int32_t h = screen -> content_size .height ;
583
+
584
+ screen_hidpi_scale_coords (screen , & x , & y );
585
+
586
+ x = (int64_t ) (x - screen -> rect .x ) * w / screen -> rect .w ;
587
+ y = (int64_t ) (y - screen -> rect .y ) * h / screen -> rect .h ;
588
+
589
+ // rotate
555
590
struct point result ;
556
591
switch (rotation ) {
557
592
case 0 :
@@ -574,3 +609,15 @@ screen_convert_to_frame_coords(struct screen *screen, int32_t x, int32_t y) {
574
609
}
575
610
return result ;
576
611
}
612
+
613
+ void
614
+ screen_hidpi_scale_coords (struct screen * screen , int32_t * x , int32_t * y ) {
615
+ // take the HiDPI scaling (dw/ww and dh/wh) into account
616
+ int ww , wh , dw , dh ;
617
+ SDL_GetWindowSize (screen -> window , & ww , & wh );
618
+ SDL_GL_GetDrawableSize (screen -> window , & dw , & dh );
619
+
620
+ // scale for HiDPI (64 bits for intermediate multiplications)
621
+ * x = (int64_t ) * x * dw / ww ;
622
+ * y = (int64_t ) * y * dh / wh ;
623
+ }
0 commit comments