Package VisionEgg :: Module Core
[frames] | no frames]

Source Code for Module VisionEgg.Core

   1  # The Vision Egg: Core 
   2  # 
   3  # Copyright (C) 2001-2004 Andrew Straw 
   4  # Copyright (C) 2004-2008 California Institute of Technology 
   5  # 
   6  # URL: <http://www.visionegg.org/> 
   7  # 
   8  # Distributed under the terms of the GNU Lesser General Public License 
   9  # (LGPL). See LICENSE.TXT that came with this file. 
  10   
  11  """ 
  12  Core Vision Egg functionality. 
  13   
  14  This module contains the architectural foundations of the Vision Egg. 
  15   
  16  """ 
  17   
  18  #################################################################### 
  19  # 
  20  #        Import all the necessary packages 
  21  # 
  22  #################################################################### 
  23   
  24  import sys, types, math, time, os               # standard Python modules 
  25  import StringIO 
  26   
  27  import logging                                  # available in Python 2.3 
  28   
  29  import VisionEgg                                # Vision Egg base module (__init__.py) 
  30  import VisionEgg.PlatformDependent              # platform dependent Vision Egg C code 
  31  import VisionEgg.ParameterTypes as ve_types     # Vision Egg type checking 
  32  import VisionEgg.GLTrace                        # Allows tracing of all OpenGL calls 
  33  import VisionEgg.ThreeDeeMath                   # OpenGL math simulation 
  34   
  35  import pygame                                   # pygame handles OpenGL window setup 
  36  import pygame.locals 
  37  import pygame.display 
  38   
  39  import VisionEgg.GL as gl # get all OpenGL stuff in one namespace 
  40   
  41  import numpy 
  42  import numpy.oldnumeric as Numeric # emulate old Numeric Python package 
  43   
  44  # Define "sum" if it's not available as Python function 
  45  try: 
  46      sum 
  47  except NameError: 
  48      import operator 
