opengl upgrade to 4.3 for masks, mask function/layout rework, make_shader rework
[goodguy/cinelerra.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,
76                  const char *vert, const char *frag);
77         ~ShaderID();
78
79 // Should really use an MD5 to compare sources but this is easiest.
80         char *vert, *frag;
81         int window_id;
82         unsigned int handle;
83 };
84
85 class PBufferID
86 {
87 public:
88         PBufferID() {};
89 #ifdef HAVE_GL
90         PBufferID(int window_id,
91                 GLXPbuffer glx_pbuffer, GLXContext glx_context,
92                 int w, int h);
93         GLXPbuffer glx_pbuffer;
94         GLXContext glx_context;
95         int window_id;
96         int w, h;
97         int in_use;
98 #endif
99 };
100
101 class BC_SynchronousCommand
102 {
103 public:
104         BC_SynchronousCommand();
105         virtual ~BC_SynchronousCommand();
106
107         virtual void copy_from(BC_SynchronousCommand *command);
108
109         Condition *command_done;
110         long result;
111         int command;
112
113 // Commands
114         enum
115         {
116                 NONE,
117                 QUIT,
118 // Used by garbage collector
119                 DELETE_WINDOW,
120                 DELETE_PIXMAP,
121                 DELETE_DISPLAY,
122 // subclasses create new commands starting with this enumeration
123                 LAST_COMMAND
124         };
125
126         int colormodel;
127         BC_WindowBase *window;
128
129         VFrame *frame;
130         VFrame *frame_return;
131
132         int id;
133         int w, h;
134
135 // For garbage collection
136         int window_id;
137         Display *display;
138         Window win;
139 #ifdef HAVE_GL
140         GLXContext glx_context;
141         GLXPixmap glx_pixmap;
142         GLXWindow glx_win;
143 #endif
144 };
145
146 class BC_Synchronous : public Thread
147 {
148 public:
149         BC_Synchronous();
150         virtual ~BC_Synchronous();
151
152         friend class BC_WindowBase;
153         friend class VFrame;
154         friend class BC_PBuffer;
155         friend class BC_Pixmap;
156         friend class BC_Texture;
157
158         void quit();
159 // Must be called after constructor to create inherited objects.
160         void create_objects();
161         void start();
162         void run();
163
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);
168
169
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);
185
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);
190
191
192 #ifdef HAVE_GL
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);
203
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,
208                 GLXPixmap pixmap,
209                 GLXContext context);
210 #endif
211
212
213
214 // Called by ~BC_WindowBase to delete OpenGL objects related to the window.
215 // This function returns immediately instead of waiting for the synchronous
216 // part to finish.
217         void delete_window(BC_WindowBase *window);
218         void delete_display(BC_WindowBase *window);
219
220         long send_command(BC_SynchronousCommand *command);
221         void send_garbage(BC_SynchronousCommand *command);
222
223         void delete_pixmap_sync(BC_SynchronousCommand *command);
224         void delete_window_sync(BC_SynchronousCommand *command);
225         void delete_display_sync(BC_SynchronousCommand *command);
226
227 // Get the window currently bound to the context.
228         BC_WindowBase* get_window();
229
230 private:
231         void handle_command_base(BC_SynchronousCommand *command);
232
233         Mutex *lock_sync;
234         void sync_lock(const char *cp=0);
235         void sync_unlock();
236
237         void get_display_sync(Display *display, const char *cp);
238
239         Condition *next_command;
240         Mutex *command_lock;
241
242 // Must be locked in order of current_window->lock_window, table_lock
243 // or just table_lock.
244         Mutex *table_lock;
245
246 // This quits the program when it's 1.
247         int done;
248 // Command stack
249         ArrayList<BC_SynchronousCommand*> commands;
250         int is_started;
251 // The window the opengl context is currently bound to.
252 // Set by BC_WindowBase::enable_opengl.
253         BC_WindowBase *current_window;
254
255         ArrayList<ShaderID*> shader_ids;
256         ArrayList<TextureID*> texture_ids;
257         ArrayList<PBufferID*> pbuffer_ids;
258
259 // When the context is bound to a pbuffer, this
260 // signals glCopyTexSubImage2D to use the front buffer.
261         int is_pbuffer;
262 };
263
264
265
266
267 #endif