@@ -420,7 +420,7 @@ def resize_fbo(self, context, oldw : int, oldh : int, bw : int, bh : int) -> Non
420
420
dy = (bh - h )- dy
421
421
#re-init our OpenGL context with the new size,
422
422
#but leave offscreen fbo with the old size
423
- self .gl_init (True )
423
+ self .gl_init (context , True )
424
424
#copy offscreen to new tmp:
425
425
self .copy_fbo (w , h , sx , sy , dx , dy )
426
426
#make tmp the new offscreen:
@@ -518,7 +518,7 @@ def gl_init_shaders(self) -> None:
518
518
raise RuntimeError (f"OpenGL shader { name } setup failure: { err } " )
519
519
log ("%s shader initialized" , name )
520
520
521
- def gl_init (self , skip_fbo :bool = False ) -> None :
521
+ def gl_init (self , context , skip_fbo :bool = False ) -> None :
522
522
#must be called within a context!
523
523
#performs init if needed
524
524
if not self .debug_setup :
@@ -534,8 +534,9 @@ def gl_init(self, skip_fbo:bool=False) -> None:
534
534
self .gl_marker ("Initializing GL context for window size %s, backing size %s, max texture size=%i" ,
535
535
self .render_size , self .size , mt )
536
536
# Initialize viewport and matrices for 2D rendering
537
- x , _ , _ , y = self .offsets
538
- glViewport (x , y , w , h )
537
+ # default is to paint to pbo, so without any scale factor or offsets
538
+ # (as those are only applied when painting the window)
539
+ glViewport (0 , 0 , w , h )
539
540
glMatrixMode (GL_PROJECTION )
540
541
glLoadIdentity ()
541
542
glOrtho (0.0 , w , h , 0.0 , - 1.0 , 1.0 )
@@ -583,7 +584,7 @@ def gl_init(self, skip_fbo:bool=False) -> None:
583
584
# Bind program 0 for YUV painting by default
584
585
glBindProgramARB (GL_FRAGMENT_PROGRAM_ARB , self .shaders [YUV_to_RGB_SHADER ])
585
586
self .gl_setup = True
586
- log ("gl_init(%s) done" , skip_fbo )
587
+ log ("gl_init(%s, %s ) done" , context , skip_fbo )
587
588
588
589
def get_init_magfilter (self ) -> IntConstant :
589
590
rw , rh = self .render_size
@@ -710,7 +711,7 @@ def fail(msg):
710
711
glDisable (target )
711
712
fire_paint_callbacks (callbacks , True )
712
713
if not self .draw_needs_refresh :
713
- self .present_fbo (0 , 0 , bw , bh , flush )
714
+ self .present_fbo (context , 0 , 0 , bw , bh , flush )
714
715
715
716
def copy_fbo (self , w : int , h : int , sx : int = 0 , sy : int = 0 , dx : int = 0 , dy : int = 0 ) -> None :
716
717
log ("copy_fbo%s" , (w , h , sx , sy , dx , dy ))
@@ -742,28 +743,32 @@ def swap_fbos(self) -> None:
742
743
self .textures [TEX_TMP_FBO ] = tmp
743
744
744
745
745
- def present_fbo (self , x : int , y : int , w : int , h : int , flush = 0 ) -> None :
746
+ def present_fbo (self , context , x : int , y : int , w : int , h : int , flush = 0 ) -> None :
746
747
log ("present_fbo: adding %s to pending paint list (size=%i), flush=%s, paint_screen=%s" ,
747
748
(x , y , w , h ), len (self .pending_fbo_paint ), flush , self .paint_screen )
749
+ if not context :
750
+ raise RuntimeError ("missing OpenGL paint context" )
748
751
self .pending_fbo_paint .append ((x , y , w , h ))
749
752
if not self .paint_screen :
750
753
return
751
754
#flush>0 means we should wait for the final flush=0 paint
752
755
if flush == 0 or not PAINT_FLUSH :
753
756
self .record_fps_event ()
754
- self .managed_present_fbo ()
757
+ self .managed_present_fbo (context )
755
758
756
- def managed_present_fbo (self ) -> None :
759
+ def managed_present_fbo (self , context ) -> None :
760
+ if not context :
761
+ raise RuntimeError ("missing opengl paint context" )
757
762
try :
758
763
with paint_context_manager :
759
- self .do_present_fbo ()
764
+ self .do_present_fbo (context )
760
765
except Exception as e :
761
766
log .error ("Error presenting FBO:" )
762
767
log .estr (e )
763
768
log ("Error presenting FBO" , exc_info = True )
764
769
self .last_present_fbo_error = str (e )
765
770
766
- def do_present_fbo (self ) -> None :
771
+ def do_present_fbo (self , context ) -> None :
767
772
bw , bh = self .size
768
773
ww , wh = self .render_size
769
774
rect_count = len (self .pending_fbo_paint )
@@ -783,10 +788,10 @@ def do_present_fbo(self) -> None:
783
788
glBindFramebuffer (GL_FRAMEBUFFER , 0 )
784
789
glBindFramebuffer (GL_DRAW_FRAMEBUFFER , 0 )
785
790
786
- left , top , right , bottom = self .offsets
787
-
788
791
#viewport for clearing the whole window:
789
- glViewport (0 , 0 , left + ww + right , top + wh + bottom )
792
+ scale = context .get_scale_factor ()
793
+ left , top , right , bottom = self .offsets
794
+ glViewport (0 , 0 , int ((left + ww + right )* scale ), int ((top + wh + bottom )* scale ))
790
795
if self ._alpha_enabled :
791
796
# transparent background:
792
797
glClearColor (0.0 , 0.0 , 0.0 , 0.0 )
@@ -796,10 +801,12 @@ def do_present_fbo(self) -> None:
796
801
if left or top or right or bottom :
797
802
self .gl_clear_color_buffer ()
798
803
799
- #from now on, take the offsets into account:
800
- glViewport (left , top , ww , wh )
804
+ #from now on, take the offsets and scaling into account:
805
+ viewport = int (left * scale ), int (top * scale ), int (ww * scale ), int (wh * scale )
806
+ log (f"window viewport for { self .render_size = } and { self .offsets } with scale factor { scale } : { viewport } " )
807
+ glViewport (* viewport )
801
808
target = GL_TEXTURE_RECTANGLE_ARB
802
- if ww != bw or wh != bh :
809
+ if ww != bw or wh != bh or scale != 1 :
803
810
glTexParameteri (target , GL_TEXTURE_MAG_FILTER , GL_LINEAR )
804
811
glTexParameteri (target , GL_TEXTURE_MIN_FILTER , GL_LINEAR )
805
812
@@ -1006,7 +1013,7 @@ def set_cursor_data(self, cursor_data) -> None:
1006
1013
pixels = cursor_data [8 ]
1007
1014
def gl_upload_cursor (context ):
1008
1015
if context :
1009
- self .gl_init ()
1016
+ self .gl_init (context )
1010
1017
self .upload_rgba_texture (self .textures [TEX_CURSOR ], cw , ch , pixels )
1011
1018
self .with_gl_context (gl_upload_cursor )
1012
1019
@@ -1119,9 +1126,9 @@ def paint_nvdec(gl_context):
1119
1126
self .idle_add (self .do_paint_rgb , rgb_format , img .get_pixels (), x , y , w , h , width , height ,
1120
1127
img .get_rowstride (), options , callbacks )
1121
1128
1122
- def cuda_buffer_to_pbo (self , cuda_buffer , rowstride :int , src_y :int , height :int , stream ):
1129
+ def cuda_buffer_to_pbo (self , gl_context , cuda_buffer , rowstride :int , src_y :int , height :int , stream ):
1123
1130
#must be called with an active cuda context, and from the UI thread
1124
- self .gl_init ()
1131
+ self .gl_init (gl_context )
1125
1132
pbo = glGenBuffers (1 )
1126
1133
size = rowstride * height
1127
1134
glBindBuffer (GL_PIXEL_UNPACK_BUFFER , pbo )
@@ -1169,8 +1176,8 @@ def paint_nvdec(self, gl_context, encoding, img_data, x : int, y : int, width :
1169
1176
strides = img .get_rowstride ()
1170
1177
height = img .get_height ()
1171
1178
try :
1172
- y_pbo = self .cuda_buffer_to_pbo (cuda_buffer , strides [0 ], 0 , height , stream )
1173
- uv_pbo = self .cuda_buffer_to_pbo (cuda_buffer , strides [1 ], roundup (height , 2 ), height // 2 , stream )
1179
+ y_pbo = self .cuda_buffer_to_pbo (gl_context , cuda_buffer , strides [0 ], 0 , height , stream )
1180
+ uv_pbo = self .cuda_buffer_to_pbo (gl_context , cuda_buffer , strides [1 ], roundup (height , 2 ), height // 2 , stream )
1174
1181
except LogicError as e :
1175
1182
#disable nvdec from now on:
1176
1183
self .nvdec_decoder = None
@@ -1203,7 +1210,7 @@ def paint_nvjpeg(self, gl_context, encoding, img_data, x : int, y : int, width :
1203
1210
raise ValueError (f"unexpected rgb format { rgb_format } " )
1204
1211
#'pixels' is a cuda buffer:
1205
1212
cuda_buffer = img .get_pixels ()
1206
- pbo = self .cuda_buffer_to_pbo (cuda_buffer , img .get_rowstride (), 0 , img .get_height (), stream )
1213
+ pbo = self .cuda_buffer_to_pbo (gl_context , cuda_buffer , img .get_rowstride (), 0 , img .get_height (), stream )
1207
1214
cuda_buffer .free ()
1208
1215
1209
1216
pformat = PIXEL_FORMAT_TO_CONSTANT [rgb_format ]
@@ -1235,7 +1242,7 @@ def paint_nvjpeg(self, gl_context, encoding, img_data, x : int, y : int, width :
1235
1242
self .paint_box (encoding , x , y , width , height )
1236
1243
# Present update to screen
1237
1244
if not self .draw_needs_refresh :
1238
- self .present_fbo (x , y , width , height , options .intget ("flush" , 0 ))
1245
+ self .present_fbo (gl_context , x , y , width , height , options .intget ("flush" , 0 ))
1239
1246
# present_fbo has reset state already
1240
1247
fire_paint_callbacks (callbacks )
1241
1248
glDeleteBuffers (1 , [pbo ])
@@ -1293,7 +1300,7 @@ def gl_paint_rgb(self, context, rgb_format:str, img_data,
1293
1300
try :
1294
1301
upload , img_data = self .pixels_for_upload (img_data )
1295
1302
1296
- self .gl_init ()
1303
+ self .gl_init (context )
1297
1304
scaling = width != render_width or height != render_height
1298
1305
1299
1306
#convert it to a GL constant:
@@ -1339,7 +1346,7 @@ def gl_paint_rgb(self, context, rgb_format:str, img_data,
1339
1346
self .paint_box (options .strget ("encoding" ), x , y , render_width , render_height )
1340
1347
# Present update to screen
1341
1348
if not self .draw_needs_refresh :
1342
- self .present_fbo (x , y , render_width , render_height , options .intget ("flush" , 0 ))
1349
+ self .present_fbo (context , x , y , render_width , render_height , options .intget ("flush" , 0 ))
1343
1350
# present_fbo has reset state already
1344
1351
fire_paint_callbacks (callbacks )
1345
1352
return
@@ -1404,7 +1411,7 @@ def do_gl_paint_planar(self, context, shader, flush:int, encoding:str, img,
1404
1411
log ("%s._do_paint_rgb(..) no OpenGL context!" , self )
1405
1412
fire_paint_callbacks (callbacks , False , "failed to get a gl context" )
1406
1413
return
1407
- self .gl_init ()
1414
+ self .gl_init (context )
1408
1415
scaling = enc_width != width or enc_height != height
1409
1416
self .update_planar_textures (enc_width , enc_height , img , pixel_format , scaling = scaling , pbo = options .get ("pbo" ))
1410
1417
@@ -1419,7 +1426,7 @@ def do_gl_paint_planar(self, context, shader, flush:int, encoding:str, img,
1419
1426
fire_paint_callbacks (callbacks , True )
1420
1427
# Present it on screen
1421
1428
if not self .draw_needs_refresh :
1422
- self .present_fbo (x , y , width , height , flush )
1429
+ self .present_fbo (context , x , y , width , height , flush )
1423
1430
img .free ()
1424
1431
return
1425
1432
except GLError as e :
@@ -1578,6 +1585,6 @@ def gl_expose_rect(self, rect=None) -> None:
1578
1585
rect = (0 , 0 , w , h )
1579
1586
def expose (context ):
1580
1587
if context :
1581
- self .gl_init ()
1582
- self .present_fbo (* rect )
1588
+ self .gl_init (context )
1589
+ self .present_fbo (context , * rect )
1583
1590
self .with_gl_context (expose )
0 commit comments