49 - def sum( values ):
50 return reduce(operator.add, values )
51
52 -def swap_buffers():
53 VisionEgg.config._FRAMECOUNT_ABSOLUTE += 1 54 return pygame.display.flip()
55 56 #################################################################### 57 # 58 # Screen 59 # 60 #################################################################### 61
62 -class Screen(VisionEgg.ClassWithParameters):
63 """An OpenGL window, possibly displayed across multiple displays. 64 65 A Screen instance is an OpenGL window for the Vision Egg to draw 66 in. For an instance of Screen to do anything useful, it must 67 contain one or more instances of the Viewport class and one or 68 more instances of the Stimulus class. 69 70 Currently, only one OpenGL window is supported by the library with 71 which the Vision Egg initializes graphics (pygame/SDL). However, 72 this need not limit display to a single physical display device. 73 Many video drivers, for example, allow applications to treat two 74 separate monitors as one large array of contiguous pixels. By 75 sizing a window such that it occupies both monitors and creating 76 separate viewports for the portion of the window on each monitor, 77 a multiple screen effect can be created. 78 79 Public read-only variables 80 ========================== 81 size -- Tuple of 2 integers specifying width and height 82 83 Parameters 84 ========== 85 bgcolor -- background color (AnyOf(Sequence3 of Real or Sequence4 of Real)) 86 Default: (0.5, 0.5, 0.5, 0.0) 87 88 Constant Parameters 89 =================== 90 alpha_bits -- number of bits per pixel for alpha channel. Can be set with VISIONEGG_REQUEST_ALPHA_BITS (UnsignedInteger) 91 Default: (determined at runtime) 92 blue_bits -- number of bits per pixel for blue channel. Can be set with VISIONEGG_REQUEST_BLUE_BITS (UnsignedInteger) 93 Default: (determined at runtime) 94 double_buffer -- use double buffering? Can be set with VISIONEGG_DOUBLE_BUFFER (Boolean) 95 Default: (determined at runtime) 96 frameless -- remove standard window frame? Can be set with VISIONEGG_FRAMELESS_WINDOW (Boolean) 97 Default: (determined at runtime) 98 fullscreen -- use full screen? Can be set with VISIONEGG_FULLSCREEN (Boolean) 99 Default: (determined at runtime) 100 green_bits -- number of bits per pixel for green channel. Can be set with VISIONEGG_REQUEST_GREEN_BITS (UnsignedInteger) 101 Default: (determined at runtime) 102 hide_mouse -- hide the mouse cursor? Can be set with VISIONEGG_HIDE_MOUSE (Boolean) 103 Default: (determined at runtime) 104 is_stereo -- allocate stereo framebuffers? Can be set with VISIONEGG_REQUEST_STEREO (Boolean) 105 Default: (determined at runtime) 106 maxpriority -- raise priority? (platform dependent) Can be set with VISIONEGG_MAXPRIORITY (Boolean) 107 Default: (determined at runtime) 108 multisample_samples -- preferred number of multisamples for FSAA (UnsignedInteger) 109 Default: (determined at runtime) 110 preferred_bpp -- preferred bits per pixel (bit depth) Can be set with VISIONEGG_PREFERRED_BPP (UnsignedInteger) 111 Default: (determined at runtime) 112 red_bits -- number of bits per pixel for red channel. Can be set with VISIONEGG_REQUEST_RED_BITS (UnsignedInteger) 113 Default: (determined at runtime) 114 size -- size (units: pixels) Can be set with VISIONEGG_SCREEN_W and VISIONEGG_SCREEN_H (Sequence2 of Real) 115 Default: (determined at runtime) 116 sync_swap -- synchronize buffer swaps to vertical sync? Can be set with VISIONEGG_SYNC_SWAP (Boolean) 117 Default: (determined at runtime) 118 """ 119 120 parameters_and_defaults = VisionEgg.ParameterDefinition({ 121 'bgcolor':((0.5,0.5,0.5,0.0), 122 ve_types.AnyOf(ve_types.Sequence3(ve_types.Real), 123 ve_types.Sequence4(ve_types.Real)), 124 'background color',), 125 }) 126 127 constant_parameters_and_defaults = VisionEgg.ParameterDefinition({ 128 'size':(None, 129 ve_types.Sequence2(ve_types.Real), 130 'size (units: pixels) Can be set with VISIONEGG_SCREEN_W and VISIONEGG_SCREEN_H'), 131 'fullscreen':(None, 132 ve_types.Boolean, 133 'use full screen? Can be set with VISIONEGG_FULLSCREEN'), 134 'double_buffer':(None, 135 ve_types.Boolean, 136 'use double buffering? Can be set with VISIONEGG_DOUBLE_BUFFER'), 137 'preferred_bpp':(None, 138 ve_types.UnsignedInteger, 139 'preferred bits per pixel (bit depth) Can be set with VISIONEGG_PREFERRED_BPP'), 140 'maxpriority':(None, 141 ve_types.Boolean, 142 'raise priority? (platform dependent) Can be set with VISIONEGG_MAXPRIORITY'), 143 'hide_mouse':(None, 144 ve_types.Boolean, 145 'hide the mouse cursor? Can be set with VISIONEGG_HIDE_MOUSE'), 146 'frameless':(None, 147 ve_types.Boolean, 148 'remove standard window frame? Can be set with VISIONEGG_FRAMELESS_WINDOW'), 149 'sync_swap':(None, 150 ve_types.Boolean, 151 'synchronize buffer swaps to vertical sync? Can be set with VISIONEGG_SYNC_SWAP'), 152 'red_bits':(None, 153 ve_types.UnsignedInteger, 154 'number of bits per pixel for red channel. Can be set with VISIONEGG_REQUEST_RED_BITS'), 155 'green_bits':(None, 156 ve_types.UnsignedInteger, 157 'number of bits per pixel for green channel. Can be set with VISIONEGG_REQUEST_GREEN_BITS'), 158 'blue_bits':(None, 159 ve_types.UnsignedInteger, 160 'number of bits per pixel for blue channel. Can be set with VISIONEGG_REQUEST_BLUE_BITS'), 161 'alpha_bits':(None, 162 ve_types.UnsignedInteger, 163 'number of bits per pixel for alpha channel. Can be set with VISIONEGG_REQUEST_ALPHA_BITS'), 164 'is_stereo':(None, 165 ve_types.Boolean, 166 'allocate stereo framebuffers? Can be set with VISIONEGG_REQUEST_STEREO'), 167 'multisample_samples':(None, # support added by Mark Halko 168 ve_types.UnsignedInteger, 169 'preferred number of multisamples for FSAA'), 170 }) 171 172 __slots__ = ( 173 '__cursor_visible_func__', 174 '__pygame_quit__', 175 '_put_pixels_texture_stimulus', 176 '_pixel_coord_projection', 177 ) 178
179 - def __init__(self,**kw):
180 logger = logging.getLogger('VisionEgg.Core') 181 182 VisionEgg.ClassWithParameters.__init__(self,**kw) 183 184 cp = self.constant_parameters # shorthand 185 if cp.size is None: 186 cp.size = (VisionEgg.config.VISIONEGG_SCREEN_W, 187 VisionEgg.config.VISIONEGG_SCREEN_H) 188 if cp.double_buffer is None: 189 cp.double_buffer = VisionEgg.config.VISIONEGG_DOUBLE_BUFFER 190 if cp.fullscreen is None: 191 cp.fullscreen = VisionEgg.config.VISIONEGG_FULLSCREEN 192 if cp.preferred_bpp is None: 193 cp.preferred_bpp = VisionEgg.config.VISIONEGG_PREFERRED_BPP 194 if cp.maxpriority is None: 195 cp.maxpriority = VisionEgg.config.VISIONEGG_MAXPRIORITY 196 if cp.hide_mouse is None: 197 cp.hide_mouse = VisionEgg.config.VISIONEGG_HIDE_MOUSE 198 if cp.frameless is None: 199 cp.frameless = VisionEgg.config.VISIONEGG_FRAMELESS_WINDOW 200 if cp.sync_swap is None: 201 cp.sync_swap = VisionEgg.config.VISIONEGG_SYNC_SWAP 202 if cp.red_bits is None: 203 cp.red_bits = VisionEgg.config.VISIONEGG_REQUEST_RED_BITS 204 if cp.green_bits is None: 205 cp.green_bits = VisionEgg.config.VISIONEGG_REQUEST_GREEN_BITS 206 if cp.blue_bits is None: 207 cp.blue_bits = VisionEgg.config.VISIONEGG_REQUEST_BLUE_BITS 208 if cp.alpha_bits is None: 209 cp.alpha_bits = VisionEgg.config.VISIONEGG_REQUEST_ALPHA_BITS 210 if cp.is_stereo is None: 211 cp.is_stereo = VisionEgg.config.VISIONEGG_REQUEST_STEREO 212 if cp.multisample_samples is None: 213 cp.multisample_samples = VisionEgg.config.VISIONEGG_MULTISAMPLE_SAMPLES 214 215 if VisionEgg.config.SYNCLYNC_PRESENT: 216 global synclync # import into global namespace 217 import synclync 218 try: 219 VisionEgg.config._SYNCLYNC_CONNECTION = synclync.SyncLyncConnection() 220 except synclync.SyncLyncError, x: 221 logger.warning( "Could not connect to SyncLync device (SyncLyncError: %s)."%str(x)) 222 VisionEgg.config._SYNCLYNC_CONNECTION = None 223 else: 224 logger.info( "Connected to SyncLync device" ) 225 else: 226 VisionEgg.config._SYNCLYNC_CONNECTION = None 227 228 # Attempt to synchronize buffer swapping with vertical sync 229 if cp.sync_swap: 230 sync_success = VisionEgg.PlatformDependent.sync_swap_with_vbl_pre_gl_init() 231 232 # Initialize pygame stuff 233 # if sys.platform == "darwin": # bug in Mac OS X version of pygame 234 # pygame.init() 235 pygame.display.init() 236 237 if hasattr(pygame.display,"gl_set_attribute"): 238 pygame.display.gl_set_attribute(pygame.locals.GL_RED_SIZE,cp.red_bits) 239 pygame.display.gl_set_attribute(pygame.locals.GL_GREEN_SIZE,cp.green_bits) 240 pygame.display.gl_set_attribute(pygame.locals.GL_BLUE_SIZE,cp.blue_bits) 241 pygame.display.gl_set_attribute(pygame.locals.GL_ALPHA_SIZE,cp.alpha_bits) 242 pygame.display.gl_set_attribute(pygame.locals.GL_STEREO,cp.is_stereo) 243 #Request FSAA 244 if cp.multisample_samples > 0 : 245 pygame.display.gl_set_attribute(pygame.locals.GL_MULTISAMPLEBUFFERS,1) 246 pygame.display.gl_set_attribute(pygame.locals.GL_MULTISAMPLESAMPLES,cp.multisample_samples) 247 else: 248 logger.debug("Could not request or query exact bit depths, " 249 "alpha or stereo because you need " 250 "pygame release 1.4.9 or greater. This is " 251 "only of concern if you use a stimulus that " 252 "needs this. In that case, the stimulus " 253 "should check for the desired feature(s).") 254 255 if not hasattr(pygame.display,"set_gamma_ramp"): 256 logger.debug("set_gamma_ramp function not available " 257 "because you need pygame release 1.5 or " 258 "greater. This is only of concern if you " 259 "need this feature.") 260 pygame.display.set_caption("Vision Egg") 261 262 flags = pygame.locals.OPENGL 263 if cp.double_buffer: 264 flags = flags | pygame.locals.DOUBLEBUF 265 if cp.fullscreen: 266 flags = flags | pygame.locals.FULLSCREEN 267 if cp.frameless: 268 flags = flags | pygame.locals.NOFRAME 269 270 try_bpp = cp.preferred_bpp 271 272 append_str = "" 273 if cp.fullscreen: 274 screen_mode = "fullscreen" 275 else: 276 screen_mode = "window" 277 if hasattr(pygame.display,"gl_set_attribute"): 278 append_str = " (%d %d %d %d RGBA)."%(cp.red_bits, 279 cp.green_bits, 280 cp.blue_bits, 281 cp.alpha_bits) 282 283 logger.info("Requesting %s %d x %d %d bpp%s"% 284 (screen_mode,self.size[0],self.size[1], 285 try_bpp,append_str)) 286 287 pygame.display.set_mode(self.size, flags, try_bpp ) 288 # set a global variable so we know workaround avoid pygame bug 289 VisionEgg.config._pygame_started = 1 290 291 try: 292 if sys.platform != 'darwin': 293 pygame.display.set_icon(pygame.transform.scale(pygame.image.load( 294 os.path.join(VisionEgg.config.VISIONEGG_SYSTEM_DIR, 295 'data','visionegg.bmp')).convert(),(32,32))) 296 else: 297 import AppKit # requires PyObjC, which is required by pygame osx 298 im = AppKit.NSImage.alloc() 299 im.initWithContentsOfFile_( 300 os.path.join(VisionEgg.config.VISIONEGG_SYSTEM_DIR, 301 'data','visionegg.tif')) 302 AppKit.NSApplication.setApplicationIconImage_(AppKit.NSApp(),im) 303 304 except Exception,x: 305 logger.info("Error while trying to set_icon: %s: %s"% 306 (str(x.__class__),str(x))) 307 308 global gl_vendor, gl_renderer, gl_version 309 gl_vendor = gl.glGetString(gl.GL_VENDOR) 310 gl_renderer = gl.glGetString(gl.GL_RENDERER) 311 gl_version = gl.glGetString(gl.GL_VERSION) 312 313 logger.info("OpenGL %s, %s, %s (PyOpenGL %s)"% 314 (gl_version, gl_renderer, gl_vendor, gl.__version__)) 315 316 if gl_renderer == "GDI Generic" and gl_vendor == "Microsoft Corporation": 317 logger.warning("Using default Microsoft Windows OpenGL " 318 "drivers. Please (re-)install the latest " 319 "video drivers from your video card " 320 "manufacturer to get hardware accelerated " 321 "performance.") 322 if gl_renderer == "Mesa GLX Indirect" and gl_vendor == "VA Linux Systems, Inc.": 323 logger.warning("Using default Mesa GLX drivers. Please " 324 "(re-)install the latest video drivers from " 325 "your video card manufacturer or DRI " 326 "project to get hardware accelarated " 327 "performance.") 328 # Set values to unknown and fill based on OpenGL values 329 cp.red_bits = None 330 cp.green_bits = None 331 cp.blue_bits = None 332 cp.alpha_bits = None 333 cp.is_stereo = None 334 got_bpp = pygame.display.Info().bitsize 335 append_str = '' 336 if hasattr(pygame.display,"gl_get_attribute"): 337 # Fill in values as known 338 cp.red_bits = pygame.display.gl_get_attribute(pygame.locals.GL_RED_SIZE) 339 cp.green_bits = pygame.display.