def _init_thread(self): """ Complete SDL2 interface initialisation. """ # initialise SDL sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING) # set clipboard handler to SDL2 backend.clipboard_handler = SDL2Clipboard() # display palettes for blink states 0, 1 self.show_palette = [ sdl2.SDL_AllocPalette(256), sdl2.SDL_AllocPalette(256) ] # get physical screen dimensions (needs to be called before set_mode) display_mode = sdl2.SDL_DisplayMode() sdl2.SDL_GetCurrentDisplayMode(0, ctypes.byref(display_mode)) self.physical_size = display_mode.w, display_mode.h # create the window initially, size will be corrected later self.display = None # create window in same thread that manipulates it # "NOTE: You should not expect to be able to create a window, render, or receive events on any thread other than the main one" # https://wiki.libsdl.org/CategoryThread # http://stackoverflow.com/questions/27751533/sdl2-threading-seg-fault self._do_create_window(640, 400) # load an all-black 16-colour game palette to get started self.set_palette([(0, 0, 0)] * 16, None) self.move_cursor(1, 1) self.set_page(0, 0) self.set_mode(self.kwargs['initial_mode']) # support for CGA composite self.composite_palette = sdl2.SDL_AllocPalette(256) composite_colors = video_graphical.composite_640.get( self.composite_card, video_graphical.composite_640['cga']) colors = (sdl2.SDL_Color * 256)( *[sdl2.SDL_Color(r, g, b, 255) for (r, g, b) in composite_colors]) sdl2.SDL_SetPaletteColors(self.composite_palette, colors, 0, 256) # check if we can honour scaling=smooth if self.smooth: # pointer to the zoomed surface self.zoomed = None pixelformat = self.display_surface.contents.format if pixelformat.contents.BitsPerPixel != 32: logging.warning( 'Smooth scaling not available on this display of %d-bit colour depth: needs 32-bit', self.display_surface.format.contents.BitsPerPixel) self.smooth = False if not hasattr(sdl2, 'sdlgfx'): logging.warning( 'Smooth scaling not available: SDL_GFX extension not found.' ) self.smooth = False # available joysticks num_joysticks = sdl2.SDL_NumJoysticks() for j in range(num_joysticks): sdl2.SDL_JoystickOpen(j) # if a joystick is present, its axes report 128 for mid, not 0 for axis in (0, 1): backend.input_queue.put( backend.Event(backend.STICK_MOVED, (j, axis, 128)))
def __init__(self, input_queue, video_queue, **kwargs): """Initialise SDL2 interface.""" if not sdl2: logging.debug('PySDL2 module not found.') raise base.InitFailed() if not numpy: logging.debug('NumPy module not found.') raise base.InitFailed() video_graphical.VideoGraphical.__init__(self, input_queue, video_queue, **kwargs) # display & border # border attribute self.border_attr = 0 # palette and colours # composite colour artifacts self.composite_artifacts = False # update cycle # refresh cycle parameters self._cycle = 0 self.last_cycle = 0 self._cycle_time = 120 self.blink_cycles = 5 # cursor # current cursor location self.last_row = 1 self.last_col = 1 # cursor is visible self.cursor_visible = True # load the icon self.icon = kwargs['icon'] # mouse setups buttons = {'left': sdl2.SDL_BUTTON_LEFT, 'middle': sdl2.SDL_BUTTON_MIDDLE, 'right': sdl2.SDL_BUTTON_RIGHT, 'none': None} copy_paste = kwargs.get('copy-paste', ('left', 'middle')) self.mousebutton_copy = buttons[copy_paste[0]] self.mousebutton_paste = buttons[copy_paste[1]] self.mousebutton_pen = buttons[kwargs.get('pen', 'right')] # keyboard setup self.f11_active = False self.altgr = kwargs['altgr'] if not self.altgr: scan_to_scan[sdl2.SDL_SCANCODE_RALT] = scancode.ALT mod_to_scan[sdl2.KMOD_RALT] = scancode.ALT # keep params for enter self.kwargs = kwargs # we need a set_mode call to be really up and running self._has_window = False # ensure the correct SDL2 video driver is chosen for Windows # since this gets messed up if we also import pygame if platform.system() == 'Windows': os.environ['SDL_VIDEODRIVER'] = 'windows' # initialise SDL if sdl2.SDL_Init(sdl2.SDL_INIT_EVERYTHING): # SDL not initialised correctly logging.error('Could not initialise SDL2: %s', sdl2.SDL_GetError()) raise base.InitFailed() display_mode = sdl2.SDL_DisplayMode() sdl2.SDL_GetCurrentDisplayMode(0, ctypes.byref(display_mode)) self.physical_size = display_mode.w, display_mode.h # create the window initially as 640*400 black # "NOTE: You should not expect to be able to create a window, render, or receive events on any thread other than the main one" # https://wiki.libsdl.org/CategoryThread # http://stackoverflow.com/questions/27751533/sdl2-threading-seg-fault self.display = None self.work_surface = None self._do_create_window(*self._find_display_size(640, 400, self.border_width)) # pop up as black rather than background, looks nicer sdl2.SDL_UpdateWindowSurface(self.display)
def display_init(diagonal_in): """Initializes the display and rendering backend, calculating and assigning the values of runtime KLParams variables related to the screen (e.g. P.screen_c, P.refresh_rate, P.pixels_per_degree). Called by 'klibs run' on launch, for internal use only. Args: diagonal_in (float): The size of the monitor in diagonal inches (e.g. 13 for a 13-inch MacBook Pro). """ if os.name == 'nt': # set video driver explicitly on Windows to avoid misdetection problems os.environ['SDL_VIDEODRIVER'] = 'windows' sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) sdl2.mouse.SDL_ShowCursor(sdl2.SDL_DISABLE) sdl2.SDL_PumpEvents() display_mode = sdl2.video.SDL_DisplayMode() sdl2.SDL_GetCurrentDisplayMode(0, display_mode) P.screen_x = display_mode.w P.screen_y = display_mode.h P.screen_c = (P.screen_x // 2, P.screen_y // 2) P.screen_x_y = (P.screen_x, P.screen_y) P.refresh_rate = float(display_mode.refresh_rate) if P.refresh_rate == 0: P.refresh_rate = 60.0 print( "\tWarning: Unable to detect your monitor's refresh rate, defaulting to 60Hz." ) elif P.refresh_rate == 59: P.refresh_rate = 59.94 # fix for some Windows monitors P.refresh_time = 1000.0 / P.refresh_rate #TODO: figure out what's actually needed for multi-monitor support for d in P.additional_displays: if d[2]: P.screen_x_y = list(d[1]) P.screen_x = d[1][0] P.screen_y = d[1][1] if P.screen_origin is None: P.screen_origin = (0, 0) # Get conversion factor for pixels to degrees of visual angle based on viewing distance, # screen resolution, and given diagonal screen size P.screen_diagonal_in = diagonal_in P.screen_diagonal_px = sqrt(P.screen_x**2.0 + P.screen_y**2.0) P.ppi = P.screen_diagonal_px / diagonal_in P.monitor_height = P.screen_y / P.ppi P.monitor_width = P.screen_x / P.ppi P.screen_degrees_x = degrees(2 * atan( (2.54 * P.monitor_width / 2.0) / P.view_distance)) P.screen_degrees_y = degrees(2 * atan( (2.54 * P.monitor_height / 2.0) / P.view_distance)) P.pixels_per_degree = P.screen_x / P.screen_degrees_x P.ppd = P.pixels_per_degree # alias for convenience # Create the SDL window object and configure it properly for OpenGL (code from Mike) SCREEN_FLAGS = (sdl2.SDL_WINDOW_SHOWN | sdl2.SDL_WINDOW_FULLSCREEN_DESKTOP | sdl2.SDL_WINDOW_OPENGL | sdl2.SDL_WINDOW_ALLOW_HIGHDPI) window = sdl2.ext.Window(P.project_name, P.screen_x_y, P.screen_origin, SCREEN_FLAGS) sdl2.SDL_GL_CreateContext(window.window) sdl2.SDL_GL_SetSwapInterval(1) # enforce vsync gl.glMatrixMode(gl.GL_PROJECTION) gl.glLoadIdentity() gl.glOrtho(0, P.screen_x, P.screen_y, 0, 0, 1) gl.glMatrixMode(gl.GL_MODELVIEW) gl.glDisable(gl.GL_DEPTH_TEST) # Clear the SDL event queue and open the window, returning the window object sdl2.SDL_PumpEvents() sdl2.mouse.SDL_ShowCursor(sdl2.SDL_DISABLE) window.show() P.display_initialized = True return window