1
2
3
4
5
6
7
8
9
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
21
22
23
24 import sys, types, math, time, os
25 import StringIO
26
27 import logging
28
29 import VisionEgg
30 import VisionEgg.PlatformDependent
31 import VisionEgg.ParameterTypes as ve_types
32 import VisionEgg.GLTrace
33 import VisionEgg.ThreeDeeMath
34
35 import pygame
36 import pygame.locals
37 import pygame.display
38
39 import VisionEgg.GL as gl
40
41 import numpy
42 import numpy.oldnumeric as Numeric
43
44
45 try:
46 sum
47 except NameError:
48 import operator
50 return reduce(operator.add, values )
51
53 VisionEgg.config._FRAMECOUNT_ABSOLUTE += 1
54 return pygame.display.flip()
55
56
57
58
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,
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
180 logger = logging.getLogger('VisionEgg.Core')
181
182 VisionEgg.ClassWithParameters.__init__(self,**kw)
183
184 cp = self.constant_parameters
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
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
229 if cp.sync_swap:
230 sync_success = VisionEgg.PlatformDependent.sync_swap_with_vbl_pre_gl_init()
231
232
233
234
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
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
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
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
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
338 cp.red_bits = pygame.display.gl_get_attribute(pygame.locals.GL_RED_SIZE)
339 cp.green_bits = pygame.display.