Skip to content

Commit

Permalink
simplify opengl paint now that we have the rgb_format passed down, su…
Browse files Browse the repository at this point in the history
…ccess 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
  • Loading branch information
totaam committed Jul 16, 2016
1 parent bcefd9e commit b76dbf8
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 82 deletions.
144 changes: 66 additions & 78 deletions src/xpra/client/gl/gl_window_backing_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of Xpra.
# Copyright (C) 2013 Serviware (Arthur Huillet, <ahuillet@serviware.com>)
# Copyright (C) 2012-2015 Antoine Martin <antoine@devloop.org.uk>
# Copyright (C) 2012-2016 Antoine Martin <antoine@devloop.org.uk>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/xpra/client/gtk2/pixmap_backing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of Xpra.
# Copyright (C) 2008 Nathaniel Smith <njs@pobox.com>
# Copyright (C) 2012-2015 Antoine Martin <antoine@devloop.org.uk>
# Copyright (C) 2012-2016 Antoine Martin <antoine@devloop.org.uk>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

Expand Down Expand Up @@ -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"):
Expand Down
4 changes: 2 additions & 2 deletions src/xpra/client/window_backing_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit b76dbf8

Please sign in to comment.