def do_present_fbo(self): bw, bh = self.size ww, wh = self.render_size self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) left, top, right, bottom = self.offsets #viewport for clearing the whole window: glViewport(0, 0, left+ww+right, top+wh+bottom) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # black, no alpha: glClearColor(0.0, 0.0, 0.0, 1.0) if left or top or right or bottom: try: glClear(GL_COLOR_BUFFER_BIT) except: log("ignoring glClear(GL_COLOR_BUFFER_BIT) error, buggy driver?", exc_info=True) #viewport for painting to window: glViewport(left, top, ww, wh) # Draw FBO texture on screen self.set_rgb_paint_state() rect_count = len(self.pending_fbo_paint) if self.glconfig.is_double_buffered() or bw!=ww or bh!=wh: #refresh the whole window: rectangles = ((0, 0, bw, bh), ) else: #paint just the rectangles we have accumulated: rectangles = self.pending_fbo_paint self.pending_fbo_paint = [] log("do_present_fbo: painting %s", rectangles) glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) if SAVE_BUFFERS: glBindFramebuffer(GL_READ_FRAMEBUFFER, self.offscreen_fbo) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glReadBuffer(GL_COLOR_ATTACHMENT0) glViewport(0, 0, bw, bh) from OpenGL.GL import glGetTexImage size = bw*bh*4 import numpy data = numpy.empty(size) img_data = glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, GL_UNSIGNED_BYTE, data) from PIL import Image, ImageOps img = Image.frombuffer("RGBA", (bw, bh), img_data, "raw", "BGRA", bw*4) img = ImageOps.flip(img) kwargs = {} if SAVE_BUFFERS=="jpeg": kwargs = { "quality" : 0, "optimize" : False, } t = time.time() tstr = time.strftime("%H-%M-%S", time.localtime(t)) filename = "./W%i-FBO-%s.%03i.%s" % (self.wid, tstr, (t*1000)%1000, SAVE_BUFFERS) log("do_present_fbo: saving %4ix%-4i pixels, %7i bytes to %s", bw, bh, size, filename) img.save(filename, SAVE_BUFFERS, **kwargs) glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) if ww!=bw or wh!=bh: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBegin(GL_QUADS) for x,y,w,h in rectangles: #note how we invert coordinates.. tx1, ty1, tx2, ty2 = x, bh-y, x+w, bh-y-h vx1, vy1, vx2, vy2 = x, y, x+w, y+h glTexCoord2i(tx1, ty1) glVertex2i(vx1, vy1) #top-left of window viewport glTexCoord2i(tx1, ty2) glVertex2i(vx1, vy2) #bottom-left of window viewport glTexCoord2i(tx2, ty2) glVertex2i(vx2, vy2) #bottom-right of window viewport glTexCoord2i(tx2, ty1) glVertex2i(vx2, vy1) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) if self.paint_spinner: #add spinner: dim = min(bw/3.0, bh/3.0) t = time.time() count = int(t*4.0) bx = bw//2 by = bh//2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count%8][i] glColor4f(c, c, c, 1) mi1 = math.pi*i/4-math.pi/16 mi2 = math.pi*i/4+math.pi/16 glVertex2i(int(bx+math.sin(mi1)*10), int(by+math.cos(mi1)*10)) glVertex2i(int(bx+math.sin(mi1)*dim), int(by+math.cos(mi1)*dim)) glVertex2i(int(bx+math.sin(mi2)*dim), int(by+math.cos(mi2)*dim)) glVertex2i(int(bx+math.sin(mi2)*10), int(by+math.cos(mi2)*10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size*2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px,py in ((0, 0), (bw, 0), (bw, bh), (0, bh)): glVertex2i(px, py) glEnd() if self.pointer_overlay: x, y, _, _, size, start_time = self.pointer_overlay elapsed = time.time()-start_time if elapsed<6: alpha = max(0, (5.0-elapsed)/5.0) glLineWidth(1) glBegin(GL_LINES) glColor4f(0, 0, 0, alpha) glVertex2i(x-size, y) glVertex2i(x+size, y) glVertex2i(x, y-size) glVertex2i(x, y+size) glEnd() else: self.pointer_overlay = None # Show the backbuffer on screen self.gl_show(rect_count) self.gl_frame_terminator() #restore pbo viewport glViewport(0, 0, bw, bh) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.do_present_fbo() done", self)
def do_present_fbo(self): self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() bw, bh = self.size ww, wh = self.render_size if self.glconfig.is_double_buffered() or bw!=ww or bh!=wh: #refresh the whole window: rectangles = ((0, 0, bw, bh), ) else: #paint just the rectangles we have accumulated: rectangles = self.pending_fbo_paint self.pending_fbo_paint = [] log("do_present_fbo: painting %s", rectangles) glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) #viewport for painting to window: glViewport(0, 0, ww, wh) if ww!=bw or wh!=bh: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBegin(GL_QUADS) for x,y,w,h in rectangles: #note how we invert coordinates.. tx1, ty1, tx2, ty2 = x, bh-y, x+w, bh-y-h vx1, vy1, vx2, vy2 = x, y, x+w, y+h glTexCoord2i(tx1, ty1) glVertex2i(vx1, vy1) #top-left of window viewport glTexCoord2i(tx1, ty2) glVertex2i(vx1, vy2) #bottom-left of window viewport glTexCoord2i(tx2, ty2) glVertex2i(vx2, vy2) #bottom-right of window viewport glTexCoord2i(tx2, ty1) glVertex2i(vx2, vy1) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) if self.paint_spinner: #add spinner: dim = min(bw/3.0, bh/3.0) t = time.time() count = int(t*4.0) bx = bw//2 by = bh//2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count%8][i] glColor4f(c, c, c, 1) mi1 = math.pi*i/4-math.pi/16 mi2 = math.pi*i/4+math.pi/16 glVertex2i(int(bx+math.sin(mi1)*10), int(by+math.cos(mi1)*10)) glVertex2i(int(bx+math.sin(mi1)*dim), int(by+math.cos(mi1)*dim)) glVertex2i(int(bx+math.sin(mi2)*dim), int(by+math.cos(mi2)*dim)) glVertex2i(int(bx+math.sin(mi2)*10), int(by+math.cos(mi2)*10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size*2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px,py in ((0, 0), (bw, 0), (bw, bh), (0, bh)): glVertex2i(px, py) glEnd() # Show the backbuffer on screen self.gl_show() self.gl_frame_terminator() #restore pbo viewport glViewport(0, 0, bw, bh) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.do_present_fbo() done", self)
def present_fbo(self, drawable): if not self.paint_screen: return self.gl_marker("Presenting FBO on screen for drawable %s" % drawable) assert drawable # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() w, h = self.size glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBegin(GL_QUADS) glTexCoord2i(0, h) glVertex2i(0, 0) glTexCoord2i(0, 0) glVertex2i(0, h) glTexCoord2i(w, 0) glVertex2i(w, h) glTexCoord2i(w, h) glVertex2i(w, 0) glEnd() #if desired, paint window border if self.border and self.border.shown: glDisable(GL_TEXTURE_RECTANGLE_ARB) #double size since half the line will be off-screen glLineWidth(self.border.size * 2) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) glBegin(GL_LINE_LOOP) for x, y in ((0, 0), (w, 0), (w, h), (0, h)): glVertex2i(x, y) glEnd() #reset color to default glColor4f(1.0, 1.0, 1.0, 1.0) # Show the backbuffer on screen if drawable.is_double_buffered(): log("%s.present_fbo() swapping buffers now", self) drawable.swap_buffers() # Clear the new backbuffer to illustrate that its contents are undefined glClear(GL_COLOR_BUFFER_BIT) else: glFlush() self.gl_frame_terminator() self.unset_rgb_paint_state() glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.present_fbo() done", self)
def present_fbo(self, drawable): if not self.paint_screen: return self.gl_marker("Presenting FBO on screen for drawable %s" % drawable) assert drawable # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() w, h = self.size glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBegin(GL_QUADS) glTexCoord2i(0, h) glVertex2i(0, 0) glTexCoord2i(0, 0) glVertex2i(0, h) glTexCoord2i(w, 0) glVertex2i(w, h) glTexCoord2i(w, h) glVertex2i(w, 0) glEnd() #if desired, paint window border if self.border and self.border.shown: glDisable(GL_TEXTURE_RECTANGLE_ARB) #double size since half the line will be off-screen glLineWidth(self.border.size*2) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) glBegin(GL_LINE_LOOP) for x,y in ((0, 0), (w, 0), (w, h), (0, h)): glVertex2i(x, y) glEnd() #reset color to default glColor4f(1.0, 1.0, 1.0, 1.0) # Show the backbuffer on screen if drawable.is_double_buffered(): log("%s.present_fbo() swapping buffers now", self) drawable.swap_buffers() # Clear the new backbuffer to illustrate that its contents are undefined glClear(GL_COLOR_BUFFER_BIT) else: glFlush() self.gl_frame_terminator() self.unset_rgb_paint_state() glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.present_fbo() done", self)
def present_fbo(self, encoding, is_delta, x, y, w, h): if not self.paint_screen: return self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() ww, wh = self.size if self.glconfig.is_double_buffered(): #refresh the whole window: x, y = 0, 0 w, h = ww, wh glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glBegin(GL_QUADS) #note how we invert coordinates.. glTexCoord2i(x, wh - y) glVertex2i(x, y) #top-left of window viewport glTexCoord2i(x, wh - y - h) glVertex2i(x, y + h) #bottom-left of window viewport glTexCoord2i(x + w, wh - y - h) glVertex2i(x + w, y + h) #bottom-right of window viewport glTexCoord2i(x + w, wh - y) glVertex2i(x + w, y) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) #show region being painted: if OPENGL_PAINT_BOX: glLineWidth(1) if is_delta: glLineStipple(1, 0xf0f0) glEnable(GL_LINE_STIPPLE) glBegin(GL_LINE_LOOP) color = BOX_COLORS.get(encoding, _DEFAULT_BOX_COLOR) glColor4f(*color) for px, py in ((x, y), (x + w, y), (x + w, y + h), (x, y + h)): glVertex2i(px, py) glEnd() if is_delta: glDisable(GL_LINE_STIPPLE) if self.paint_spinner: #add spinner: dim = min(ww / 3.0, wh / 3.0) t = time.time() count = int(t * 4.0) bx = ww // 2 by = wh // 2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count % 8][i] glColor4f(c, c, c, 1) mi1 = math.pi * i / 4 - math.pi / 16 mi2 = math.pi * i / 4 + math.pi / 16 glVertex2i(int(bx + math.sin(mi1) * 10), int(by + math.cos(mi1) * 10)) glVertex2i(int(bx + math.sin(mi1) * dim), int(by + math.cos(mi1) * dim)) glVertex2i(int(bx + math.sin(mi2) * dim), int(by + math.cos(mi2) * dim)) glVertex2i(int(bx + math.sin(mi2) * 10), int(by + math.cos(mi2) * 10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size * 2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px, py in ((0, 0), (ww, 0), (ww, wh), (0, wh)): glVertex2i(px, py) glEnd() # Show the backbuffer on screen self.gl_show() self.gl_frame_terminator() self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.present_fbo() done", self)
def draw_pointer(self): px, py, _, _, size, start_time = self.pointer_overlay elapsed = monotonic_time()-start_time log("pointer_overlay=%s, elapsed=%.1f, timeout=%s, cursor-data=%s", self.pointer_overlay, elapsed, CURSOR_IDLE_TIMEOUT, (self.cursor_data or [])[:7]) if elapsed>=CURSOR_IDLE_TIMEOUT: #timeout - stop showing it: self.pointer_overlay = None return x = px y = py if not self.cursor_data: #paint a fake one: alpha = max(0, (5.0-elapsed)/5.0) lw = 2 glLineWidth(lw) glBegin(GL_LINES) glColor4f(0, 0, 0, alpha) glVertex2i(x-size, y-lw//2) glVertex2i(x+size, y-lw//2) glVertex2i(x, y-size) glVertex2i(x, y+size) glEnd() return cw = self.cursor_data[3] ch = self.cursor_data[4] xhot = self.cursor_data[5] yhot = self.cursor_data[6] x = px-xhot y = py-yhot if TEXTURE_CURSOR: #paint the texture containing the cursor: glActiveTexture(GL_TEXTURE0) target = GL_TEXTURE_RECTANGLE_ARB glEnable(target) glBindTexture(target, self.textures[TEX_CURSOR]) glEnablei(GL_BLEND, self.textures[TEX_CURSOR]) glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) glBlendFunc(GL_ONE, GL_ONE) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glBegin(GL_QUADS) glTexCoord2i(0, 0) glVertex2i(x, y) glTexCoord2i(0, ch) glVertex2i(x, y+ch) glTexCoord2i(cw, ch) glVertex2i(x+cw, y+ch) glTexCoord2i(cw, 0) glVertex2i(x+cw, y) glEnd() glBindTexture(target, 0) glDisable(target) else: #FUGLY: paint each pixel separately.. if not self.validate_cursor(): return pixels = self.cursor_data[8] blen = cw*ch*4 p = struct.unpack(b"B"*blen, pixels) glLineWidth(1) #TODO: use VBO arrays to make this faster for cx in range(cw): for cy in range(ch): i = cx*4+cy*cw*4 if p[i+3]>=64: glBegin(GL_POINTS) glColor4f(p[i]/256.0, p[i+1]/256.0, p[i+2]/256.0, p[i+3]/256.0) glVertex2i(x+cx, y+cy) glEnd()
def do_present_fbo(self): bw, bh = self.size ww, wh = self.render_size rect_count = len(self.pending_fbo_paint) if self.is_double_buffered() or bw!=ww or bh!=wh: #refresh the whole window: rectangles = ((0, 0, bw, bh), ) else: #paint just the rectangles we have accumulated: rectangles = self.pending_fbo_paint self.pending_fbo_paint = [] log("do_present_fbo: painting %s", rectangles) if SAVE_BUFFERS: self.save_FBO() self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) left, top, right, bottom = self.offsets #viewport for clearing the whole window: glViewport(0, 0, left+ww+right, top+wh+bottom) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # black, no alpha: glClearColor(0.0, 0.0, 0.0, 1.0) if left or top or right or bottom: glClear(GL_COLOR_BUFFER_BIT) #from now on, take the offsets into account: glViewport(left, top, ww, wh) target = GL_TEXTURE_RECTANGLE_ARB if ww!=bw or wh!=bh: glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) # Draw FBO texture on screen glEnable(target) #redundant - done in rgb paint state glBindTexture(target, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glBegin(GL_QUADS) for x,y,w,h in rectangles: #note how we invert coordinates.. tx1, ty1, tx2, ty2 = x, bh-y, x+w, bh-y-h vx1, vy1, vx2, vy2 = x, y, x+w, y+h glTexCoord2i(tx1, ty1) glVertex2i(vx1, vy1) #top-left of window viewport glTexCoord2i(tx1, ty2) glVertex2i(vx1, vy2) #bottom-left of window viewport glTexCoord2i(tx2, ty2) glVertex2i(vx2, vy2) #bottom-right of window viewport glTexCoord2i(tx2, ty1) glVertex2i(vx2, vy1) #top-right of window viewport glEnd() glBindTexture(target, 0) glDisable(target) if self.pointer_overlay: self.draw_pointer() if self.paint_spinner: #add spinner: self.draw_spinner() if self.border and self.border.shown: self.draw_border() # Show the backbuffer on screen glFlush() self.gl_show(rect_count) self.gl_frame_terminator() #restore pbo viewport glViewport(0, 0, bw, bh) glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST) log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.do_present_fbo() done", self)
def present_fbo(self, encoding, is_delta, x, y, w, h): if not self.paint_screen: return self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() ww, wh = self.size if self.glconfig.is_double_buffered(): #refresh the whole window: x, y = 0, 0 w, h = ww, wh glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glBegin(GL_QUADS) #note how we invert coordinates.. glTexCoord2i(x, wh-y) glVertex2i(x, y) #top-left of window viewport glTexCoord2i(x, wh-y-h) glVertex2i(x, y+h) #bottom-left of window viewport glTexCoord2i(x+w, wh-y-h) glVertex2i(x+w, y+h) #bottom-right of window viewport glTexCoord2i(x+w, wh-y) glVertex2i(x+w, y) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) #show region being painted: if OPENGL_PAINT_BOX: glLineWidth(1) if is_delta: glLineStipple(1, 0xf0f0) glEnable(GL_LINE_STIPPLE) glBegin(GL_LINE_LOOP) color = BOX_COLORS.get(encoding, _DEFAULT_BOX_COLOR) glColor4f(*color) for px,py in ((x, y), (x+w, y), (x+w, y+h), (x, y+h)): glVertex2i(px, py) glEnd() if is_delta: glDisable(GL_LINE_STIPPLE) if self.paint_spinner: #add spinner: dim = min(ww/3.0, wh/3.0) t = time.time() count = int(t*4.0) bx = ww//2 by = wh//2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count%8][i] glColor4f(c, c, c, 1) mi1 = math.pi*i/4-math.pi/16 mi2 = math.pi*i/4+math.pi/16 glVertex2i(int(bx+math.sin(mi1)*10), int(by+math.cos(mi1)*10)) glVertex2i(int(bx+math.sin(mi1)*dim), int(by+math.cos(mi1)*dim)) glVertex2i(int(bx+math.sin(mi2)*dim), int(by+math.cos(mi2)*dim)) glVertex2i(int(bx+math.sin(mi2)*10), int(by+math.cos(mi2)*10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size*2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px,py in ((0, 0), (ww, 0), (ww, wh), (0, wh)): glVertex2i(px, py) glEnd() # Show the backbuffer on screen self.gl_show() self.gl_frame_terminator() self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.present_fbo() done", self)
def do_present_fbo(self): bw, bh = self.size ww, wh = self.render_size self.gl_marker("Presenting FBO on screen") # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() rect_count = len(self.pending_fbo_paint) if self.glconfig.is_double_buffered() or bw!=ww or bh!=wh: #refresh the whole window: rectangles = ((0, 0, bw, bh), ) else: #paint just the rectangles we have accumulated: rectangles = self.pending_fbo_paint self.pending_fbo_paint = [] log("do_present_fbo: painting %s", rectangles) glEnable(GL_TEXTURE_RECTANGLE_ARB) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) if SAVE_BUFFERS: glBindFramebuffer(GL_READ_FRAMEBUFFER, self.offscreen_fbo) glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO], 0) glReadBuffer(GL_COLOR_ATTACHMENT0) glViewport(0, 0, bw, bh) from OpenGL.GL import glGetTexImage size = bw*bh*4 import numpy data = numpy.empty(size) img_data = glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, GL_UNSIGNED_BYTE, data) from PIL import Image, ImageOps img = Image.frombuffer("RGBA", (bw, bh), img_data, "raw", "BGRA", bw*4) img = ImageOps.flip(img) kwargs = {} if SAVE_BUFFERS=="jpeg": kwargs = { "quality" : 0, "optimize" : False, } t = time.time() tstr = time.strftime("%H-%M-%S", time.localtime(t)) filename = "./W%i-FBO-%s.%03i.%s" % (self.wid, tstr, (t*1000)%1000, SAVE_BUFFERS) log("do_present_fbo: saving %4ix%-4i pixels, %7i bytes to %s", bw, bh, size, filename) img.save(filename, SAVE_BUFFERS, **kwargs) glBindFramebuffer(GL_READ_FRAMEBUFFER, 0) #viewport for painting to window: glViewport(0, 0, ww, wh) if ww!=bw or wh!=bh: glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glBegin(GL_QUADS) for x,y,w,h in rectangles: #note how we invert coordinates.. tx1, ty1, tx2, ty2 = x, bh-y, x+w, bh-y-h vx1, vy1, vx2, vy2 = x, y, x+w, y+h glTexCoord2i(tx1, ty1) glVertex2i(vx1, vy1) #top-left of window viewport glTexCoord2i(tx1, ty2) glVertex2i(vx1, vy2) #bottom-left of window viewport glTexCoord2i(tx2, ty2) glVertex2i(vx2, vy2) #bottom-right of window viewport glTexCoord2i(tx2, ty1) glVertex2i(vx2, vy1) #top-right of window viewport glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) if self.paint_spinner: #add spinner: dim = min(bw/3.0, bh/3.0) t = time.time() count = int(t*4.0) bx = bw//2 by = bh//2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count%8][i] glColor4f(c, c, c, 1) mi1 = math.pi*i/4-math.pi/16 mi2 = math.pi*i/4+math.pi/16 glVertex2i(int(bx+math.sin(mi1)*10), int(by+math.cos(mi1)*10)) glVertex2i(int(bx+math.sin(mi1)*dim), int(by+math.cos(mi1)*dim)) glVertex2i(int(bx+math.sin(mi2)*dim), int(by+math.cos(mi2)*dim)) glVertex2i(int(bx+math.sin(mi2)*10), int(by+math.cos(mi2)*10)) glEnd() #if desired, paint window border if self.border and self.border.shown: #double size since half the line will be off-screen glLineWidth(self.border.size*2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px,py in ((0, 0), (bw, 0), (bw, bh), (0, bh)): glVertex2i(px, py) glEnd() if self.pointer_overlay: x, y, _, _, size, start_time = self.pointer_overlay elapsed = time.time()-start_time if elapsed<6: alpha = max(0, (5.0-elapsed)/5.0) glLineWidth(1) glBegin(GL_LINES) glColor4f(0, 0, 0, alpha) glVertex2i(x-size, y) glVertex2i(x+size, y) glVertex2i(x, y-size) glVertex2i(x, y+size) glEnd() else: self.pointer_overlay = None # Show the backbuffer on screen self.gl_show(rect_count) self.gl_frame_terminator() #restore pbo viewport glViewport(0, 0, bw, bh) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.unset_rgb_paint_state() log("%s(%s, %s)", glBindFramebuffer, GL_FRAMEBUFFER, self.offscreen_fbo) glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.do_present_fbo() done", self)
def present_fbo(self, drawable): if not self.paint_screen: return self.gl_marker("Presenting FBO on screen for drawable %s" % drawable) assert drawable # Change state to target screen instead of our FBO glBindFramebuffer(GL_FRAMEBUFFER, 0) if self._alpha_enabled: # transparent background: glClearColor(0.0, 0.0, 0.0, 0.0) else: # plain white no alpha: glClearColor(1.0, 1.0, 1.0, 1.0) # Draw FBO texture on screen self.set_rgb_paint_state() w, h = self.size glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[TEX_FBO]) if self._alpha_enabled: # support alpha channel if present: glEnablei(GL_BLEND, self.textures[TEX_FBO]) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) glBegin(GL_QUADS) glTexCoord2i(0, h) glVertex2i(0, 0) glTexCoord2i(0, 0) glVertex2i(0, h) glTexCoord2i(w, 0) glVertex2i(w, h) glTexCoord2i(w, h) glVertex2i(w, 0) glEnd() glDisable(GL_TEXTURE_RECTANGLE_ARB) if self.paint_spinner: #add spinner: dim = min(w / 3.0, h / 3.0) t = time.time() count = int(t * 4.0) bx = w // 2 by = h // 2 for i in range(8): #8 lines glBegin(GL_POLYGON) c = cv.trs[count % 8][i] glColor4f(c, c, c, 1) mi1 = math.pi * i / 4 - math.pi / 16 mi2 = math.pi * i / 4 + math.pi / 16 glVertex2i(int(bx + math.sin(mi1) * 10), int(by + math.cos(mi1) * 10)) glVertex2i(int(bx + math.sin(mi1) * dim), int(by + math.cos(mi1) * dim)) glVertex2i(int(bx + math.sin(mi2) * dim), int(by + math.cos(mi2) * dim)) glVertex2i(int(bx + math.sin(mi2) * 10), int(by + math.cos(mi2) * 10)) glEnd() #if desired, paint window border if self.border and self.border.shown: glDisable(GL_TEXTURE_RECTANGLE_ARB) #double size since half the line will be off-screen glLineWidth(self.border.size * 2) glBegin(GL_LINE_LOOP) glColor4f(self.border.red, self.border.green, self.border.blue, self.border.alpha) for px, py in ((0, 0), (w, 0), (w, h), (0, h)): glVertex2i(px, py) glEnd() #reset color to default glColor4f(1.0, 1.0, 1.0, 1.0) # Show the backbuffer on screen if drawable.is_double_buffered(): log("%s.present_fbo() swapping buffers now", self) drawable.swap_buffers() # Clear the new backbuffer to illustrate that its contents are undefined glClear(GL_COLOR_BUFFER_BIT) else: glFlush() self.gl_frame_terminator() self.unset_rgb_paint_state() glBindFramebuffer(GL_FRAMEBUFFER, self.offscreen_fbo) log("%s.present_fbo() done", self)