xpra icon
Bug tracker and wiki

Ticket #229: gl-check-thread.patch

File gl-check-thread.patch, 5.2 KB (added by Antoine Martin, 7 years ago)

ensures we call gtk/gl code only from the UI thread and that decode is not from UI thread

  • xpra/gl/gl_client_window.py

     
    66
    77from wimpiggy.log import Logger
    88log = Logger()
     9import threading
    910
    1011from xpra.client_window import ClientWindow
    1112from xpra.gl.gl_window_backing import GLPixmapBacking
     
    2021        ClientWindow.__init__(self, client, group_leader, wid, x, y, w, h, metadata, override_redirect, client_properties, auto_refresh_delay)
    2122        self.set_reallocate_redraws(True)
    2223        self.add(self._backing.glarea)
     24        self.UI_thread = threading.currentThread()
    2325
    2426    def is_GL(self):
    2527        return True
     
    2830        log("GL do_configure_event(%s)", event)
    2931        ClientWindow.do_configure_event(self, event)
    3032        self._backing.paint_screen = True
     33        assert self.UI_thread == threading.currentThread()
    3134
    3235    def destroy(self):
    3336        self._backing.paint_screen = False
    3437        ClientWindow.destroy(self)
     38        assert self.UI_thread == threading.currentThread()
    3539
    3640    def new_backing(self, w, h):
    3741        log("GL new_backing(%s, %s)", w, h)
  • xpra/gl/gl_window_backing.py

     
    1010assert gtk.gdkgl is not None and gtk.gtkgl is not None
    1111import gobject
    1212import os
     13import threading
    1314
    1415from wimpiggy.log import Logger
    1516log = Logger()
     
    6162        self.gl_setup = False
    6263        self.paint_screen = False
    6364        self._video_use_swscale = False
     65        self.UI_thread = threading.currentThread()
    6466
    6567    def init(self, w, h):
     68        assert self.UI_thread == threading.currentThread()
    6669        #re-init gl context with new dimensions:
    6770        self.gl_setup = False
    6871        self.size = w, h
     
    7376        PixmapBacking.init(self, w, h)
    7477
    7578    def gl_init(self):
     79        assert self.UI_thread == threading.currentThread()
    7680        drawable = self.gl_begin()
    7781        w, h = self.size
    7882        debug("GL Pixmap backing size: %d x %d, drawable=%s", w, h, drawable)
     
    9498        return drawable
    9599
    96100    def close(self):
     101        assert self.UI_thread == threading.currentThread()
    97102        PixmapBacking.close(self)
    98103        self.remove_shader()
    99104        self.glarea = None
    100105        self.glconfig = None
    101106
    102107    def remove_shader(self):
     108        assert self.UI_thread == threading.currentThread()
    103109        if self.yuv_shader:
    104110            drawable = self.gl_init()
    105111            if drawable:
     
    111117            self.yuv_shader = None
    112118
    113119    def gl_begin(self):
     120        assert self.UI_thread == threading.currentThread()
    114121        if self.glarea is None:
    115122            return None     #closed already
    116123        drawable = self.glarea.get_gl_drawable()
     
    124131        return drawable
    125132
    126133    def gl_end(self, drawable):
     134        assert self.UI_thread == threading.currentThread()
    127135        if drawable.is_double_buffered():
    128136            drawable.swap_buffers()
    129137        else:
     
    131139        drawable.gl_end()
    132140
    133141    def gl_expose_event(self, glarea, event):
     142        assert self.UI_thread == threading.currentThread()
    134143        debug("gl_expose_event(%s, %s)", glarea, event)
    135144        area = event.area
    136145        x, y, w, h = area.x, area.y, area.width, area.height
     
    143152                self.gl_end(drawable)
    144153
    145154    def _do_paint_rgb24(self, img_data, x, y, width, height, rowstride, options, callbacks):
     155        assert self.UI_thread == threading.currentThread()
    146156        gc = self._backing.new_gc()
    147157        self.glarea.window.draw_rgb_image(gc, x, y, width, height, gdk.RGB_DITHER_NONE, img_data, rowstride)
    148158
    149159    def do_video_paint(self, coding, img_data, x, y, w, h, options, callbacks):
     160        assert self.UI_thread != threading.currentThread()
    150161        debug("do_video_paint: options=%s, decoder=%s", options, type(self._video_decoder))
    151162        err, rowstrides, img_data = self._video_decoder.decompress_image_to_yuv(img_data, options)
    152163        csc_pixel_format = options.get("csc_pixel_format", -1)
     
    161172        gobject.idle_add(self.do_gl_paint, x, y, w, h, img_data, rowstrides, pixel_format, callbacks)
    162173
    163174    def do_gl_paint(self, x, y, w, h, img_data, rowstrides, pixel_format, callbacks):
     175        assert self.UI_thread == threading.currentThread()
    164176        #this function runs in the UI thread, no video_decoder lock held
    165177        drawable = self.gl_init()
    166178        if not drawable:
     
    192204        raise Exception("invalid pixel format: %s" % pixel_format)
    193205
    194206    def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format):
     207        assert self.UI_thread == threading.currentThread()
    195208        window_width, window_height = self.size
    196209        assert self.textures is not None, "no OpenGL textures!"
    197210
     
    253266        glFlush()
    254267
    255268    def render_image(self, rx, ry, rw, rh):
     269        assert self.UI_thread == threading.currentThread()
    256270        debug("render_image %sx%s at %sx%s pixel_format=%s", rw, rh, rx, ry, self.pixel_format)
    257271        if self.pixel_format not in (YUV420P, YUV422P, YUV444P):
    258272            #not ready to render yet