2 # Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
4 # This file is part of GNU Radio
6 # GNU Radio is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
11 # GNU Radio is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with GNU Radio; see the file COPYING. If not, write to
18 # the Free Software Foundation, Inc., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
27 BACKGROUND_COLOR_SPEC = (1, 0.976, 1, 1) #creamy white
29 ##################################################
30 # GL caching interface
31 ##################################################
32 class gl_cache(object):
34 Cache a set of gl drawing routines in a compiled list.
37 def __init__(self, draw):
40 @param draw a function to draw gl stuff
47 To be called when gl initializes.
48 Create a new compiled list.
50 self._grid_compiled_list_id = GL.glGenLists(1)
54 Draw the gl stuff using a compiled list.
55 If changed, reload the compiled list.
58 GL.glNewList(self._grid_compiled_list_id, GL.GL_COMPILE)
63 GL.glCallList(self._grid_compiled_list_id)
65 def changed(self, state=None):
67 Set the changed flag if state is not None.
68 Otherwise return the changed flag.
70 if state is None: return self._changed
73 ##################################################
74 # OpenGL WX Plotter Canvas
75 ##################################################
76 class plotter_base(wx.glcanvas.GLCanvas, common.mutex):
78 Plotter base class for all plot types.
81 def __init__(self, parent):
83 Create a new plotter base.
84 Initialize the GLCanvas with double buffering.
85 Initialize various plotter flags.
86 Bind the paint and size events.
87 @param parent the parent widgit
89 attribList = (wx.glcanvas.WX_GL_DOUBLEBUFFER, wx.glcanvas.WX_GL_RGBA)
90 wx.glcanvas.GLCanvas.__init__(self, parent, attribList=attribList);
91 self.use_persistence=False
92 self.persist_alpha=2.0/15
94 self._gl_init_flag = False
95 self._resized_flag = True
96 self._init_fcns = list()
97 self._draw_fcns = list()
98 self._gl_caches = list()
99 self.Bind(wx.EVT_PAINT, self._on_paint)
100 self.Bind(wx.EVT_SIZE, self._on_size)
101 self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
103 def set_use_persistence(self,enable):
104 self.use_persistence=enable
105 self.clear_accum=True
107 def set_persist_alpha(self,analog_alpha):
108 self.persist_alpha=analog_alpha
110 def new_gl_cache(self, draw_fcn, draw_pri=50):
112 Create a new gl cache.
113 Register its draw and init function.
114 @return the new cache object
116 cache = gl_cache(draw_fcn)
117 self.register_init(cache.init)
118 self.register_draw(cache.draw, draw_pri)
119 self._gl_caches.append(cache)
122 def register_init(self, init_fcn):
123 self._init_fcns.append(init_fcn)
125 def register_draw(self, draw_fcn, draw_pri=50):
127 Register a draw function with a layer priority.
128 Large pri values are drawn last.
129 Small pri values are drawn first.
131 for i in range(len(self._draw_fcns)):
132 if draw_pri < self._draw_fcns[i][0]:
133 self._draw_fcns.insert(i, (draw_pri, draw_fcn))
135 self._draw_fcns.append((draw_pri, draw_fcn))
137 def _on_size(self, event):
139 Flag the resize event.
140 The paint event will handle the actual resizing.
143 self._resized_flag = True
144 self.clear_accum=True
147 def _on_paint(self, event):
149 Respond to paint events.
150 Initialize GL if this is the first paint event.
151 Resize the view port if the width or height changed.
152 Redraw the screen, calling the draw functions.
156 #check if gl was initialized
157 if not self._gl_init_flag:
158 GL.glClearColor(*BACKGROUND_COLOR_SPEC)
159 for fcn in self._init_fcns: fcn()
160 self._gl_init_flag = True
161 #check for a change in window size
162 if self._resized_flag:
163 self.width, self.height = self.GetSize()
164 GL.glMatrixMode(GL.GL_PROJECTION)
166 GL.glOrtho(0, self.width, self.height, 0, 1, 0)
167 GL.glMatrixMode(GL.GL_MODELVIEW)
169 GL.glViewport(0, 0, self.width, self.height)
170 for cache in self._gl_caches: cache.changed(True)
171 self._resized_flag = False
172 #clear, draw functions, swap
173 GL.glClear(GL.GL_COLOR_BUFFER_BIT)
176 GL.glEnable (GL.GL_LINE_SMOOTH)
177 GL.glEnable (GL.GL_POLYGON_SMOOTH)
178 GL.glEnable (GL.GL_BLEND)
179 GL.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
180 GL.glHint (GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST) #GL.GL_DONT_CARE)
181 GL.glHint(GL.GL_POLYGON_SMOOTH_HINT, GL.GL_NICEST)
182 #GL.glLineWidth (1.5)
184 GL.glEnable(GL.GL_MULTISAMPLE) #Enable Multisampling anti-aliasing
187 for fcn in self._draw_fcns: fcn[1]()
189 if self.use_persistence:
191 #GL.glClear(GL.GL_ACCUM_BUFFER_BIT)
192 GL.glAccum(GL.GL_LOAD, 1.0)
193 self.clear_accum=False
195 GL.glAccum(GL.GL_MULT, 1.0-self.persist_alpha)
196 GL.glAccum(GL.GL_ACCUM, self.persist_alpha)
197 GL.glAccum(GL.GL_RETURN, 1.0)
205 if not self._gl_init_flag: return
206 wx.PostEvent(self, wx.PaintEvent())