initial commit
[goodguy/history.git] / cinelerra-5.0 / guicast / bcsynchronous.h
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifndef BCSYNCHRONOUS_H
23 #define BCSYNCHRONOUS_H
24
25 #include "arraylist.h"
26 #include "bcpbuffer.inc"
27 #include "bcpixmap.inc"
28 #include "bctexture.inc"
29 #include "bcwindowbase.inc"
30 #include "condition.inc"
31 #include "mutex.inc"
32 #include "thread.h"
33 #include "vframe.inc"
34
35 #if defined(HAVE_CONFIG_H)
36 #include "config.h"
37 #endif
38
39 #ifdef HAVE_GL
40 #include <GL/gl.h>
41 #include <GL/glx.h>
42 #endif
43
44 #include <X11/Xlib.h>
45
46 // This takes requests and runs all OpenGL calls in the main thread.
47 // Past experience showed OpenGL couldn't be run from multiple threads
48 // reliably even if MakeCurrent was used and only 1 thread at a time did
49 // anything.
50
51 // Also manages texture memory.  Textures are not deleted until the glx_context
52 // is deleted, so they have to be reused as much as possible.
53 // Must be run as the main loop of the application.  Other threads must
54 // call into it to dispatch commands.
55
56 // In addition to synchronous operations, it handles global OpenGL variables.
57
58 // Users should create a subclass of the command and thread components to
59 // add specific commands.
60
61
62
63 class TextureID
64 {
65 public:
66         TextureID(int window_id, int id, int w, int h, int components);
67         int window_id;
68         int id;
69         int w;
70         int h;
71         int components;
72         BC_WindowBase *window;
73         int in_use;
74 };
75
76 class ShaderID
77 {
78 public:
79         ShaderID(int window_id, unsigned int handle, char *source);
80         ~ShaderID();
81
82 // Should really use an MD5 to compare sources but this is easiest.
83         char *source;
84         int window_id;
85         unsigned int handle;
86 };
87
88 class PBufferID
89 {
90 public:
91         PBufferID() {};
92 #ifdef HAVE_GL
93         PBufferID(int window_id,
94                 GLXPbuffer glx_pbuffer, GLXContext glx_context,
95                 int w, int h);
96         GLXPbuffer glx_pbuffer;
97         GLXContext glx_context;
98         int window_id;
99         int w, h;
100         int in_use;
101 #endif
102 };
103
104 class BC_SynchronousCommand
105 {
106 public:
107         BC_SynchronousCommand();
108         virtual ~BC_SynchronousCommand();
109
110         virtual void copy_from(BC_SynchronousCommand *command);
111
112         Condition *command_done;
113         long result;
114         int command;
115
116 // Commands
117         enum
118         {
119                 NONE,
120                 QUIT,
121 // Used by garbage collector
122                 DELETE_WINDOW,
123                 DELETE_PIXMAP,
124                 DELETE_DISPLAY,
125 // subclasses create new commands starting with this enumeration
126                 LAST_COMMAND
127         };
128
129         int colormodel;
130         BC_WindowBase *window;
131
132         VFrame *frame;
133         VFrame *frame_return;
134
135         int id;
136         int w, h;
137
138 // For garbage collection
139         int window_id;
140         Display *display;
141         Window win;
142 #ifdef HAVE_GL
143         GLXContext glx_context;
144         GLXPixmap glx_pixmap;
145         GLXWindow glx_win;
146 #endif
147 };
148
149 class BC_Synchronous;
150
151 class BC_SynchGarbage : public Thread
152 {
153 public:
154         BC_SynchGarbage(BC_Synchronous*sync);
155         ~BC_SynchGarbage();
156
157         void send_garbage(BC_SynchronousCommand *command);
158         void handle_garbage();
159         void start();
160         void run();
161         void quit();
162         void stop();
163
164         BC_Synchronous *synchronous;
165         Condition *more_garbage;
166         Mutex *garbage_lock;
167         ArrayList<BC_SynchronousCommand*> garbage;
168         int done;
169 };
170
171 class BC_Synchronous : public Thread
172 {
173         BC_SynchGarbage *sync_garbage;
174 public:
175         BC_Synchronous();
176         virtual ~BC_Synchronous();
177
178         friend class BC_WindowBase;
179         friend class VFrame;
180         friend class BC_PBuffer;
181         friend class BC_Pixmap;
182         friend class BC_Texture;
183         friend class BC_SynchGarbage;
184
185         void quit();
186 // Must be called after constructor to create inherited objects.
187         void create_objects();
188         void start();
189         void run();
190
191         virtual BC_SynchronousCommand* new_command();
192 // Handle extra commands not part of the base class.
193 // Contains a switch statement starting with LAST_COMMAND
194         virtual void handle_command(BC_SynchronousCommand *command);
195
196
197 // OpenGL texture removal doesn't work.  Need to store the ID's of all the deleted
198 // textures in this stack and reuse them.  Also since OpenGL needs synchronous
199 // commands, be sure this is always called synchronously.
200 // Called when a texture is created to associate it with the current window.
201 // Must be called inside synchronous loop.
202         void put_texture(int id, int w, int h, int components);
203 // Search for existing texture matching the parameters and not in use
204 // and return it.  If -1 is returned, a new texture must be created.
205 // Must be called inside synchronous loop.
206 // If someone proves OpenGL can delete texture memory, this function can be
207 // forced to always return -1.
208         int get_texture(int w, int h, int components);
209 // Release a texture for use by the get_texture call.
210 // Can be called outside synchronous loop.
211         void release_texture(int window_id, int id);
212
213 // Get the shader by window_id and source comparison if it exists.
214 // Not run in OpenGL thread because it has its own lock.
215 // Sets *got_it to 1 on success.
216         unsigned int get_shader(char *source, int *got_it);
217 // Add a new shader program by title if it doesn't exist.
218 // Doesn't check if it already exists.
219         void put_shader(unsigned int handle, char *source);
220         void dump_shader(unsigned int handle);
221
222
223 #ifdef HAVE_GL
224 // Push a pbuffer when it's created.
225 // Must be called inside synchronous loop.
226         void put_pbuffer(int w, int h,
227                 GLXPbuffer glx_pbuffer,
228                 GLXContext glx_context);
229 // Get the PBuffer by window_id and dimensions if it exists.
230 // Must be called inside synchronous loop.
231         GLXPbuffer get_pbuffer(int w,
232                 int h,
233                 int *window_id,
234                 GLXContext *glx_context);
235 // Release a pbuffer for use by get_pbuffer.
236         void release_pbuffer(int window_id, GLXPbuffer pbuffer);
237
238 // Schedule GL pixmap for deletion by the garbage collector.
239 // Pixmaps don't wait until until the window is deleted but they must be
240 // deleted before the window is deleted to have the display connection.
241         void delete_pixmap(BC_WindowBase *window,
242                 GLXPixmap pixmap,
243                 GLXContext context);
244 #endif
245
246
247
248 // Called by ~BC_WindowBase to delete OpenGL objects related to the window.
249 // This function returns immediately instead of waiting for the synchronous
250 // part to finish.
251         void delete_window(BC_WindowBase *window);
252         void delete_display(BC_WindowBase *window);
253
254         long send_command(BC_SynchronousCommand *command);
255         void send_garbage(BC_SynchronousCommand *command);
256
257         void delete_pixmap_sync(BC_SynchronousCommand *command);
258         void delete_window_sync(BC_SynchronousCommand *command);
259         void delete_display_sync(BC_SynchronousCommand *command);
260
261 // Get the window currently bound to the context.
262         BC_WindowBase* get_window();
263
264 private:
265         void handle_command_base(BC_SynchronousCommand *command);
266
267         Mutex *lock_sync;
268         void sync_lock(const char *cp=0);
269         void sync_lock(Display *display, const char *cp);
270         void sync_unlock();
271
272         void get_display_sync(Display *display, const char *cp);
273
274         Condition *next_command;
275         Mutex *command_lock;
276
277 // Must be locked in order of current_window->lock_window, table_lock
278 // or just table_lock.
279         Mutex *table_lock;
280
281 // This quits the program when it's 1.
282         int done;
283 // Command stack
284         ArrayList<BC_SynchronousCommand*> commands;
285         int is_running;
286 // The window the opengl context is currently bound to.
287 // Set by BC_WindowBase::enable_opengl.
288         BC_WindowBase *current_window;
289
290         ArrayList<ShaderID*> shader_ids;
291         ArrayList<TextureID*> texture_ids;
292         ArrayList<PBufferID*> pbuffer_ids;
293
294 // When the context is bound to a pbuffer, this
295 // signals glCopyTexSubImage2D to use the front buffer.
296         int is_pbuffer;
297 };
298
299
300
301
302 #endif