def create_opengl_context(self, surface_size=(640, 480)): """Create offscreen OpenGL context and make it current. Users are expected to directly use EGL API in case more advanced context management is required. Args: surface_size: (width, height), size of the offscreen rendering surface. """ egl_display = egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY) major, minor = egl.EGLint(), egl.EGLint() egl.eglInitialize(egl_display, pointer(major), pointer(minor)) config_attribs = [ egl.EGL_SURFACE_TYPE, egl.EGL_PBUFFER_BIT, egl.EGL_BLUE_SIZE, 8, egl.EGL_GREEN_SIZE, 8, egl.EGL_RED_SIZE, 8, egl.EGL_DEPTH_SIZE, 24, egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_BIT, egl.EGL_NONE, ] # if need MSAA https://www.khronos.org/opengl/wiki/Multisampling config_attribs = (egl.EGLint * len(config_attribs))(*config_attribs) num_configs = egl.EGLint() egl_cfg = egl.EGLConfig() egl.eglChooseConfig(egl_display, config_attribs, pointer(egl_cfg), 1, pointer(num_configs)) width, height = surface_size pbuffer_attribs = [ egl.EGL_WIDTH, width, egl.EGL_HEIGHT, height, egl.EGL_NONE, ] pbuffer_attribs = (egl.EGLint * len(pbuffer_attribs))(*pbuffer_attribs) egl_surf = egl.eglCreatePbufferSurface(egl_display, egl_cfg, pbuffer_attribs) egl.eglBindAPI(egl.EGL_OPENGL_API) egl_context = egl.eglCreateContext(egl_display, egl_cfg, egl.EGL_NO_CONTEXT, None) egl.eglMakeCurrent(egl_display, egl_surf, egl_surf, egl_context) self.display = egl_display
def __init__(self, width=640, height=480, fullscreen=False, aspect=None): self.gl = gl self.bo_next = self.bo_prev = None self.last_swap = time.time() self.frame_count = 0 self.card = pykms.Card() print("DRM fd: %d" % self.card.fd) print("Has atomic: %r" % self.card.has_atomic) self.render_fd = -1 render_name = libdrm.drmGetRenderDeviceNameFromFd(self.card.fd) print("Render device name: %r" % render_name) if render_name: try: self.render_fd = os.open(render_name, os.O_RDWR) except OSError: print("Render node not available") print("Render fd: %d" % self.render_fd) self.gbm_dev = libgbm.gbm_create_device(self.card.fd) if not self.gbm_dev: raise Exception("Failed to create GBM device") print("GBM dev: %x" % self.gbm_dev) self.res = pykms.ResourceManager(self.card) self.conn = self.res.reserve_connector() self.crtc = self.res.reserve_crtc(self.conn) self.root_plane = self.res.reserve_generic_plane(self.crtc) if not self.root_plane: raise Exception("Root plane not available") self.mode = mode = self.conn.get_default_mode() BaseDisplay.__init__(self, mode.hdisplay, mode.vdisplay, True, aspect) self.fps = 1000 * mode.clock / (mode.htotal * mode.vtotal) print("Creating GBM surface (%dx%d %f Hz)" % (mode.hdisplay, mode.vdisplay, self.fps)) self.gbm_surface = libgbm.gbm_surface_create( c_void_p(self.gbm_dev), mode.hdisplay, mode.vdisplay, GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING) if not self.gbm_surface: raise Exception("Failed to create GBM surface") print("GBM surface: %x" % self.gbm_surface) self.disp = egl.eglGetDisplay(self.gbm_dev) if not self.disp: raise Exception("Failed to get egl display") attribList = arrays.GLintArray.asArray([ egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_ES2_BIT, egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT, #egl.EGL_COLOR_BUFFER_TYPE, egl.EGL_RGB_BUFFER, egl.EGL_RED_SIZE, 8, egl.EGL_GREEN_SIZE, 8, egl.EGL_BLUE_SIZE, 8, egl.EGL_ALPHA_SIZE, 0, egl.EGL_NONE ]) ctxAttrib = arrays.GLintArray.asArray([ egl.EGL_CONTEXT_CLIENT_VERSION, 2, egl.EGL_NONE ]) egl.eglInitialize(self.disp, None, None) config = egl.EGLConfig() num_configs = ctypes.c_long() egl.eglChooseConfig(self.disp, attribList, byref(config), 1, byref(num_configs)) ret = ctypes.c_int() egl.eglBindAPI(egl.EGL_OPENGL_ES_API) self.surface = egl.eglCreateWindowSurface(self.disp, config, c_void_p(self.gbm_surface), None) self.context = egl.eglCreateContext(self.disp, config, egl.EGL_NO_CONTEXT, ctxAttrib) assert egl.eglMakeCurrent(self.disp, self.surface, self.surface, self.context) egl.eglSwapInterval(self.disp, 1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) gl.glClearColor(0, 0, 0, 1.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) #fb = self.lock_next() #self.crtc.set_mode(self.conn, fb, mode) modeb = mode.to_blob(self.card) req = pykms.AtomicReq(self.card) req.add(self.conn, "CRTC_ID", self.crtc.id) req.add(self.crtc, {"ACTIVE": 1, "MODE_ID": modeb.id}) if req.test(allow_modeset = True): raise Exception("Atomic test failed") if req.commit_sync(allow_modeset = True): raise Exception("Atomic commit failed") self.win_width = self.width = mode.hdisplay self.win_height = self.height = mode.vdisplay gl.glViewport(0, 0, self.win_width, self.win_height) self.clear_color = self.BLACK self._initialize()
def __init__(self, width=640, height=480, fullscreen=False, aspect=None): self.gl = gl libbcm_host.bcm_host_init() display = libbcm_host.vc_dispmanx_display_open(0) mode = DISPMANX_MODEINFO_T() libbcm_host.vc_dispmanx_display_get_info(display, byref(mode)) print("Display mode: %dx%d" % (mode.width, mode.height)) self.disp = egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY) attribList = arrays.GLintArray.asArray([ egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_ES2_BIT, egl.EGL_SURFACE_TYPE, egl.EGL_WINDOW_BIT, #egl.EGL_COLOR_BUFFER_TYPE, egl.EGL_RGB_BUFFER, egl.EGL_RED_SIZE, 8, egl.EGL_GREEN_SIZE, 8, egl.EGL_BLUE_SIZE, 8, egl.EGL_ALPHA_SIZE, 8, egl.EGL_NONE ]) ctxAttrib = arrays.GLintArray.asArray([ egl.EGL_CONTEXT_CLIENT_VERSION, 2, egl.EGL_NONE ]) egl.eglInitialize(self.disp, None, None) config = egl.EGLConfig() num_configs = ctypes.c_long() egl.eglChooseConfig(self.disp, attribList, byref(config), 1, byref(num_configs)) ret = ctypes.c_int() egl.eglBindAPI(egl.EGL_OPENGL_ES_API) update = libbcm_host.vc_dispmanx_update_start(0) rectDst = VC_RECT_T() rectDst.x = rectDst.y = 0 rectDst.width = mode.width rectDst.height = mode.height rectSrc = VC_RECT_T() rectSrc.x = rectDst.y = 0 rectSrc.width = mode.width << 16 rectSrc.height = mode.height << 16 alpha = VC_DISPMANX_ALPHA_T() alpha.flags = 1 << 16 # premultiplied alpha alpha.opacity = 255 alpha.mask = 0 self.nativeWindow = EGL_DISPMANX_WINDOW_T() self.nativeWindow.width = mode.width self.nativeWindow.height = mode.height layer = 0 self.nativeWindow.element = libbcm_host.vc_dispmanx_element_add( update, display, layer, byref(rectDst), 0, byref(rectSrc), 0, byref(alpha), 0, 0) libbcm_host.vc_dispmanx_update_submit_sync(update) libbcm_host.vc_dispmanx_display_close(display) self.surface = egl.eglCreateWindowSurface(self.disp, config, byref(self.nativeWindow), None) self.context = egl.eglCreateContext(self.disp, config, egl.EGL_NO_CONTEXT, ctxAttrib) assert egl.eglMakeCurrent(self.disp, self.surface, self.surface, self.context) egl.eglSwapInterval(self.disp, 1) gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0) for i in range(5): gl.glClearColor(0, 0, 0, 1.0) gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) egl.eglSwapBuffers(self.disp, self.surface) self.win_width = self.width = mode.width self.win_height = self.height = mode.height gl.glViewport(0, 0, self.win_width, self.win_height) BaseDisplay.__init__(self, mode.width, mode.height, True, aspect) # Transparent layer self.clear_color = self.TRANSPARENT self._initialize()
def video_init(self): """This function should be called from within the RomOpen() video plugin function call. The default SDL implementation of this function simply calls SDL_InitSubSystem(SDL_INIT_VIDEO). It does not open a rendering window or switch video modes. PROTOTYPE: m64p_error VidExt_Init(void)""" log.debug("Vidext: video_init()") if self.window.platform == 'Linux': #if self.window.environment.wm == 'X11': from gi.repository import GdkX11 self.window_handle = self.window.canvas.get_property( 'window').get_xid() #elif self.window.environment.wm == 'Wayland': # from gi.repository import GdkWayland # No bindings...? # # XXX: It won't work on wayland without forcing GDK_BACKEND=x11, but I can live with that. # self.window_handle = GdkWayland.window_get_wl_surface(self.parent.get_window()) elif self.window.platform == 'Windows': # https://stackoverflow.com/questions/23021327/how-i-can-get-drawingarea-window-handle-in-gtk3/27236258#27236258 # https://gitlab.gnome.org/GNOME/gtk/issues/510 drawingareahwnd = self.window.canvas.get_property("window") # make sure to call ensure_native before e.g. on realize if not drawingareahwnd.has_native(): log.warning( "Vidext: Your window is gonna freeze as soon as you move or resize it..." ) c.pythonapi.PyCapsule_GetPointer.restype = c.c_void_p c.pythonapi.PyCapsule_GetPointer.argtypes = [c.py_object] drawingarea_gpointer = c.pythonapi.PyCapsule_GetPointer( drawingareahwnd.__gpointer__, None) # get the win32 handle libgdk = c.CDLL("gdk-3-vs16.dll") self.window_handle = libgdk.gdk_win32_window_get_handle( drawingarea_gpointer) elif self.window.platform == 'Darwin': # https://gitlab.gnome.org/GNOME/pygobject/issues/112 drawingareahnd = self.window.canvas.get_property("window") # make sure to call ensure_native before e.g. on realize if not drawingareahnd.has_native(): log.warning( "Vidext: Your window is gonna freeze as soon as you move or resize it..." ) c.pythonapi.PyCapsule_GetPointer.restype = c.c_void_p c.pythonapi.PyCapsule_GetPointer.argtypes = [c.py_object] gpointer = c.pythonapi.PyCapsule_GetPointer( drawingareahnd.__gpointer__, None) libgdk = c.CDLL("libgdk-3.0.dylib") #gdk_quartz_window_get_nswindow segfaults. libgdk.gdk_quartz_window_get_nsview.restype = c.c_void_p libgdk.gdk_quartz_window_get_nsview.argtypes = [c.c_void_p] self.window_handle = libgdk.gdk_quartz_window_get_nsview(gpointer) # Reset EGL self.__reset_egl() # Get EGL display self.egl_display = egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY) if self.egl_display == egl.EGL_NO_DISPLAY: log.error(f"eglGetDisplay() returned error: {egl.eglGetError()}") return wrp_dt.m64p_error.M64ERR_INVALID_STATE.value # Initialize EGL retval = egl.eglInitialize(self.egl_display, c.c_int(0), c.c_int(0)) # XXX: Required by glide64mk, make EGL know that we want pure OpenGL egl.eglBindAPI(egl.EGL_OPENGL_API) if retval == egl.EGL_TRUE: return wrp_dt.m64p_error.M64ERR_SUCCESS.value else: log.error(f"eglInitialize() returned error: {egl.eglGetError()}") return wrp_dt.m64p_error.M64ERR_INVALID_STATE.value