4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #ifndef BCSYNCHRONOUS_H
23 #define BCSYNCHRONOUS_H
25 #include "arraylist.h"
26 #include "bcpbuffer.inc"
27 #include "bcpixmap.inc"
28 #include "bctexture.inc"
29 #include "bcwindowbase.inc"
30 #include "condition.inc"
42 // This takes requests and runs all OpenGL calls in the main thread.
43 // Past experience showed OpenGL couldn't be run from multiple threads
44 // reliably even if MakeCurrent was used and only 1 thread at a time did
47 // Also manages texture memory. Textures are not deleted until the glx_context
48 // is deleted, so they have to be reused as much as possible.
49 // Must be run as the main loop of the application. Other threads must
50 // call into it to dispatch commands.
52 // In addition to synchronous operations, it handles global OpenGL variables.
54 // Users should create a subclass of the command and thread components to
55 // add specific commands.
62 TextureID(int window_id, int id, int w, int h, int components);
68 BC_WindowBase *window;
75 ShaderID(int window_id, unsigned int handle,
76 const char *vert, const char *frag);
79 // Should really use an MD5 to compare sources but this is easiest.
90 PBufferID(int window_id,
91 GLXPbuffer glx_pbuffer, GLXContext glx_context,
93 GLXPbuffer glx_pbuffer;
94 GLXContext glx_context;
101 class BC_SynchronousCommand
104 BC_SynchronousCommand();
105 virtual ~BC_SynchronousCommand();
107 virtual void copy_from(BC_SynchronousCommand *command);
109 Condition *command_done;
118 // Used by garbage collector
122 // subclasses create new commands starting with this enumeration
127 BC_WindowBase *window;
130 VFrame *frame_return;
135 // For garbage collection
140 GLXContext glx_context;
141 GLXPixmap glx_pixmap;
146 class BC_Synchronous : public Thread
150 virtual ~BC_Synchronous();
152 friend class BC_WindowBase;
154 friend class BC_PBuffer;
155 friend class BC_Pixmap;
156 friend class BC_Texture;
159 // Must be called after constructor to create inherited objects.
160 void create_objects();
164 virtual BC_SynchronousCommand* new_command();
165 // Handle extra commands not part of the base class.
166 // Contains a switch statement starting with LAST_COMMAND
167 virtual void handle_command(BC_SynchronousCommand *command);
170 // OpenGL texture removal doesn't work. Need to store the ID's of all the deleted
171 // textures in this stack and reuse them. Also since OpenGL needs synchronous
172 // commands, be sure this is always called synchronously.
173 // Called when a texture is created to associate it with the current window.
174 // Must be called inside synchronous loop.
175 void put_texture(int id, int w, int h, int components);
176 // Search for existing texture matching the parameters and not in use
177 // and return it. If -1 is returned, a new texture must be created.
178 // Must be called inside synchronous loop.
179 // If someone proves OpenGL can delete texture memory, this function can be
180 // forced to always return -1.
181 int get_texture(int w, int h, int components);
182 // Release a texture for use by the get_texture call.
183 // Can be called outside synchronous loop.
184 void release_texture(int window_id, int id);
186 // Get the shader by window_id and vertex/fragment source comparison
187 int get_shader(unsigned int *handle, const char *vert, const char *frag);
188 void put_shader(unsigned int handle, const char *vert, const char *frag);
189 void dump_shader(unsigned int handle);
193 // Push a pbuffer when it's created.
194 // Must be called inside synchronous loop.
195 void put_pbuffer(int w, int h,
196 GLXPbuffer glx_pbuffer,
197 GLXContext glx_context);
198 // Get the PBuffer by window_id and dimensions if it exists.
199 // Must be called inside synchronous loop.
200 GLXPbuffer get_pbuffer(int w, int h, GLXContext *glx_context);
201 // Release a pbuffer for use by get_pbuffer.
202 void release_pbuffer(int window_id, GLXPbuffer pbuffer);
204 // Schedule GL pixmap for deletion by the garbage collector.
205 // Pixmaps don't wait until until the window is deleted but they must be
206 // deleted before the window is deleted to have the display connection.
207 void delete_pixmap(BC_WindowBase *window,
214 // Called by ~BC_WindowBase to delete OpenGL objects related to the window.
215 // This function returns immediately instead of waiting for the synchronous
217 void delete_window(BC_WindowBase *window);
218 void delete_display(BC_WindowBase *window);
220 long send_command(BC_SynchronousCommand *command);
221 void send_garbage(BC_SynchronousCommand *command);
223 void delete_pixmap_sync(BC_SynchronousCommand *command);
224 void delete_window_sync(BC_SynchronousCommand *command);
225 void delete_display_sync(BC_SynchronousCommand *command);
227 // Get the window currently bound to the context.
228 BC_WindowBase* get_window();
231 void handle_command_base(BC_SynchronousCommand *command);
234 void sync_lock(const char *cp=0);
237 void get_display_sync(Display *display, const char *cp);
239 Condition *next_command;
242 // Must be locked in order of current_window->lock_window, table_lock
243 // or just table_lock.
246 // This quits the program when it's 1.
249 ArrayList<BC_SynchronousCommand*> commands;
251 // The window the opengl context is currently bound to.
252 // Set by BC_WindowBase::enable_opengl.
253 BC_WindowBase *current_window;
255 ArrayList<ShaderID*> shader_ids;
256 ArrayList<TextureID*> texture_ids;
257 ArrayList<PBufferID*> pbuffer_ids;
259 // When the context is bound to a pbuffer, this
260 // signals glCopyTexSubImage2D to use the front buffer.