#include "bcwindowbase.h"
#include "vframe.h"
-#if defined(HAVE_CONFIG_H)
-#include "config.h"
-#endif
#ifdef HAVE_GL
#include <GL/gl.h>
#include <GL/glext.h>
#endif
}
-void VFrame::to_ram()
-{
-#ifdef HAVE_GL
- switch(opengl_state)
- {
-// Only pbuffer is supported since this is only called after the
-// overlay operation onto the pbuffer.
- case VFrame::SCREEN:
- if(pbuffer)
- {
- enable_opengl();
-//printf("VFrame::to_ram %d %d\n", get_w(), get_h());
- glReadPixels(0,
- 0,
- get_w(),
- get_h(),
- GL_RGB,
- GL_UNSIGNED_BYTE,
- get_rows()[0]);
- flip_vert();
- }
- opengl_state = VFrame::RAM;
- return;
- }
-#endif
-}
-
void VFrame::create_pbuffer()
{
if(pbuffer &&
#ifdef HAVE_GL
// Create texture
BC_Texture::new_texture(&texture,
- get_w(),
- get_h(),
- get_color_model());
+ get_w(), get_h(), get_color_model());
- if(pbuffer)
- {
+ if(pbuffer) {
glEnable(GL_TEXTURE_2D);
// Read canvas into texture, use back texture for DOUBLE_BUFFER
#endif
}
-void VFrame::draw_texture(float in_x1,
- float in_y1,
- float in_x2,
- float in_y2,
- float out_x1,
- float out_y1,
- float out_x2,
- float out_y2,
- int flip_y)
+void VFrame::screen_to_ram()
{
#ifdef HAVE_GL
- glBegin(GL_QUADS);
- glNormal3f(0, 0, 1.0);
-
- glTexCoord2f(in_x1 / get_texture_w(), in_y1 / get_texture_h());
- glVertex3f(out_x1, flip_y ? -out_y1 : -out_y2, 0);
-
- glTexCoord2f(in_x2 / get_texture_w(), in_y1 / get_texture_h());
- glVertex3f(out_x2, flip_y ? -out_y1 : -out_y2, 0);
-
- glTexCoord2f(in_x2 / get_texture_w(), in_y2 / get_texture_h());
- glVertex3f(out_x2, flip_y ? -out_y2 : -out_y1, 0);
-
- glTexCoord2f(in_x1 / get_texture_w(), in_y2 / get_texture_h());
- glVertex3f(out_x1, flip_y ? -out_y2 : -out_y1, 0);
-
-
- glEnd();
+ enable_opengl();
+ glReadBuffer(GL_BACK);
+ int type = BC_CModels::is_float(color_model) ? GL_FLOAT : GL_UNSIGNED_BYTE;
+ int format = BC_CModels::has_alpha(color_model) ? GL_RGBA : GL_RGB;
+ glReadPixels(0, 0, get_w(), get_h(), format, type, get_rows()[0]);
+ opengl_state = VFrame::RAM;
+#endif
+}
+void VFrame::draw_texture(
+ float in_x1, float in_y1, float in_x2, float in_y2,
+ float out_x1, float out_y1, float out_x2, float out_y2,
+ int flip_y)
+{
+#ifdef HAVE_GL
+ in_x1 /= get_texture_w(); in_y1 /= get_texture_h();
+ in_x2 /= get_texture_w(); in_y2 /= get_texture_h();
+ float ot_y1 = flip_y ? -out_y1 : -out_y2;
+ float ot_y2 = flip_y ? -out_y2 : -out_y1;
+ texture->draw_texture(
+ in_x1,in_y1, in_x2,in_y2,
+ out_x1,ot_y1, out_x2, ot_y2);
#endif
}
void VFrame::draw_texture(int flip_y)
{
- draw_texture(0,
- 0,
- get_w(),
- get_h(),
- 0,
- 0,
- get_w(),
- get_h(),
- flip_y);
+ draw_texture(0,0, get_w(),get_h(),
+ 0,0, get_w(),get_h(), flip_y);
}
glGetShaderInfoLog(object, BCTEXTLEN, &len, string);
if(len > 0) printf("Playback3D::print_error:\n%s\n%s\n", source, string);
if(len > 0) return 1;
- return 0;
#endif
+ return 0;
}
+// call as:
+// make_shader(0, frag1, .., fragn, 0);
+// or make_shader(fragments);
-
-unsigned int VFrame::make_shader(int x, ...)
+unsigned int VFrame::make_shader(const char **fragments, ...)
{
unsigned int result = 0;
#ifdef HAVE_GL
// Construct single source file out of arguments
- char *complete_program = 0;
- int complete_size = 0;
- int current_shader = 0;
-
- va_list list;
- va_start(list, x);
-
- while(1)
- {
- char *text = va_arg(list, char*);
- if(!text) break;
-
-// Replace one occurrance in each source of main() with a unique id.
- char main_replacement[BCTEXTLEN];
- sprintf(main_replacement, "main%03d()", current_shader);
-//printf("VFrame::make_shader %s %s\n", text, main_replacement);
- char *source_replacement = new char[strlen(text) + strlen(main_replacement) + 1];
- char *ptr = strstr(text, "main()");
-
- if(ptr)
- {
- memcpy(source_replacement, text, ptr - text);
- source_replacement[ptr - text] = 0;
- strcat(source_replacement, main_replacement);
- ptr += strlen("main()");
- strcat(source_replacement, ptr);
- current_shader++;
- }
- else
- {
- memcpy(source_replacement, text, strlen(text));
- source_replacement[strlen(text)] = 0;
- }
-
- if(!complete_program)
- {
- complete_size = strlen(source_replacement) + 1;
- complete_program = (char*)malloc(complete_size);
- strcpy(complete_program, source_replacement);
- }
- else
- {
- complete_size += strlen(source_replacement);
- complete_program = (char*)realloc(complete_program, complete_size);
- strcat(complete_program, source_replacement);
- }
-
- delete [] source_replacement;
- }
- va_end(list);
-
-// Add main() function which calls all the unique main replacements in order
- char main_function[BCTEXTLEN];
- sprintf(main_function,
- "\n"
- "void main()\n"
- "{\n");
-
- for(int i = 0; i < current_shader; i++)
- {
- char main_replacement[BCTEXTLEN];
- sprintf(main_replacement, "\tmain%03d();\n", i);
- strcat(main_function, main_replacement);
- }
-
- strcat(main_function, "}\n");
- if(!complete_program)
- {
- complete_size = strlen(main_function) + 1;
- complete_program = (char*)malloc(complete_size);
- strcpy(complete_program, main_function);
+ char *program = 0;
+ int nb_mains = 0;
+
+ int nb_frags = 1;
+ if( !fragments ) {
+ va_list list; va_start(list, fragments);
+ while( va_arg(list, char*) != 0 ) ++nb_frags;
+ va_end(list);
}
- else
- {
- complete_size += strlen(main_function);
- complete_program = (char*)realloc(complete_program, complete_size);
- strcat(complete_program, main_function);
+ const char *frags[nb_frags], *text = 0;
+ if( !fragments ) {
+ va_list list; va_start(list, fragments);
+ for( int i=0; i<nb_frags; ++i ) frags[i] = va_arg(list, char*);
+ va_end(list);
+ fragments = frags;
}
+ while( (text = *fragments++) ) {
+ char src[strlen(text) + BCSTRLEN + 1];
+ const char *tp = strstr(text, "main()");
+ if( tp ) {
+// Replace main() with a mainxxx()
+ char mainxxx[BCSTRLEN], *sp = src;
+ sprintf(mainxxx, "main%03d()", nb_mains++);
+ int n = tp - text;
+ memcpy(sp, text, n); sp += n;
+ n = strlen(mainxxx);
+ memcpy(sp, mainxxx, n); sp += n;
+ tp += strlen("main()");
+ strcpy(sp, tp);
+ text = src;
+ }
+ char *new_program = !program ? cstrdup(text) :
+ cstrcat(2, program, text);
+ delete [] program; program = new_program;
+ }
-
+// Add main() which calls mainxxx() in order
+ char main_program[BCTEXTLEN], *cp = main_program;
+ cp += sprintf(cp, "\nvoid main() {\n");
+ for( int i=0; i < nb_mains; ++i )
+ cp += sprintf(cp, "\tmain%03d();\n", i);
+ cp += sprintf(cp, "}\n");
+ cp = !program ? cstrdup(main_program) :
+ cstrcat(2, program, main_program);
+ delete [] program; program = cp;
int got_it = 0;
- result = BC_WindowBase::get_synchronous()->get_shader(complete_program,
- &got_it);
-
- if(!got_it)
- {
+ result = BC_WindowBase::get_synchronous()->get_shader(program, &got_it);
+ if( !got_it ) {
result = glCreateProgram();
-
- unsigned int shader;
- shader = glCreateShader(GL_FRAGMENT_SHADER);
- const GLchar *text_ptr = complete_program;
+ unsigned int shader = glCreateShader(GL_FRAGMENT_SHADER);
+ const GLchar *text_ptr = program;
glShaderSource(shader, 1, &text_ptr, NULL);
glCompileShader(shader);
- int error = print_error(complete_program, shader, 0);
+ int error = print_error(program, shader, 0);
glAttachShader(result, shader);
glDeleteShader(shader);
-
glLinkProgram(result);
- if(!error) error = print_error(complete_program, result, 1);
-
-
-// printf("BC_WindowBase::make_shader: shader=%d window_id=%d\n",
-// result,
+ if( !error )
+ error = print_error(program, result, 1);
+//printf("BC_WindowBase::make_shader: shader=%d window_id=%d\n", result,
// BC_WindowBase::get_synchronous()->current_window->get_id());
- BC_WindowBase::get_synchronous()->put_shader(result, complete_program);
+ BC_WindowBase::get_synchronous()->put_shader(result, program);
}
-//printf("VFrame::make_shader\n%s\n", complete_program);
- free(complete_program);
- complete_program = NULL;
-
+//printf("VFrame::make_shader\n%s\n", program);
#endif
return result;
}