1 #ifndef BCSYNCHRONOUS_H
2 #define BCSYNCHRONOUS_H
5 #include "bcpbuffer.inc"
6 #include "bcpixmap.inc"
7 #include "bctexture.inc"
8 #include "bcwindowbase.inc"
9 #include "condition.inc"
14 #if defined(HAVE_CONFIG_H)
26 // This takes requests and runs all OpenGL calls in the main thread.
27 // Past experience showed OpenGL couldn't be run from multiple threads
28 // reliably even if MakeCurrent was used and only 1 thread at a time did
31 // Also manages texture memory. Textures are not deleted until the gl_context
32 // is deleted, so they have to be reused as much as possible.
33 // Must be run as the main loop of the application. Other threads must
34 // call into it to dispatch commands.
36 // In addition to synchronous operations, it handles global OpenGL variables.
38 // Users should create a subclass of the command and thread components to
39 // add specific commands.
46 TextureID(int window_id
, int id
, int w
, int h
, int components
);
52 BC_WindowBase
*window
;
59 ShaderID(int window_id
, unsigned int handle
, char *source
);
62 // Should really use an MD5 to compare sources but this is easiest.
73 PBufferID(int window_id
,
75 GLXContext gl_context
,
79 GLXContext gl_context
;
87 class BC_SynchronousCommand
90 BC_SynchronousCommand();
91 ~BC_SynchronousCommand();
93 virtual void copy_from(BC_SynchronousCommand
*command
);
95 Condition
*command_done
;
104 // Used by garbage collector
107 // subclasses create new commands starting with this enumeration
112 BC_WindowBase
*window
;
115 VFrame
*frame_return
;
121 // For garbage collection
126 GLXContext gl_context
;
132 class BC_Synchronous
: public Thread
136 virtual ~BC_Synchronous();
138 friend class BC_WindowBase
;
140 friend class BC_PBuffer
;
141 friend class BC_Pixmap
;
142 friend class BC_Texture
;
144 // Called by another thread
147 // Must be called after constructor to create inherited objects.
148 void create_objects();
152 virtual BC_SynchronousCommand
* new_command();
153 // Handle extra commands not part of the base class.
154 // Contains a switch statement starting with LAST_COMMAND
155 virtual void handle_command(BC_SynchronousCommand
*command
);
158 // OpenGL texture removal doesn't work. Need to store the ID's of all the deleted
159 // textures in this stack and reuse them. Also since OpenGL needs synchronous
160 // commands, be sure this is always called synchronously.
161 // Called when a texture is created to associate it with the current window.
162 // Must be called inside synchronous loop.
163 void put_texture(int id
, int w
, int h
, int components
);
164 // Search for existing texture matching the parameters and not in use
165 // and return it. If -1 is returned, a new texture must be created.
166 // Must be called inside synchronous loop.
167 // If someone proves OpenGL can delete texture memory, this function can be
168 // forced to always return -1.
169 int get_texture(int w
, int h
, int components
);
170 // Release a texture for use by the get_texture call.
171 // Can be called outside synchronous loop.
172 void release_texture(int window_id
, int id
);
174 // Get the shader by window_id and source comparison if it exists.
175 // Not run in OpenGL thread because it has its own lock.
176 // Sets *got_it to 1 on success.
177 unsigned int get_shader(char *source
, int *got_it
);
178 // Add a new shader program by title if it doesn't exist.
179 // Doesn't check if it already exists.
180 void put_shader(unsigned int handle
, char *source
);
181 void dump_shader(unsigned int handle
);
185 // Push a pbuffer when it's created.
186 // Must be called inside synchronous loop.
187 void put_pbuffer(int w
,
190 GLXContext gl_context
);
191 // Get the PBuffer by window_id and dimensions if it exists.
192 // Must be called inside synchronous loop.
193 GLXPbuffer
get_pbuffer(int w
,
196 GLXContext
*gl_context
);
197 // Release a pbuffer for use by get_pbuffer.
198 void release_pbuffer(int window_id
, GLXPbuffer pbuffer
);
200 // Schedule GL pixmap for deletion by the garbage collector.
201 // Pixmaps don't wait until until the window is deleted but they must be
202 // deleted before the window is deleted to have the display connection.
203 void delete_pixmap(BC_WindowBase
*window
,
210 // Called by ~BC_WindowBase to delete OpenGL objects related to the window.
211 // This function returns immediately instead of waiting for the synchronous
213 void delete_window(BC_WindowBase
*window
);
216 int send_command(BC_SynchronousCommand
*command
);
217 void send_garbage(BC_SynchronousCommand
*command
);
220 // Get the window currently bound to the context.
221 BC_WindowBase
* get_window();
224 void handle_command_base(BC_SynchronousCommand
*command
);
226 // Execute commands which can't be executed until the caller returns.
227 void handle_garbage();
229 // Release OpenGL objects related to the window id.
230 // Called from the garbage collector only
231 void delete_window_sync(BC_SynchronousCommand
*command
);
232 void delete_pixmap_sync(BC_SynchronousCommand
*command
);
234 Condition
*next_command
;
237 // Must be locked in order of current_window->lock_window, table_lock
238 // or just table_lock.
241 // This quits the program when it's 1.
244 ArrayList
<BC_SynchronousCommand
*> commands
;
246 // The window the opengl context is currently bound to.
247 // Set by BC_WindowBase::enable_opengl.
248 BC_WindowBase
*current_window
;
250 ArrayList
<ShaderID
*> shader_ids
;
251 ArrayList
<TextureID
*> texture_ids
;
252 ArrayList
<PBufferID
*> pbuffer_ids
;
253 // Commands which can't be executed until the caller returns.
254 ArrayList
<BC_SynchronousCommand
*> garbage
;
256 // When the context is bound to a pbuffer, this
257 // signals glCopyTexSubImage2D to use the front buffer.