def _transfer_frame_pbo(self): # generate PBO's if self._video_thread.has_video_loaded and (self._pbo_shape != self._video_thread.frame.shape): if self._pbos is not None: gl.glDeleteBuffers(PBO_COUNT, self._pbos) self._pbo_shape = self._video_thread.frame.shape self._pbos = gl.glGenBuffers(PBO_COUNT) h, w, b = self._pbo_shape num_bytes = h*w*b for pbo in self._pbos: gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, pbo) gl.glBufferData(gl.GL_PIXEL_UNPACK_BUFFER, num_bytes, None, gl.GL_STREAM_DRAW) gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, 0) # generate/update OpenGL texture if (self._frame is None or self._frame.shape != self._pbo_shape) and self._pbo_shape is not None: self._frame = np.zeros(self._pbo_shape, dtype=np.uint8).view(gloo.Texture2D) self._frame.activate() self._frame.deactivate() # do the transfer of pixel data from cpu to gpu using PBO's # inspired by this: https://gist.github.com/roxlu/4663550 if self._video_thread.has_video_loaded and self._video_thread.frame_changed: self._video_thread.frame_changed = False pbo = self._pbos[self._pbo_index] gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, pbo) t = self._frame._handle h, w, b = self._pbo_shape assert t != None and t != 0 gl.glBindTexture(gl.GL_TEXTURE_2D, t) gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, w, h, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, None) h, w, b = self._pbo_shape num_bytes = h*w*b self._pbo_index = (self._pbo_index + 1) % PBO_COUNT pbo = self._pbos[self._pbo_index] gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, pbo) # this might be an alternative, but not so fast as tested so far #gl.glBufferSubData(gl.GL_PIXEL_UNPACK_BUFFER, 0, num_bytes, ctypes.c_void_p(self._video_thread.frame.ctypes.data)) ptr = gl.glMapBuffer(gl.GL_PIXEL_UNPACK_BUFFER, gl.GL_WRITE_ONLY) if ptr != 0: #start = time.time() ctypes.memmove(ctypes.c_voidp(ptr), ctypes.c_void_p(self._video_thread.frame.ctypes.data), num_bytes) #end = time.time() #elapsed = end - start #print("Took %.2fms, %.2fMB/s" % (elapsed * 1000, (num_bytes / 1000000) / elapsed)) gl.glUnmapBuffer(gl.GL_PIXEL_UNPACK_BUFFER) gl.glBindBuffer(gl.GL_PIXEL_UNPACK_BUFFER, 0)
def delete(self): print('deleting buffers...') if self.vb is not None: gl.glDeleteBuffers(1, np.array([self.vb.handle], "I")) self.vb = None if self.psb is not None: gl.glDeleteBuffers(1, np.array([self.psb.handle], "I")) self.psb = None if self.program is not None: self.program.delete() self.program = None
def _download_texture(self, texture): # generate PBO's if self._pbos is None or self._pbo_shape != texture.shape: if self._pbos is not None: gl.glDeleteBuffers(2, self._pbos) self._pbo_shape = texture.shape self._pbos = gl.glGenBuffers(2) h, w, b = self._pbo_shape num_bytes = h*w*b for pbo in self._pbos: gl.glBindBuffer(gl.GL_PIXEL_PACK_BUFFER, pbo) gl.glBufferData(gl.GL_PIXEL_PACK_BUFFER, num_bytes, None, gl.GL_STREAM_DRAW) gl.glBindBuffer(gl.GL_PIXEL_PACK_BUFFER, 0) # do the transfer of pixel data from gpu to cpu using PBO's # inspired by this: https://gist.github.com/roxlu/4663550 h, w, b = self._pbo_shape b -= 1 num_bytes = h*w*b pbo = self._pbos[self._pbo_index] gl.glBindBuffer(gl.GL_PIXEL_PACK_BUFFER, pbo) t = texture._handle assert t != None and t != 0 gl.glBindTexture(gl.GL_TEXTURE_2D, t) gl.glGetTexImage(gl.GL_TEXTURE_2D, 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, ctypes.c_void_p(0)) self._pbo_index = (self._pbo_index + 1) % 2 pbo = self._pbos[self._pbo_index] gl.glBindBuffer(gl.GL_PIXEL_PACK_BUFFER, pbo) ptr = gl.glMapBuffer(gl.GL_PIXEL_PACK_BUFFER, gl.GL_READ_ONLY) data = None if ptr != 0: p = ctypes.cast(ptr, ctypes.POINTER(ctypes.c_ubyte * num_bytes)) data = np.frombuffer(p.contents, dtype=np.uint8).copy().reshape((h, w, b)) gl.glUnmapBuffer(gl.GL_PIXEL_PACK_BUFFER) gl.glBindBuffer(gl.GL_PIXEL_PACK_BUFFER, 0) assert data is not None return data
def _delete(self): """ Delete buffer from GPU """ if self._handle > -1: gl.glDeleteBuffers(1, np.array([self._handle]))