From b76dbf8553c8f2e9236627493d9e17042ce988f4 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sat, 16 Jul 2016 10:14:25 +0000 Subject: [PATCH] simplify opengl paint now that we have the rgb_format passed down, success arg to fire_paint_callbacks status now defaults to true git-svn-id: https://xpra.org/svn/Xpra/trunk@13026 3bb7dfac-3a0b-4e04-842a-767bc560f471 --- src/xpra/client/gl/gl_window_backing_base.py | 144 +++++++++---------- src/xpra/client/gtk2/pixmap_backing.py | 4 +- src/xpra/client/window_backing_base.py | 4 +- 3 files changed, 70 insertions(+), 82 deletions(-) diff --git a/src/xpra/client/gl/gl_window_backing_base.py b/src/xpra/client/gl/gl_window_backing_base.py index 6d79025189..b711a2d35c 100644 --- a/src/xpra/client/gl/gl_window_backing_base.py +++ b/src/xpra/client/gl/gl_window_backing_base.py @@ -1,6 +1,6 @@ # This file is part of Xpra. # Copyright (C) 2013 Serviware (Arthur Huillet, ) -# Copyright (C) 2012-2015 Antoine Martin +# Copyright (C) 2012-2016 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -717,87 +717,75 @@ def pixels_for_upload(self, img_data): return "copy:str", img_data - def _do_paint_rgb32(self, img_data, x, y, width, height, rowstride, options): - return self._do_paint_rgb(32, img_data, x, y, width, height, rowstride, options) - - def _do_paint_rgb24(self, img_data, x, y, width, height, rowstride, options): - return self._do_paint_rgb(24, img_data, x, y, width, height, rowstride, options) - - def _do_paint_rgb(self, bpp, img_data, x, y, width, height, rowstride, options): - log("%s._do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d, options=%s)", self, bpp, len(img_data), x, y, width, height, rowstride, options) + def do_paint_rgb(self, rgb_format, img_data, x, y, width, height, rowstride, options, callbacks): + log("%s.do_paint_rgb(%s, %s bytes, x=%d, y=%d, width=%d, height=%d, rowstride=%d, options=%s)", self, rgb_format, len(img_data), x, y, width, height, rowstride, options) context = self.gl_context() if not context: log("%s._do_paint_rgb(..) no context!", self) - return False - - #TODO: move this code up to the decode thread section - upload, img_data = self.pixels_for_upload(img_data) - - with context: - self.gl_init() - self.set_rgb_paint_state() - - rgb_format = options.get(b"rgb_format") - if not rgb_format: - #Older servers may not tell us the pixel format, so we must infer it: - if bpp==24: - rgb_format = "RGB" - else: - assert bpp==32 - rgb_format = "RGBA" - else: - rgb_format = rgb_format.decode() - #convert it to a GL constant: - pformat = PIXEL_FORMAT_TO_CONSTANT.get(rgb_format) - assert pformat is not None, "could not find pixel format for %s (bpp=%s)" % (rgb_format, bpp) - - bytes_per_pixel = len(rgb_format) #ie: BGRX -> 4 - # Compute alignment and row length - row_length = 0 - alignment = 1 - for a in [2, 4, 8]: - # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on - if (rowstride & a-1) == 0: - alignment = a - # If number of extra bytes is greater than the alignment value, - # then we also have to set row_length - # Otherwise it remains at 0 (= width implicitely) - if (rowstride - width * bytes_per_pixel) >= alignment: - row_length = width + (rowstride - width * bytes_per_pixel) // bytes_per_pixel - - self.gl_marker("%s %sbpp update at (%d,%d) size %dx%d (%s bytes), stride=%d, row length %d, alignment %d, using GL %s format=%s", - rgb_format, bpp, x, y, width, height, len(img_data), rowstride, row_length, alignment, upload, CONSTANT_TO_PIXEL_FORMAT.get(pformat)) - - # Upload data as temporary RGB texture - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) - glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0) - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAX_LEVEL, 0) - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) - - # Draw textured RGB quad at the right coordinates - glBegin(GL_QUADS) - glTexCoord2i(0, 0) - glVertex2i(x, y) - glTexCoord2i(0, height) - glVertex2i(x, y+height) - glTexCoord2i(width, height) - glVertex2i(x+width, y+height) - glTexCoord2i(width, 0) - glVertex2i(x+width, y) - glEnd() - - self.paint_box(options.get("encoding"), options.get("delta", -1)>=0, x, y, width, height) + fire_paint_callbacks(callbacks, False, "no opengl context") + return - # Present update to screen - self.present_fbo(x, y, width, height, options.get("flush", 0)) - # present_fbo has reset state already - return True + try: + upload, img_data = self.pixels_for_upload(img_data) + + with context: + self.gl_init() + self.set_rgb_paint_state() + + #convert it to a GL constant: + pformat = PIXEL_FORMAT_TO_CONSTANT.get(rgb_format.decode()) + assert pformat is not None, "could not find pixel format for %s" % rgb_format + + bytes_per_pixel = len(rgb_format) #ie: BGRX -> 4 + # Compute alignment and row length + row_length = 0 + alignment = 1 + for a in [2, 4, 8]: + # Check if we are a-aligned - ! (var & 0x1) means 2-aligned or better, 0x3 - 4-aligned and so on + if (rowstride & a-1) == 0: + alignment = a + # If number of extra bytes is greater than the alignment value, + # then we also have to set row_length + # Otherwise it remains at 0 (= width implicitely) + if (rowstride - width * bytes_per_pixel) >= alignment: + row_length = width + (rowstride - width * bytes_per_pixel) // bytes_per_pixel + + self.gl_marker("%s update at (%d,%d) size %dx%d (%s bytes), stride=%d, row length %d, alignment %d, using GL %s format=%s", + rgb_format, x, y, width, height, len(img_data), rowstride, row_length, alignment, upload, CONSTANT_TO_PIXEL_FORMAT.get(pformat)) + + # Upload data as temporary RGB texture + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_RGB]) + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length) + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment) + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0) + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAX_LEVEL, 0) + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER) + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER) + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, self.texture_pixel_format, width, height, 0, pformat, GL_UNSIGNED_BYTE, img_data) + + # Draw textured RGB quad at the right coordinates + glBegin(GL_QUADS) + glTexCoord2i(0, 0) + glVertex2i(x, y) + glTexCoord2i(0, height) + glVertex2i(x, y+height) + glTexCoord2i(width, height) + glVertex2i(x+width, y+height) + glTexCoord2i(width, 0) + glVertex2i(x+width, y) + glEnd() + + self.paint_box(options.get("encoding"), options.get("delta", -1)>=0, x, y, width, height) + + # Present update to screen + self.present_fbo(x, y, width, height, options.get("flush", 0)) + # present_fbo has reset state already + fire_paint_callbacks(callbacks) + except Exception as e: + log("Error in %s paint of %i bytes, options=%s)", rgb_format, len(img_data), options) + fire_paint_callbacks(callbacks, False, "opengl %s paint error: %s" % (rgb_format, e)) def do_video_paint(self, img, x, y, enc_width, enc_height, width, height, options, callbacks): #copy so the data will be usable (usually a str) diff --git a/src/xpra/client/gtk2/pixmap_backing.py b/src/xpra/client/gtk2/pixmap_backing.py index 9b851c9982..f06a1a2239 100644 --- a/src/xpra/client/gtk2/pixmap_backing.py +++ b/src/xpra/client/gtk2/pixmap_backing.py @@ -1,6 +1,6 @@ # This file is part of Xpra. # Copyright (C) 2008 Nathaniel Smith -# Copyright (C) 2012-2015 Antoine Martin +# Copyright (C) 2012-2016 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -114,7 +114,7 @@ def do_paint_scroll(self, x, y, w, h, scrolls, options, callbacks): gc = self._backing.new_gc() for sx,sy,sw,sh,xdelta,ydelta in scrolls: self._backing.draw_drawable(gc, self._backing, sx, sy, sx+xdelta, sy+ydelta, sw, sh) - fire_paint_callbacks(callbacks, True) + fire_paint_callbacks(callbacks) def bgr_to_rgb(self, img_data, width, height, rowstride, rgb_format, target_format): if not rgb_format.startswith("BGR"): diff --git a/src/xpra/client/window_backing_base.py b/src/xpra/client/window_backing_base.py index 783799262b..088e84c077 100644 --- a/src/xpra/client/window_backing_base.py +++ b/src/xpra/client/window_backing_base.py @@ -55,7 +55,7 @@ def load_video_decoders(): return VIDEO_DECODERS -def fire_paint_callbacks(callbacks, success, message=""): +def fire_paint_callbacks(callbacks, success=True, message=""): for x in callbacks: try: x(success, message) @@ -379,7 +379,7 @@ def paint_with_video_decoder(self, decoder_module, coding, img_data, x, y, width if options.get("delayed", 0)>0: #there are further frames queued up, #and this frame references those, so assume all is well: - fire_paint_callbacks(callbacks, True) + fire_paint_callbacks(callbacks) else: fire_paint_callbacks(callbacks, False, "video decoder %s failed to decode %i bytes of %s data" % (vd.get_type(), len(img_data), coding)) log.error("Error: decode failed on %s bytes of %s data", len(img_data), coding)