1 #define GL_GLEXT_PROTOTYPES
4 #include "bcresources.h"
6 #include "bcsynchronous.h"
8 #include "bcwindowbase.h"
11 #if defined(HAVE_CONFIG_H)
25 int VFrame::get_opengl_state()
30 void VFrame::set_opengl_state(int value)
35 int VFrame::get_window_id()
37 return texture ? texture->window_id : -1;
40 int VFrame::get_texture_id()
42 return texture ? texture->texture_id : -1;
45 int VFrame::get_texture_w()
47 return texture ? texture->texture_w : 0;
50 int VFrame::get_texture_h()
52 return texture ? texture->texture_h : 0;
56 int VFrame::get_texture_components()
58 return texture ? texture->texture_components : 0;
71 void VFrame::to_texture()
75 // Must be here so user can create textures without copying data by setting
76 // opengl_state to TEXTURE.
77 BC_Texture::new_texture(&texture,
82 // Determine what to do based on state
89 if((get_w() % 4) || (get_h() % 4))
91 printf("VFrame::to_texture w=%d h=%d\n", get_w(), get_h());
99 opengl_state = VFrame::TEXTURE;
103 //printf("VFrame::to_texture %d\n", texture_id);
109 glTexSubImage2D(GL_TEXTURE_2D,
122 glTexSubImage2D(GL_TEXTURE_2D,
134 glTexSubImage2D(GL_TEXTURE_2D,
146 glTexSubImage2D(GL_TEXTURE_2D,
159 "VFrame::to_texture: unsupported color model %d.\n",
164 opengl_state = VFrame::TEXTURE;
168 void VFrame::to_ram()
173 // Only pbuffer is supported since this is only called after the
174 // overlay operation onto the pbuffer.
179 printf("VFrame::to_ram %d %d\n", get_w(), get_h());
189 opengl_state = VFrame::RAM;
195 void VFrame::create_pbuffer()
199 pbuffer->window_id != BC_WindowBase::get_synchronous()->current_window->get_id())
207 if((get_w() % 4) || (get_h() % 4))
209 printf("VFrame::create_pbuffer w=%d h=%d\n", get_w(), get_h());
216 pbuffer = new BC_PBuffer(get_w(), get_h());
221 void VFrame::enable_opengl()
226 pbuffer->enable_opengl();
230 BC_PBuffer* VFrame::get_pbuffer()
236 void VFrame::screen_to_texture(int x, int y, int w, int h)
240 BC_Texture::new_texture(&texture,
247 glEnable(GL_TEXTURE_2D);
249 // Read canvas into texture
250 // According to the man page, it must be GL_BACK for the onscreen buffer
251 // and GL_FRONT for a single buffered PBuffer. In reality it must be
252 // GL_BACK for a single buffered PBuffer if the PBuffer has alpha and using
253 // GL_FRONT captures the onscreen front buffer.
254 // glReadBuffer(BC_WindowBase::get_synchronous()->is_pbuffer ?
255 // GL_FRONT : GL_BACK);
256 glReadBuffer(GL_BACK);
257 glCopyTexSubImage2D(GL_TEXTURE_2D,
263 w >= 0 ? w : get_w(),
264 h >= 0 ? h : get_h());
269 void VFrame::draw_texture(float in_x1,
281 glNormal3f(0, 0, 1.0);
283 glTexCoord2f(in_x1 / get_texture_w(), in_y1 / get_texture_h());
284 glVertex3f(out_x1, flip_y ? -out_y1 : -out_y2, 0);
286 glTexCoord2f(in_x2 / get_texture_w(), in_y1 / get_texture_h());
287 glVertex3f(out_x2, flip_y ? -out_y1 : -out_y2, 0);
289 glTexCoord2f(in_x2 / get_texture_w(), in_y2 / get_texture_h());
290 glVertex3f(out_x2, flip_y ? -out_y2 : -out_y1, 0);
292 glTexCoord2f(in_x1 / get_texture_w(), in_y2 / get_texture_h());
293 glVertex3f(out_x1, flip_y ? -out_y2 : -out_y1, 0);
301 void VFrame::draw_texture(int flip_y)
315 void VFrame::bind_texture(int texture_unit)
320 texture->bind(texture_unit);
329 void VFrame::init_screen(int w, int h)
332 glViewport(0, 0, w, h);
333 glMatrixMode(GL_PROJECTION);
337 float frustum_ratio = near / ((near + far) / 2);
338 float near_h = (float)h *
340 float near_w = (float)w *
342 glFrustum(-near_w / 2,
348 glMatrixMode(GL_MODELVIEW);
350 // Shift down and right so 0,0 is the top left corner
351 glTranslatef(-w / 2, h / 2, 0.0);
352 glTranslatef(0.0, 0.0, -(far + near) / 2);
354 glDisable(GL_DEPTH_TEST);
355 glShadeModel(GL_SMOOTH);
356 // Default for direct copy playback
358 glDisable(GL_COLOR_MATERIAL);
359 glDisable(GL_CULL_FACE);
360 glEnable(GL_NORMALIZE);
361 glAlphaFunc(GL_GREATER, 0);
362 glDisable(GL_LIGHTING);
364 const GLfloat one[] = { 1, 1, 1, 1 };
365 const GLfloat zero[] = { 0, 0, 0, 0 };
366 const GLfloat light_position[] = { 0, 0, -1, 0 };
367 const GLfloat light_direction[] = { 0, 0, 1, 0 };
369 // glEnable(GL_LIGHT0);
370 // glLightfv(GL_LIGHT0, GL_AMBIENT, zero);
371 // glLightfv(GL_LIGHT0, GL_DIFFUSE, one);
372 // glLightfv(GL_LIGHT0, GL_SPECULAR, one);
373 // glLighti(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
374 // glLightfv(GL_LIGHT0, GL_POSITION, light_position);
375 // glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
376 // glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
377 // glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zero);
378 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
379 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
380 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zero);
381 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, zero);
382 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0);
386 void VFrame::init_screen()
388 init_screen(get_w(), get_h());
391 static int print_error(char *source, unsigned int object, int is_program)
394 char string[BCTEXTLEN];
397 glGetProgramInfoLog(object, BCTEXTLEN, &len, string);
399 glGetShaderInfoLog(object, BCTEXTLEN, &len, string);
400 if(len > 0) printf("Playback3D::print_error:\n%s\n%s\n", source, string);
401 if(len > 0) return 1;
410 unsigned int VFrame::make_shader(int x, ...)
412 unsigned int result = 0;
414 // Construct single source file out of arguments
415 char *complete_program = 0;
416 int complete_size = 0;
417 int current_shader = 0;
424 char *text = va_arg(list, char*);
428 // Replace one occurrance in each source of main() with a unique id.
429 char main_replacement[BCTEXTLEN];
431 sprintf(main_replacement, "main%03d()", current_shader);
432 //printf("VFrame::make_shader %s %s\n", text, main_replacement);
434 char *source_replacement = new char[strlen(text) + strlen(main_replacement) + 1];
436 char *ptr = strstr(text, "main()");
441 memcpy(source_replacement, text, ptr - text);
442 source_replacement[ptr - text] = 0;
443 strcat(source_replacement, main_replacement);
444 ptr += strlen("main()");
445 strcat(source_replacement, ptr);
450 memcpy(source_replacement, text, strlen(text));
451 source_replacement[strlen(text)] = 0;
455 if(!complete_program)
457 complete_size = strlen(source_replacement) + 1;
458 complete_program = (char*)malloc(complete_size);
459 strcpy(complete_program, source_replacement);
463 complete_size += strlen(source_replacement);
464 complete_program = (char*)realloc(complete_program, complete_size);
465 strcat(complete_program, source_replacement);
468 delete [] source_replacement;
472 // Add main() function which calls all the unique main replacements in order
473 char main_function[BCTEXTLEN];
474 sprintf(main_function,
479 for(int i = 0; i < current_shader; i++)
481 char main_replacement[BCTEXTLEN];
482 sprintf(main_replacement, "\tmain%03d();\n", i);
483 strcat(main_function, main_replacement);
486 strcat(main_function, "}\n");
487 if(!complete_program)
489 complete_size = strlen(main_function) + 1;
490 complete_program = (char*)malloc(complete_size);
491 strcpy(complete_program, main_function);
495 complete_size += strlen(main_function);
496 complete_program = (char*)realloc(complete_program, complete_size);
497 strcat(complete_program, main_function);
505 result = BC_WindowBase::get_synchronous()->get_shader(complete_program,
510 result = glCreateProgram();
513 shader = glCreateShader(GL_FRAGMENT_SHADER);
514 const GLchar *text_ptr = complete_program;
515 glShaderSource(shader, 1, &text_ptr, NULL);
516 glCompileShader(shader);
517 int error = print_error(complete_program, shader, 0);
518 glAttachShader(result, shader);
519 glDeleteShader(shader);
521 glLinkProgram(result);
522 if(!error) error = print_error(complete_program, result, 1);
525 // printf("BC_WindowBase::make_shader: shader=%d window_id=%d\n",
527 // BC_WindowBase::get_synchronous()->current_window->get_id());
528 BC_WindowBase::get_synchronous()->put_shader(result, complete_program);
531 //printf("VFrame::make_shader\n%s\n", complete_program);
532 delete [] complete_program;
538 void VFrame::dump_shader(int shader_id)
540 BC_WindowBase::get_synchronous()->dump_shader(shader_id);
544 void VFrame::clear_pbuffer()
547 if(cmodel_is_yuv(get_color_model()))
548 glClearColor(0.0, 0.5, 0.5, 0.0);
550 glClearColor(0.0, 0.0, 0.0, 0.0);
551 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);