1 #define GL_GLEXT_PROTOTYPES
2 #include "bcresources.h"
4 #include "bcsynchronous.h"
5 #include "bcwindowbase.h"
18 TextureID::TextureID(int window_id, int id, int w, int h, int components)
20 this->window_id = window_id;
24 this->components = components;
28 ShaderID::ShaderID(int window_id, unsigned int handle, char *source)
30 this->window_id = window_id;
31 this->handle = handle;
32 this->source = strdup(source);
41 PBufferID::PBufferID(int window_id,
43 GLXContext gl_context,
47 this->pbuffer = pbuffer;
48 this->gl_context = gl_context;
49 this->window_id = window_id;
58 BC_SynchronousCommand::BC_SynchronousCommand()
60 command = BC_SynchronousCommand::NONE;
64 command_done = new Condition(0, "BC_SynchronousCommand::command_done", 0);
67 BC_SynchronousCommand::~BC_SynchronousCommand()
72 void BC_SynchronousCommand::copy_from(BC_SynchronousCommand *command)
74 this->command = command->command;
75 this->colormodel = command->colormodel;
76 this->window = command->window;
77 this->frame = command->frame;
78 this->window_id = command->window_id;
80 this->frame_return = command->frame_return;
82 this->id = command->id;
90 BC_Synchronous::BC_Synchronous()
93 next_command = new Condition(0, "BC_Synchronous::next_command", 0);
94 command_lock = new Mutex("BC_Synchronous::command_lock");
95 table_lock = new Mutex("BC_Synchronous::table_lock");
99 BC_WindowBase::get_resources()->set_synchronous(this);
102 BC_Synchronous::~BC_Synchronous()
104 commands.remove_all_objects();
107 BC_SynchronousCommand* BC_Synchronous::new_command()
109 return new BC_SynchronousCommand;
112 void BC_Synchronous::create_objects()
116 void BC_Synchronous::start()
121 void BC_Synchronous::quit()
123 command_lock->lock("BC_Synchronous::quit");
124 BC_SynchronousCommand *command = new_command();
125 commands.append(command);
126 command->command = BC_SynchronousCommand::QUIT;
127 command_lock->unlock();
129 next_command->unlock();
132 int BC_Synchronous::send_command(BC_SynchronousCommand *command)
134 command_lock->lock("BC_Synchronous::send_command");
135 BC_SynchronousCommand *command2 = new_command();
136 commands.append(command2);
137 command2->copy_from(command);
138 command_lock->unlock();
140 next_command->unlock();
141 //printf("BC_Synchronous::send_command 1 %d\n", next_command->get_value());
143 // Wait for completion
144 command2->command_done->lock("BC_Synchronous::send_command");
145 int result = command2->result;
150 void BC_Synchronous::run()
155 next_command->lock("BC_Synchronous::run");
158 command_lock->lock("BC_Synchronous::run");
159 BC_SynchronousCommand *command = 0;
162 command = commands.values[0];
163 commands.remove_number(0);
165 // Prevent executing the same command twice if spurious unlock.
166 command_lock->unlock();
167 //printf("BC_Synchronous::run %d\n", command->command);
169 handle_command_base(command);
175 void BC_Synchronous::handle_command_base(BC_SynchronousCommand *command)
180 //printf("BC_Synchronous::handle_command_base 1 %d\n", command->command);
181 switch(command->command)
183 case BC_SynchronousCommand::QUIT:
188 handle_command(command);
197 command->command_done->unlock();
201 void BC_Synchronous::handle_command(BC_SynchronousCommand *command)
205 void BC_Synchronous::handle_garbage()
209 table_lock->lock("BC_Synchronous::handle_garbage");
212 table_lock->unlock();
216 BC_SynchronousCommand *command = garbage.values[0];
217 garbage.remove_number(0);
218 table_lock->unlock();
220 switch(command->command)
222 case BC_SynchronousCommand::DELETE_WINDOW:
223 delete_window_sync(command);
226 case BC_SynchronousCommand::DELETE_PIXMAP:
227 delete_pixmap_sync(command);
235 void BC_Synchronous::put_texture(int id, int w, int h, int components)
239 table_lock->lock("BC_Resources::put_texture");
240 // Search for duplicate
241 for(int i = 0; i < texture_ids.total; i++)
243 TextureID *ptr = texture_ids.values[i];
244 if(ptr->window_id == current_window->get_id() &&
247 printf("BC_Synchronous::push_texture: texture exists\n"
248 "exists: window=%d id=%d w=%d h=%d\n"
249 "new: window=%d id=%d w=%d h=%d\n",
254 current_window->get_id(),
258 table_lock->unlock();
263 TextureID *new_id = new TextureID(current_window->get_id(),
268 texture_ids.append(new_id);
269 table_lock->unlock();
273 int BC_Synchronous::get_texture(int w, int h, int components)
275 table_lock->lock("BC_Resources::get_texture");
276 for(int i = 0; i < texture_ids.total; i++)
278 if(texture_ids.values[i]->w == w &&
279 texture_ids.values[i]->h == h &&
280 texture_ids.values[i]->components == components &&
281 !texture_ids.values[i]->in_use &&
282 texture_ids.values[i]->window_id == current_window->get_id())
284 int result = texture_ids.values[i]->id;
285 texture_ids.values[i]->in_use = 1;
286 table_lock->unlock();
290 table_lock->unlock();
294 void BC_Synchronous::release_texture(int window_id, int id)
296 table_lock->lock("BC_Resources::release_texture");
297 for(int i = 0; i < texture_ids.total; i++)
299 if(texture_ids.values[i]->id == id &&
300 texture_ids.values[i]->window_id == window_id)
302 texture_ids.values[i]->in_use = 0;
303 table_lock->unlock();
307 table_lock->unlock();
314 unsigned int BC_Synchronous::get_shader(char *source, int *got_it)
316 table_lock->lock("BC_Resources::get_shader");
317 for(int i = 0; i < shader_ids.total; i++)
319 if(shader_ids.values[i]->window_id == current_window->get_id() &&
320 !strcmp(shader_ids.values[i]->source, source))
322 unsigned int result = shader_ids.values[i]->handle;
323 table_lock->unlock();
328 table_lock->unlock();
333 void BC_Synchronous::put_shader(unsigned int handle,
336 table_lock->lock("BC_Resources::put_shader");
337 shader_ids.append(new ShaderID(current_window->get_id(), handle, source));
338 table_lock->unlock();
341 void BC_Synchronous::dump_shader(unsigned int handle)
344 table_lock->lock("BC_Resources::dump_shader");
345 for(int i = 0; i < shader_ids.total; i++)
347 if(shader_ids.values[i]->handle == handle)
349 printf("BC_Synchronous::dump_shader\n"
350 "%s", shader_ids.values[i]->source);
355 table_lock->unlock();
356 if(!got_it) printf("BC_Synchronous::dump_shader couldn't find %d\n", handle);
360 void BC_Synchronous::delete_window(BC_WindowBase *window)
363 BC_SynchronousCommand *command = new_command();
364 command->command = BC_SynchronousCommand::DELETE_WINDOW;
365 command->window_id = window->get_id();
366 command->display = window->get_display();
367 command->win = window->win;
368 command->gl_context = window->gl_win_context;
370 send_garbage(command);
374 void BC_Synchronous::delete_window_sync(BC_SynchronousCommand *command)
377 int window_id = command->window_id;
378 Display *display = command->display;
379 Window win = command->win;
380 GLXContext gl_context = command->gl_context;
383 // texture ID's are unique to different contexts
384 glXMakeCurrent(display,
388 table_lock->lock("BC_Resources::release_textures");
389 for(int i = 0; i < texture_ids.total; i++)
391 if(texture_ids.values[i]->window_id == window_id)
393 GLuint id = texture_ids.values[i]->id;
394 glDeleteTextures(1, &id);
396 printf("BC_Synchronous::delete_window_sync texture_id=%d window_id=%d\n",
399 texture_ids.remove_object_number(i);
404 for(int i = 0; i < shader_ids.total; i++)
406 if(shader_ids.values[i]->window_id == window_id)
408 glDeleteShader(shader_ids.values[i]->handle);
410 printf("BC_Synchronous::delete_window_sync shader_id=%d window_id=%d\n",
411 shader_ids.values[i]->handle,
413 shader_ids.remove_object_number(i);
418 for(int i = 0; i < pbuffer_ids.total; i++)
420 if(pbuffer_ids.values[i]->window_id == window_id)
422 glXDestroyPbuffer(display, pbuffer_ids.values[i]->pbuffer);
423 glXDestroyContext(display, pbuffer_ids.values[i]->gl_context);
425 printf("BC_Synchronous::delete_window_sync pbuffer_id=%p window_id=%d\n",
426 pbuffer_ids.values[i]->pbuffer,
428 pbuffer_ids.remove_object_number(i);
434 table_lock->unlock();
436 XDestroyWindow(display, win);
437 if(gl_context) glXDestroyContext(display, gl_context);
444 void BC_Synchronous::put_pbuffer(int w,
447 GLXContext gl_context)
450 table_lock->lock("BC_Resources::release_textures");
451 for(int i = 0; i < pbuffer_ids.total; i++)
453 PBufferID *ptr = pbuffer_ids.values[i];
456 ptr->pbuffer == pbuffer)
467 PBufferID *ptr = new PBufferID(current_window->get_id(),
472 pbuffer_ids.append(ptr);
474 table_lock->unlock();
477 GLXPbuffer BC_Synchronous::get_pbuffer(int w,
480 GLXContext *gl_context)
482 table_lock->lock("BC_Resources::release_textures");
483 for(int i = 0; i < pbuffer_ids.total; i++)
485 PBufferID *ptr = pbuffer_ids.values[i];
488 ptr->window_id == current_window->get_id() &&
491 GLXPbuffer result = ptr->pbuffer;
492 *gl_context = ptr->gl_context;
493 *window_id = ptr->window_id;
495 table_lock->unlock();
499 table_lock->unlock();
503 void BC_Synchronous::release_pbuffer(int window_id, GLXPbuffer pbuffer)
505 table_lock->lock("BC_Resources::release_textures");
506 for(int i = 0; i < pbuffer_ids.total; i++)
508 PBufferID *ptr = pbuffer_ids.values[i];
509 if(ptr->window_id == window_id)
514 table_lock->unlock();
517 void BC_Synchronous::delete_pixmap(BC_WindowBase *window,
521 BC_SynchronousCommand *command = new_command();
522 command->command = BC_SynchronousCommand::DELETE_PIXMAP;
523 command->window_id = window->get_id();
524 command->display = window->get_display();
525 command->win = window->win;
526 command->gl_pixmap = pixmap;
527 command->gl_context = context;
529 send_garbage(command);
533 void BC_Synchronous::delete_pixmap_sync(BC_SynchronousCommand *command)
536 Display *display = command->display;
537 Window win = command->win;
538 glXMakeCurrent(display,
540 command->gl_context);
541 glXDestroyContext(display, command->gl_context);
542 glXDestroyGLXPixmap(display, command->gl_pixmap);
548 void BC_Synchronous::send_garbage(BC_SynchronousCommand *command)
550 table_lock->lock("BC_Synchronous::delete_window");
551 garbage.append(command);
552 table_lock->unlock();
554 next_command->unlock();
557 BC_WindowBase* BC_Synchronous::get_window()
559 return current_window;