rework edge plugin, add crikey plugin, text tumbler tweak, eyedropper coords
[goodguy/history.git] / cinelerra-5.1 / 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 #ifdef HAVE_GL
36 #include <GL/gl.h>
37 #include <GL/glx.h>
38 #endif
39
40 #include <X11/Xlib.h>
41
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
45 // anything.
46
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.
51
52 // In addition to synchronous operations, it handles global OpenGL variables.
53
54 // Users should create a subclass of the command and thread components to
55 // add specific commands.
56
57
58
59 class TextureID
60 {
61 public:
62         TextureID(int window_id, int id, int w, int h, int components);
63         int window_id;
64         int id;
65         int w;
66         int h;
67         int components;
68         BC_WindowBase *window;
69         int in_use;
70 };
71
72 class ShaderID
73 {
74 public:
75         ShaderID(int window_id, unsigned int handle, char *source);
76         ~ShaderID();
77
78 // Should really use an MD5 to compare sources but this is easiest.
79         char *source;
80         int window_id;
81         unsigned int handle;
82 };
83
84 class PBufferID
85 {
86 public:
87         PBufferID() {};
88 #ifdef HAVE_GL
89         PBufferID(int window_id,
90                 GLXPbuffer glx_pbuffer, GLXContext glx_context,
91                 int w, int h);
92         GLXPbuffer glx_pbuffer;
93         GLXContext glx_context;
94         int window_id;
95         int w, h;
96         int in_use;
97 #endif
98 };
99
100 class BC_SynchronousCommand
101 {
102 public:
103         BC_SynchronousCommand();
104         virtual ~BC_SynchronousCommand();
105
106         virtual void copy_from(BC_SynchronousCommand *command);
107
108         Condition *command_done;
109         long result;
110         int command;
111
112 // Commands
113         enum
114         {
115                 NONE,
116                 QUIT,
117 // Used by garbage collector
118                 DELETE_WINDOW,
119                 DELETE_PIXMAP,
120                 DELETE_DISPLAY,
121 // subclasses create new commands starting with this enumeration
122                 LAST_COMMAND
123         };
124
125         int colormodel;
126         BC_WindowBase *window;
127
128         VFrame *frame;
129         VFrame *frame_return;
130
131         int id;
132         int w, h;
133
134 // For garbage collection
135         int window_id;
136         Display *display;
137         Window win;
138 #ifdef HAVE_GL
139         GLXContext glx_context;
140         GLXPixmap glx_pixmap;
141         GLXWindow glx_win;
142 #endif
143 };
144
145 class BC_Synchronous : public Thread
146 {
147 public:
148         BC_Synchronous();
149         virtual ~BC_Synchronous();
150
151         friend class BC_WindowBase;
152         friend class VFrame;
153         friend class BC_PBuffer;
154         friend class BC_Pixmap;
155         friend class BC_Texture;
156
157         void quit();
158 // Must be called after constructor to create inherited objects.
159         void create_objects();
160         void start();
161         void run();
162
163         virtual BC_SynchronousCommand* new_command();
164 // Handle extra commands not part of the base class.
165 // Contains a switch statement starting with LAST_COMMAND
166         virtual void handle_command(BC_SynchronousCommand *command);
167
168
169 // OpenGL texture removal doesn't work.  Need to store the ID's of all the deleted
170 // textures in this stack and reuse them.  Also since OpenGL needs synchronous
171 // commands, be sure this is always called synchronously.
172 // Called when a texture is created to associate it with the current window.
173 // Must be called inside synchronous loop.
174         void put_texture(int id, int w, int h, int components);
175 // Search for existing texture matching the parameters and not in use
176 // and return it.  If -1 is returned, a new texture must be created.
177 // Must be called inside synchronous loop.
178 // If someone proves OpenGL can delete texture memory, this function can be
179 // forced to always return -1.
180         int get_texture(int w, int h, int components);
181 // Release a texture for use by the get_texture call.
182 // Can be called outside synchronous loop.
183         void release_texture(int window_id, int id);
184
185 // Get the shader by window_id and source comparison if it exists.
186 // Not run in OpenGL thread because it has its own lock.
187 // Sets *got_it to 1 on success.
188         unsigned int get_shader(char *source, int *got_it);
189 // Add a new shader program by title if it doesn't exist.
190 // Doesn't check if it already exists.
191         void put_shader(unsigned int handle, char *source);
192         void dump_shader(unsigned int handle);
193
194
195 #ifdef HAVE_GL
196 // Push a pbuffer when it's created.
197 // Must be called inside synchronous loop.
198         void put_pbuffer(int w, int h,
199                 GLXPbuffer glx_pbuffer,
200                 GLXContext glx_context);
201 // Get the PBuffer by window_id and dimensions if it exists.
202 // Must be called inside synchronous loop.
203         GLXPbuffer get_pbuffer(int w, int h, GLXContext *glx_context);
204 // Release a pbuffer for use by get_pbuffer.
205         void release_pbuffer(int window_id, GLXPbuffer pbuffer);
206
207 // Schedule GL pixmap for deletion by the garbage collector.
208 // Pixmaps don't wait until until the window is deleted but they must be
209 // deleted before the window is deleted to have the display connection.
210         void delete_pixmap(BC_WindowBase *window,
211                 GLXPixmap pixmap,
212                 GLXContext context);
213 #endif
214
215
216
217 // Called by ~BC_WindowBase to delete OpenGL objects related to the window.
218 // This function returns immediately instead of waiting for the synchronous
219 // part to finish.
220         void delete_window(BC_WindowBase *window);
221         void delete_display(BC_WindowBase *window);
222
223         long send_command(BC_SynchronousCommand *command);
224         void send_garbage(BC_SynchronousCommand *command);
225
226         void delete_pixmap_sync(BC_SynchronousCommand *command);
227         void delete_window_sync(BC_SynchronousCommand *command);
228         void delete_display_sync(BC_SynchronousCommand *command);
229
230 // Get the window currently bound to the context.
231         BC_WindowBase* get_window();
232
233 private:
234         void handle_command_base(BC_SynchronousCommand *command);
235
236         Mutex *lock_sync;
237         void sync_lock(const char *cp=0);
238         void sync_unlock();
239
240         void get_display_sync(Display *display, const char *cp);
241
242         Condition *next_command;
243         Mutex *command_lock;
244
245 // Must be locked in order of current_window->lock_window, table_lock
246 // or just table_lock.
247         Mutex *table_lock;
248
249 // This quits the program when it's 1.
250         int done;
251 // Command stack
252         ArrayList<BC_SynchronousCommand*> commands;
253         int is_started;
254 // The window the opengl context is currently bound to.
255 // Set by BC_WindowBase::enable_opengl.
256         BC_WindowBase *current_window;
257
258         ArrayList<ShaderID*> shader_ids;
259         ArrayList<TextureID*> texture_ids;
260         ArrayList<PBufferID*> pbuffer_ids;
261
262 // When the context is bound to a pbuffer, this
263 // signals glCopyTexSubImage2D to use the front buffer.
264         int is_pbuffer;
265 };
266
267
268
269
270 #endif