xpra icon
Bug tracker and wiki

Ticket #385: opengl-transparency-v5.patch

File opengl-transparency-v5.patch, 11.2 KB (added by Antoine Martin, 6 years ago)

working patch for posix clients (win32 broken)

  • xpra/client/gl/gl_check.py

     
    1919
    2020BLACKLIST = {"vendor" : ["nouveau", "Humper"]}
    2121
    22 #needed on win32?
    23 DEFAULT_DOUBLE_BUFFERED=0
     22DEFAULT_DOUBLE_BUFFERED = 0
     23DEFAULT_ALPHA = 1
    2424if sys.platform.startswith("win"):
    25     DEFAULT_DOUBLE_BUFFERED=1
     25    #needed on win32?
     26    DEFAULT_DOUBLE_BUFFERED = 1
     27    #does not work on win32:
     28    DEFAULT_ALPHA = 1
    2629DOUBLE_BUFFERED = os.environ.get("XPRA_OPENGL_DOUBLE_BUFFERED", str(DEFAULT_DOUBLE_BUFFERED))=="1"
     30ALPHA = os.environ.get("XPRA_OPENGL_ALPHA", str(DEFAULT_ALPHA))=="1"
    2731
    2832
    2933def get_DISPLAY_MODE():
    3034    import gtk.gdkgl
    31     #return  gtk.gdkgl.MODE_RGB | gtk.gdkgl.MODE_DEPTH | gtk.gdkgl.MODE_DOUBLE
     35    #gtk.gdkgl.MODE_DEPTH
     36    mode = 0
     37    if ALPHA:
     38        mode = mode | gtk.gdkgl.MODE_RGBA | gtk.gdkgl.MODE_ALPHA
     39    else:
     40        mode = mode | gtk.gdkgl.MODE_RGB
    3241    if DOUBLE_BUFFERED:
    33         return  gtk.gdkgl.MODE_RGB | gtk.gdkgl.MODE_DOUBLE
    34     return  gtk.gdkgl.MODE_RGB | gtk.gdkgl.MODE_SINGLE
     42        mode = mode | gtk.gdkgl.MODE_DOUBLE
     43    else:
     44        mode = mode | gtk.gdkgl.MODE_SINGLE
     45    return mode
    3546
     47def get_MODE_names(mode):
     48    import gtk.gdkgl
     49    friendly_mode_names = {gtk.gdkgl.MODE_RGB       : "RGB",
     50                           gtk.gdkgl.MODE_RGB       : "RGBA",
     51                           gtk.gdkgl.MODE_ALPHA     : "ALPHA",
     52                           gtk.gdkgl.MODE_DEPTH     : "DEPTH",
     53                           gtk.gdkgl.MODE_DOUBLE    : "DOUBLE",
     54                           gtk.gdkgl.MODE_SINGLE    : "SINGLE"}
     55    friendly_modes = [v for k,v in friendly_mode_names.items() if k>0 and (k&mode)==k]
     56    #special case for single (value is zero!)
     57    if not (mode&gtk.gdkgl.MODE_DOUBLE==gtk.gdkgl.MODE_DOUBLE):
     58        friendly_modes.append("SINGLE")
     59    return friendly_modes
     60
     61
    3662#by default, we raise an ImportError as soon as we find something missing:
    3763def raise_error(msg):
    3864    raise ImportError(msg)
     
    213239    display_mode = get_DISPLAY_MODE()
    214240    try:
    215241        glconfig = gtk.gdkgl.Config(mode=display_mode)
    216     except gtk.gdkgl.NoMatches:
     242    except gtk.gdkgl.NoMatches, e:
     243        debug("no match: %s, toggling double-buffering", e)
    217244        display_mode &= ~gtk.gdkgl.MODE_DOUBLE
    218245        glconfig = gtk.gdkgl.Config(mode=display_mode)
    219     friendly_mode_names = {gtk.gdkgl.MODE_RGB       : "RGB",
    220                            gtk.gdkgl.MODE_DEPTH     : "DEPTH",
    221                            gtk.gdkgl.MODE_DOUBLE    : "DOUBLE",
    222                            gtk.gdkgl.MODE_SINGLE    : "SINGLE"}
    223     friendly_modes = [v for k,v in friendly_mode_names.items() if (k&display_mode)==k]
    224     debug("using display mode: %s", friendly_modes)
    225     props["display_mode"] = friendly_modes
     246    props["display_mode"] = get_MODE_names(display_mode)
    226247    props["glconfig"] = glconfig
     248    props["has_alpha"] = glconfig.has_alpha()
     249    props["rgba"] = glconfig.is_rgba()
     250    debug("GL props=%s", props)
    227251    assert gtk.gdkgl.query_extension()
    228252    glcontext, gldrawable, glext, w = None, None, None, None
    229253    try:
  • xpra/client/gl/gl_window_backing.py

     
    2222from OpenGL.GL import GL_PROJECTION, GL_MODELVIEW, \
    2323    GL_UNPACK_ROW_LENGTH, GL_UNPACK_ALIGNMENT, \
    2424    GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_NEAREST, \
    25     GL_UNSIGNED_BYTE, GL_LUMINANCE, GL_RGB, GL_LINEAR, \
     25    GL_UNSIGNED_BYTE, GL_LUMINANCE, GL_RGB, GL_RGBA, GL_LINEAR, \
    2626    GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_QUADS, GL_COLOR_BUFFER_BIT, \
    27     GL_DONT_CARE, GL_TRUE,\
     27    GL_DONT_CARE, GL_TRUE, \
     28    GL_BLEND, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, \
    2829    glActiveTexture, glTexSubImage2D, \
    2930    glGetString, glViewport, glMatrixMode, glLoadIdentity, glOrtho, \
    3031    glGenTextures, glDisable, \
    3132    glBindTexture, glPixelStorei, glEnable, glBegin, glFlush, \
     33    glBlendFunc, \
    3234    glTexParameteri, \
    3335    glTexImage2D, \
    3436    glMultiTexCoord2i, \
     
    7981#  3 = V plane
    8082#  4 = RGB updates
    8183#  5 = FBO texture (guaranteed up-to-date window contents)
     84# The first four are used to update the FBO,
     85# the FBO is what is painted on screen.
    8286TEX_Y = 0
    8387TEX_U = 1
    8488TEX_V = 2
     
    108112        self._backing = gtk.gtkgl.DrawingArea(self.glconfig)
    109113        #restoring missed masks:
    110114        self._backing.set_events(self._backing.get_events() | gdk.POINTER_MOTION_MASK | gdk.POINTER_MOTION_HINT_MASK)
     115        rgba = self._backing.get_screen().get_rgba_colormap()
     116        if rgba:
     117            self._backing.set_colormap(rgba)
    111118        self._backing.show()
    112119        self._backing.connect("expose_event", self.gl_expose_event)
    113120        self.textures = None # OpenGL texture IDs
     
    189196            # glEnableClientState(GL_VERTEX_ARRAY)
    190197            # glEnableClientState(GL_TEXTURE_COORD_ARRAY)
    191198
    192             # Clear to white
    193             glClearColor(1.0, 1.0, 1.0, 1.0)
     199            # Clear background to transparent white
     200            glClearColor(1.0, 1.0, 1.0, 0.0)
    194201
    195202            # Default state is good for YUV painting:
    196203            #  - fragment program enabled
     
    205212
    206213            # Define empty FBO texture and set rendering to FBO
    207214            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO])
    208             glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, None)
     215            glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, None)
    209216            glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo)
    210217            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0)
    211218            glClear(GL_COLOR_BUFFER_BIT)
     
    246253            return None
    247254        return drawable
    248255
    249     def set_rgb24_paint_state(self):
    250         # Set GL state for RGB24 painting:
     256    def set_rgb_paint_state(self):
     257        # Set GL state for RGB painting:
    251258        #    no fragment program
    252259        #    only tex unit #0 active
    253         self.gl_marker("Switching to RGB24 paint state")
     260        self.gl_marker("Switching to RGB paint state")
    254261        glDisable(GL_FRAGMENT_PROGRAM_ARB);
    255262        for texture in (GL_TEXTURE1, GL_TEXTURE2):
    256263            glActiveTexture(texture)
     
    258265        glActiveTexture(GL_TEXTURE0);
    259266        glEnable(GL_TEXTURE_RECTANGLE_ARB)
    260267
    261     def unset_rgb24_paint_state(self):
     268    def unset_rgb_paint_state(self):
    262269        # Reset state to our default
    263270        self.gl_marker("Switching back to YUV paint state")
    264271        glEnable(GL_FRAGMENT_PROGRAM_ARB)
     
    274281        glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, self.shaders[0])
    275282
    276283    def present_fbo(self, drawable):
     284        debug("present_fbo(%s)", drawable)
    277285        self.gl_marker("Presenting FBO on screen for drawable %s" % drawable)
    278286        assert drawable
    279287        # Change state to target screen instead of our FBO
    280288        glBindFramebuffer(GL_FRAMEBUFFER, 0)
    281289
     290        # transparent background:
     291        glClearColor(1.0, 0.0, 1.0, 0)
     292
    282293        # Draw FBO texture on screen
    283         self.set_rgb24_paint_state()
     294        self.set_rgb_paint_state()
    284295
    285296        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO])
     297        # support alpha channel if present:
     298        glEnable(GL_BLEND)
     299        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    286300
    287301        w, h = self.size
    288302        glBegin(GL_QUADS)
     
    306320            glFlush()
    307321        self.gl_frame_terminator()
    308322
    309         self.unset_rgb24_paint_state()
     323        self.unset_rgb_paint_state()
    310324        glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo)
    311325        debug("%s.present_fbo() done", self)
    312326
     
    320334        finally:
    321335            drawable.gl_end()
    322336
    323     def _do_paint_rgb32(self, *args):
    324         #FIXME #385: add transparency to GL
    325         raise Exception("bug: it should be impossible to get here: gl backing does not handle transparency")
     337    def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options, callbacks):
     338        self._do_paint_rgb(32, img_data, x, y, width, height, rowstride, options, callbacks)
    326339
    327340    def _do_paint_rgb24(self, img_data, x, y, width, height, rowstride, options, callbacks):
    328         debug("%s._do_paint_rgb24(x=%d, y=%d, width=%d, height=%d, rowstride=%d)", self, x, y, width, height, rowstride)
     341        self._do_paint_rgb(24, img_data, x, y, width, height, rowstride, options, callbacks)
     342
     343    def _do_paint_rgb(self, bpp, img_data, x, y, width, height, rowstride, options, callbacks):
     344        debug("%s._do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d)", self, bpp, len(img_data), x, y, width, height, rowstride)
    329345        drawable = self.gl_init()
    330346        if not drawable:
    331             debug("%s._do_paint_rgb24(..) drawable is not set!", self)
     347            debug("%s._do_paint_rgb(..) drawable is not set!", self)
    332348            return False
    333349
    334350        try:
    335             self.set_rgb24_paint_state()
     351            self.set_rgb_paint_state()
    336352
     353            bytes_per_pixel = bpp/8
    337354            # Compute alignment and row length
    338355            row_length = 0
    339356            alignment = 1
     
    344361            # If number of extra bytes is greater than the alignment value,
    345362            # then we also have to set row_length
    346363            # Otherwise it remains at 0 (= width implicitely)
    347             if (rowstride - width * 3) > a:
    348                 row_length = width + (rowstride - width * 3) / 3
     364            if (rowstride - width * bytes_per_pixel) > a:
     365                row_length = width + (rowstride - width * bytes_per_pixel) / bytes_per_pixel
    349366
    350             self.gl_marker("RGB24 update at %d,%d, size %d,%d, stride is %d, row length %d, alignment %d" % (x, y, width, height, rowstride, row_length, alignment))
     367            self.gl_marker("RGB%s update at %d,%d, size %d,%d, stride is %d, row length %d, alignment %d" % (bpp, x, y, width, height, rowstride, row_length, alignment))
    351368            # Upload data as temporary RGB texture
     369            if bpp==24:
     370                pformat = GL_RGB
     371            else:
     372                assert bpp==32
     373                pformat = GL_RGBA
     374                #TODO: handle BGRA as input directly!
     375
    352376            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB])
    353377            glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length)
    354378            glPixelStorei(GL_UNPACK_ALIGNMENT, alignment)
    355379            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    356380            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    357             glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)
     381            glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data)
    358382
    359383            # Draw textured RGB quad at the right coordinates
    360384            glBegin(GL_QUADS)
     
    371395            # Present update to screen
    372396            self.present_fbo(drawable)
    373397            # present_fbo has reset state already
    374 
    375398        finally:
    376399            drawable.gl_end()
    377400        return True