diff --git a/README.md b/README.md index 94b93b860..684a35045 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,14 @@ EGL, mmal, GLESv2, vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG. Use buildme to build. It requires cmake to be installed and an arm cross compiler. It is set up to use this one: https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian +Raspistill shader parameters can be controlled through OpenSoundControl. +To enable that, you need liblo-dev package. +`sudo apt-get install liblo7 liblo-dev` +Install it and run ./buildme to build raspistill with OSC support. +Then you can control each shader parameters with OSC message. + +To cross-compile with liblo support, you can download deb package on your pi with this command : +`apt-get download liblo7 liblo-dev` +Then extract them in the folder returned by : `arm-linux-gnueabihf-gcc -print-sysroot`. + Note that this repository does not contain the source for the edid_parser and vcdbg binaries due to licensing restrictions. diff --git a/host_applications/linux/apps/raspicam/CMakeLists.txt b/host_applications/linux/apps/raspicam/CMakeLists.txt index f7db21e16..22e0dd04a 100644 --- a/host_applications/linux/apps/raspicam/CMakeLists.txt +++ b/host_applications/linux/apps/raspicam/CMakeLists.txt @@ -36,6 +36,7 @@ set (GL_SCENE_SOURCES gl_scenes/sobel.c gl_scenes/square.c gl_scenes/teapot.c + gl_scenes/shader.c gl_scenes/vcsm_square.c) set (COMMON_SOURCES @@ -54,6 +55,14 @@ add_executable(raspividyuv ${COMMON_SOURCES} RaspiVidYUV.c) set (MMAL_LIBS mmal_core mmal_util mmal_vc_client) +FIND_PACKAGE(liblo) +if(LIBLO_FOUND) + message( STATUS "Building with OSC support !") + add_definitions(-DHAVE_LIBLO) + include_directories(${LIBLO_INCLUDE_DIRS}) + target_link_libraries(raspistill ${LIBLO_LIBRARIES}) +endif() + target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host brcmGLESv2 brcmEGL m dl) target_link_libraries(raspiyuv ${MMAL_LIBS} vcos bcm_host) target_link_libraries(raspivid ${MMAL_LIBS} vcos bcm_host) diff --git a/host_applications/linux/apps/raspicam/RaspiStill.c b/host_applications/linux/apps/raspicam/RaspiStill.c index 638b3c6c4..ac4b4e8de 100644 --- a/host_applications/linux/apps/raspicam/RaspiStill.c +++ b/host_applications/linux/apps/raspicam/RaspiStill.c @@ -87,6 +87,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "gl_scenes/shader.h" + +#ifdef HAVE_LIBLO +#include +#endif + // Standard port setting for the camera component #define MMAL_CAMERA_PREVIEW_PORT 0 #define MMAL_CAMERA_VIDEO_PORT 1 @@ -158,6 +164,12 @@ typedef struct MMAL_POOL_T *encoder_pool; /// Pointer to the pool of buffers used by encoder output port RASPITEX_STATE raspitex_state; /// GL renderer state and parameters + + #ifdef HAVE_LIBLO + lo_server_thread osc_server; + char* osc_inport; + #endif + int useOSC; } RASPISTILL_STATE; @@ -194,6 +206,9 @@ enum CommandTimeStamp, CommandFrameStart, CommandRestartInterval, + CommandOSCport, + CommandFragmentShader, + CommandVertexShader, }; static COMMAND_LIST cmdline_commands[] = @@ -217,6 +232,9 @@ static COMMAND_LIST cmdline_commands[] = { CommandTimeStamp, "-timestamp", "ts", "Replace output pattern (%d) with unix timestamp (seconds since 1970)", 0}, { CommandFrameStart,"-framestart","fs", "Starting frame number in output pattern(%d)", 1}, { CommandRestartInterval, "-restart","rs","JPEG Restart interval (default of 0 for none)", 1}, + { CommandOSCport, "-oscport", "oscp", "OSC input port", 1 }, + { CommandFragmentShader, "-fragmentshader", "frag", "fragment shader program file", 1 }, + { CommandVertexShader, "-fragmentshader", "vert", "vertex shader program file", 1 }, }; static int cmdline_commands_size = sizeof(cmdline_commands) / sizeof(cmdline_commands[0]); @@ -300,6 +318,7 @@ static void default_status(RASPISTILL_STATE *state) state->datetime = 0; state->timestamp = 0; state->restart_interval = 0; + state->useOSC = 0; // Setup preview window defaults raspipreview_set_defaults(&state->preview_parameters); @@ -636,6 +655,60 @@ static int parse_cmdline(int argc, const char **argv, RASPISTILL_STATE *state) break; } + case CommandOSCport: // Set OSC port (only valid with shader scene) + { +#ifdef HAVE_LIBLO + int len = strlen(argv[i + 1]); + if (len) + { + state->osc_inport = malloc(len+1); // leave enough space for any timelapse generated changes to filename + vcos_assert(state->osc_inport); + if (state->osc_inport) + strncpy(state->osc_inport, argv[i + 1], len+1); + i++; + state->useOSC=1; + } + else + valid = 0; + break; +#else + fprintf(stderr, "OSC port passed as argument put Raspistill have been build without liblo !"); + fprintf(stderr, "OSC is disable."); +#endif /* HAVE_LIBLO */ + } + + case CommandFragmentShader: // Set fragment shader file to load + { + int len = strlen(argv[i + 1]); + if (len) + { + state->raspitex_state.fragment_shader_filename = malloc(len+1); // leave enough space for any timelapse generated changes to filename + vcos_assert(state->raspitex_state->fragment_shader_filename); + if (state->raspitex_state.fragment_shader_filename) + strncpy(state->raspitex_state.fragment_shader_filename, argv[i + 1], len+1); + i++; + } + else + valid = 0; + break; + } + + case CommandVertexShader: // Set vertex shader file to load + { + int len = strlen(argv[i + 1]); + if (len) + { + state->raspitex_state.vertex_shader_filename = malloc(len+1); // leave enough space for any timelapse generated changes to filename + vcos_assert(state->raspitex_state->vertex_shader_filename); + if (state->raspitex_state.vertex_shader_filename) + strncpy(state->raspitex_state.vertex_shader_filename, argv[i + 1], len+1); + i++; + } + else + valid = 0; + break; + } + default: { // Try parsing for any image specific parameters @@ -1629,6 +1702,53 @@ static void rename_file(RASPISTILL_STATE *state, FILE *output_file, } } +#ifdef HAVE_LIBLO +void osc_error(int num, const char *msg, const char *path) +{ + printf("liblo server error %d in path %s: %s\n", num, path, msg); + fflush(stdout); +} + +void osc_generic_handler(const char *path, const char *types, lo_arg ** argv, + int argc, void *data, void *user_data) +{ + int i; + + RASPISTILL_STATE *state = user_data; + RASPITEXUTIL_SHADER_PROGRAM_T *shader = shader_get_shader(); + + if (state->verbose) + { + fprintf(stderr, "Receive OSC message : %s with %d values\n", path, argc); + } + + for (i=0;iuniform_count;i++){ + if ( strcmp(shader->uniform_array[i].name, path+1) == 0 ){ + int j; + for (j=0;juniform_array[i].param[j]= (GLfloat) argv[j]->f; + } else if ( types[j] == 'i' ){ + shader->uniform_array[i].param[j]= (GLfloat) argv[j]->i; + } else { + printf("%s parameter #%d wrong type (%c)! only float or int are allowed !\n",path,j,types[j]); + } + } + shader->uniform_array[i].flag = 1; + break; + } + } +} + +static void init_osc(RASPISTILL_STATE *state) +{ + printf("initialize OSC server on port %s\n", state->osc_inport); + state->osc_server = lo_server_thread_new(state->osc_inport, osc_error); + /* add method that will match any path and args */ + lo_server_thread_add_method(state->osc_server , NULL, NULL, (lo_method_handler) osc_generic_handler, state); + lo_server_thread_start(state->osc_server); +} +#endif /* HAVE_LIBLO */ /** * main @@ -1697,6 +1817,11 @@ int main(int argc, const char **argv) if (state.useGL) raspitex_init(&state.raspitex_state); +#ifdef HAVE_LIBLO + if (state.useOSC) + init_osc(&state); +#endif + // OK, we have a nice set of parameters. Now set up our components // We have three components. Camera, Preview and encoder. // Camera and encoder are different in stills/video, but preview diff --git a/host_applications/linux/apps/raspicam/RaspiTex.c b/host_applications/linux/apps/raspicam/RaspiTex.c index d70ef4471..4c47bb770 100644 --- a/host_applications/linux/apps/raspicam/RaspiTex.c +++ b/host_applications/linux/apps/raspicam/RaspiTex.c @@ -50,6 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "gl_scenes/teapot.h" #include "gl_scenes/vcsm_square.h" #include "gl_scenes/yuv.h" +#include "gl_scenes/shader.h" /** * \file RaspiTex.c @@ -101,7 +102,7 @@ enum static COMMAND_LIST cmdline_commands[] = { - { CommandGLScene, "-glscene", "gs", "GL scene square,teapot,mirror,yuv,sobel,vcsm_square", 1 }, + { CommandGLScene, "-glscene", "gs", "GL scene square,teapot,mirror,yuv,sobel,vcsm_square,shader", 1 }, { CommandGLWin, "-glwin", "gw", "GL window settings <'x,y,w,h'>", 1 }, }; @@ -165,6 +166,8 @@ int raspitex_parse_cmdline(RASPITEX_STATE *state, state->scene_id = RASPITEX_SCENE_SOBEL; else if (strcmp(arg2, "vcsm_square") == 0) state->scene_id = RASPITEX_SCENE_VCSM_SQUARE; + else if (strcmp(arg2, "shader") == 0) + state->scene_id = RASPITEX_SCENE_SHADER; else vcos_log_error("Unknown scene %s", arg2); @@ -594,6 +597,9 @@ int raspitex_init(RASPITEX_STATE *state) case RASPITEX_SCENE_VCSM_SQUARE: rc = vcsm_square_open(state); break; + case RASPITEX_SCENE_SHADER: + rc = shader_open(state); + break; default: rc = -1; break; diff --git a/host_applications/linux/apps/raspicam/RaspiTex.h b/host_applications/linux/apps/raspicam/RaspiTex.h index 20b9fd644..2817ccf32 100644 --- a/host_applications/linux/apps/raspicam/RaspiTex.h +++ b/host_applications/linux/apps/raspicam/RaspiTex.h @@ -48,6 +48,7 @@ typedef enum RASPITEX_SCENE_YUV, RASPITEX_SCENE_SOBEL, RASPITEX_SCENE_VCSM_SQUARE, + RASPITEX_SCENE_SHADER, } RASPITEX_SCENE_T; @@ -175,7 +176,9 @@ typedef struct RASPITEX_STATE int verbose; /// Log FPS RASPITEX_CAPTURE capture; /// Frame-buffer capture state - + char* fragment_shader_filename; + char* vertex_shader_filename; + } RASPITEX_STATE; int raspitex_init(RASPITEX_STATE *state); diff --git a/host_applications/linux/apps/raspicam/RaspiTexUtil.c b/host_applications/linux/apps/raspicam/RaspiTexUtil.c index 664751d2e..f6b6ccb18 100644 --- a/host_applications/linux/apps/raspicam/RaspiTexUtil.c +++ b/host_applications/linux/apps/raspicam/RaspiTexUtil.c @@ -586,6 +586,24 @@ int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p) } } + /// Automatically find uniform variables + glGetProgramiv( p->program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &p->max_length); + glGetProgramiv( p->program, GL_ACTIVE_UNIFORMS, &p->uniform_count); + printf("found %d uniform variable(s) : \n",p->uniform_count); + + raspitexutil_create_param_array(p); + + GLchar *name= (GLchar*) malloc(sizeof(GLchar)*p->max_length); + GLsizei length=0; + RASPITEXUTIL_SHADER_PARAMETER_T *array = p->uniform_array; + for(i=0;iuniform_count;i++){ + glGetActiveUniform(p->program, i, p->max_length, &length, &array[i].size, &array[i].type, name); + array[i].loc = glGetUniformLocation( p->program, name ); + strncpy(array[i].name,name,length+1); + printf("\t%s\n",name); + } + free(name); + return 0; fail: @@ -599,3 +617,36 @@ int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p) return -1; } +void raspitexutil_create_param_array(RASPITEXUTIL_SHADER_PROGRAM_T *p) +{ + + int i; + + p->uniform_array = (RASPITEXUTIL_SHADER_PARAMETER_T*) malloc(sizeof (RASPITEXUTIL_SHADER_PARAMETER_T) * p->uniform_count); + p->attribute_array = (RASPITEXUTIL_SHADER_PARAMETER_T*) malloc(sizeof (RASPITEXUTIL_SHADER_PARAMETER_T) * p->attribute_count); + + RASPITEXUTIL_SHADER_PARAMETER_T* array = p->uniform_array; + // allocate maximum size for a param, which is a 4x4 matrix of floats + // in the future, only allocate for specific type + // also, technically we should handle arrays of matrices, too...sheesh! + for (i = 0; i < p->uniform_count; i++) { + int j=0; + array[i].size = 0; + array[i].type = 0; + array[i].loc = 0; + array[i].name = (GLchar*) malloc(sizeof(GLchar)* p->max_length+1);; + array[i].flag = 0; + for(j=0; j<16; j++)array[i].param[j]=0; + } + + array = p->attribute_array; + for (i = 0; i < p->attribute_count; i++) { + int j=0; + array[i].size = 0; + array[i].type = 0; + array[i].loc = 0; + array[i].name = (GLchar*) malloc(sizeof(GLchar)* p->max_length+1); + array[i].flag = 0; + for(j=0; j<16; j++)array[i].param[j]=0; + } +} diff --git a/host_applications/linux/apps/raspicam/RaspiTexUtil.h b/host_applications/linux/apps/raspicam/RaspiTexUtil.h index a741fab32..e6447af72 100644 --- a/host_applications/linux/apps/raspicam/RaspiTexUtil.h +++ b/host_applications/linux/apps/raspicam/RaspiTexUtil.h @@ -29,7 +29,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef RASPITEX_UTIL_H_ #define RASPITEX_UTIL_H_ +#ifndef VCOS_LOG_CATEGORY #define VCOS_LOG_CATEGORY (&raspitex_log_category) +#endif #include #include #include @@ -43,6 +45,19 @@ extern VCOS_LOG_CAT_T raspitex_log_category; #define SHADER_MAX_ATTRIBUTES 16 #define SHADER_MAX_UNIFORMS 16 + +typedef struct RASPITEXUTIL_SHADER_PARAMETER_T +{ + // Variables for the, uh, variables + // stolen from puredata/gem glsl_program.h, thanks guys ;-) + GLint size; + GLenum type; + GLint loc; + GLchar *name; + GLfloat param[16]; + int flag; +} RASPITEXUTIL_SHADER_PARAMETER_T; + /** * Container for a simple shader program. The uniform and attribute locations * are automatically setup by raspitex_build_shader_program. @@ -51,7 +66,16 @@ typedef struct RASPITEXUTIL_SHADER_PROGRAM_T { const char *vertex_source; /// Pointer to vertex shader source const char *fragment_source; /// Pointer to fragment shader source + + GLint max_length; /// Maximum length of parameter name; + GLint uniform_count, attribute_count; /// Number of parameters + + char* fragment_shader_filename; + char* vertex_shader_filename; + /// Array of shader paramaters (uniform and attributes) + RASPITEXUTIL_SHADER_PARAMETER_T *uniform_array, *attribute_array; + /// Array of uniform names for raspitex_build_shader_program to process const char *uniform_names[SHADER_MAX_UNIFORMS]; /// Array of attribute names for raspitex_build_shader_program to process @@ -112,5 +136,6 @@ void raspitexutil_close(RASPITEX_STATE* raspitex_state); /* Utility functions */ int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p); void raspitexutil_brga_to_rgba(uint8_t *buffer, size_t size); +void raspitexutil_create_param_array(RASPITEXUTIL_SHADER_PROGRAM_T *p); #endif /* RASPITEX_UTIL_H_ */ diff --git a/host_applications/linux/apps/raspicam/gl_scenes/shader.c b/host_applications/linux/apps/raspicam/gl_scenes/shader.c new file mode 100644 index 000000000..ed340fffc --- /dev/null +++ b/host_applications/linux/apps/raspicam/gl_scenes/shader.c @@ -0,0 +1,291 @@ +/* +Copyright (c) 2013, Broadcom Europe Ltd +Copyright (c) 2013, Tim Gover +Copyright (c) 2015, Antoine Villeret +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include "RaspiTexUtil.h" + +/* Vertex co-ordinates: + * + * v0----v1 + * | | + * | | + * | | + * v3----v2 + */ + +static const GLfloat vertices[] = +{ +#define V0 -0.8, 0.8, 0.8, +#define V1 0.8, 0.8, 0.8, +#define V2 0.8, -0.8, 0.8, +#define V3 -0.8, -0.8, 0.8, + V0 V3 V2 V2 V1 V0 +}; + +/* Texture co-ordinates: + * + * (0,0) b--c + * | | + * a--d + * + * b,a,d d,c,b + */ +static const GLfloat tex_coords[] = +{ + 0, 0, 0, 1, 1, 1, + 1, 1, 1, 0, 0, 0 +}; + +RASPITEXUTIL_SHADER_PROGRAM_T shader; + +static int shader_init(RASPITEX_STATE *state) +{ + int rc = raspitexutil_gl_init_2_0(state); + if (rc != 0) + goto end; + + rc = raspitexutil_build_shader_program(&shader); +end: + return rc; +} + +static int shader_update_shader(RASPITEX_STATE *state) +{ + int i; + + RASPITEXUTIL_SHADER_PARAMETER_T *array = shader.uniform_array; + + for(i=0; i 0) + { + switch (array[i].type) + { + /* float vectors */ + case GL_FLOAT: + glUniform1f( array[i].loc, array[i].param[0] ); + break; + case GL_FLOAT_VEC2: + glUniform2f( array[i].loc, (array[i].param[0]), (array[i].param[1]) ); + break; + case GL_FLOAT_VEC3: + glUniform3f( array[i].loc, (array[i].param[0]), (array[i].param[1]), + (array[i].param[2]) ); + break; + case GL_FLOAT_VEC4: + glUniform4f( array[i].loc, (array[i].param[0]), (array[i].param[1]), + (array[i].param[2]), (array[i].param[3]) ); + break; + /* int vectors */ + case GL_INT: + glUniform1i( array[i].loc, (array[i].param[0]) ); + break; + case GL_INT_VEC2: + glUniform2i( array[i].loc, (array[i].param[0]), (array[i].param[1]) ); + break; + case GL_INT_VEC3: + glUniform3i(array[i].loc, + (array[i].param[0]), (array[i].param[1]), (array[i].param[2]) ); + break; + case GL_INT_VEC4: + glUniform4i(array[i].loc, + (array[i].param[0]), (array[i].param[1]), + (array[i].param[2]), (array[i].param[3]) ); + break; + /* bool vectors */ + case GL_BOOL: + glUniform1f( array[i].loc, (array[i].param[0]) ); + break; + case GL_BOOL_VEC2: + glUniform2f( array[i].loc, (array[i].param[0]), (array[i].param[1]) ); + break; + case GL_BOOL_VEC3: + glUniform3f( array[i].loc, + (array[i].param[0]), (array[i].param[1]), + (array[i].param[2]) ); + break; + case GL_BOOL_VEC4: + glUniform4f( array[i].loc, + (array[i].param[0]), (array[i].param[1]), + (array[i].param[2]), (array[i].param[3]) ); + break; + + /* float matrices */ + case GL_FLOAT_MAT2: + // GL_TRUE = row major order, GL_FALSE = column major + glUniformMatrix2fv( array[i].loc, 1, GL_FALSE, array[i].param ); + break; + case GL_FLOAT_MAT3: + glUniformMatrix3fv( array[i].loc, 1, GL_FALSE, array[i].param ); + break; + case GL_FLOAT_MAT4: + glUniformMatrix4fv( array[i].loc, 1, GL_FALSE, array[i].param ); + break; + + /* textures */ + case GL_SAMPLER_2D: + glUniform1i(array[i].loc, array[i].param[0]); + break; + case GL_SAMPLER_CUBE: break; + glUniform1i(array[i].loc, (array[i].param[0])); + break; + default: + ; + } + // remove flag because the value is in GL's state now... + array[i].flag=0; + + } + } + return 0; +} + +static int shader_redraw(RASPITEX_STATE *state) +{ + // Start with a clear screen + //~ static float offset = 0.0; + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Bind the OES texture which is used to render the camera preview + glBindTexture(GL_TEXTURE_EXTERNAL_OES, state->texture); + + //~ offset += 0.05; + GLCHK(glUseProgram(shader.program)); + GLCHK(glEnableVertexAttribArray(shader.attribute_locations[0])); + GLfloat varray[] = { + -1.0f, -1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f, + + -1.0f, 1.0f, + 1.0f, 1.0f, + -1.0f, -1.0f, + }; + GLCHK(glVertexAttribPointer(shader.attribute_locations[0], 2, GL_FLOAT, GL_FALSE, 0, varray)); + + shader_update_shader(state); + + //GLCHK(glUniform1f(shader.uniform_locations[1], offset)); + GLCHK(glDrawArrays(GL_TRIANGLES, 0, 6)); + + GLCHK(glDisableVertexAttribArray(shader.attribute_locations[0])); + GLCHK(glUseProgram(0)); + return 0; +} + +int shader_open(RASPITEX_STATE *state) +{ + const GLchar *defaultVertexShader = + "attribute vec2 vertex;\n" + "varying vec2 texcoord;" + "void main(void) {\n" + " texcoord = 0.5 * (vertex + 1.0);\n" + " gl_Position = vec4(vertex, 0.0, 1.0);\n" + "}\n"; + + const GLchar *defaultFragmentShader = + "#extension GL_OES_EGL_image_external : require\n" + "varying vec2 texcoord;" + "uniform samplerExternalOES tex;" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D(tex, texcoord); \n" + "} \n"; + + FILE * pfFile=NULL; + FILE * pvFile=NULL; + long lSize; + int result; + + pfFile = fopen (state->fragment_shader_filename,"rb"); + if (pfFile==NULL) { + fprintf(stderr,"No or invalid fragment file provided, used the default one\n"); + shader.fragment_source=defaultFragmentShader; + } else { + + // obtain file size: + fseek (pfFile , 0 , SEEK_END); + lSize = ftell (pfFile); + rewind (pfFile); + + // allocate memory to contain the whole file: + shader.fragment_source = (GLchar*) malloc (sizeof(GLchar)*lSize); + + // copy the file into the buffer: + result = fread (shader.fragment_source,1,lSize,pfFile); + if (result != lSize) { + fputs ("Reading error",stderr); + return -1; + } + + printf("fragment shader file : %s\n", state->fragment_shader_filename); + + /* the whole file is now loaded in the memory buffer. */ + } + + pvFile = fopen (state->vertex_shader_filename,"rb"); + if (pvFile==NULL) { + fprintf(stderr, "No or invalid vertex file provided, used the default one\n"); + shader.vertex_source=defaultVertexShader; + } else { + + // obtain file size: + fseek (pvFile , 0 , SEEK_END); + lSize = ftell (pvFile); + rewind (pvFile); + + // allocate memory to contain the whole file: + shader.vertex_source = (GLchar*) malloc (sizeof(GLchar)*lSize); + + // copy the file into the buffer: + result = fread (shader.vertex_source,1,lSize,pvFile); + if (result != lSize) { + fputs ("Reading error",stderr); + return -1; + } + + printf("vertex shader file : %s\n", state->vertex_shader_filename); + + /* the whole file is now loaded in the memory buffer. */ + } + + state->ops.gl_init = shader_init; + state->ops.redraw = shader_redraw; + state->ops.update_texture = raspitexutil_update_texture; + return 0; +} + +RASPITEXUTIL_SHADER_PROGRAM_T* shader_get_shader() +{ + return &shader; +} diff --git a/host_applications/linux/apps/raspicam/gl_scenes/shader.h b/host_applications/linux/apps/raspicam/gl_scenes/shader.h new file mode 100644 index 000000000..7f9c90312 --- /dev/null +++ b/host_applications/linux/apps/raspicam/gl_scenes/shader.h @@ -0,0 +1,41 @@ +/* +Copyright (c) 2013, Broadcom Europe Ltd +Copyright (c) 2013, Tim Gover +Copyright (c) 2015, Antoine Villeret + +All rights reserved. + + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef SHADER_H +#define SHADER_H + +#include "RaspiTex.h" +#include "RaspiTexUtil.h" + +int shader_open(RASPITEX_STATE *state); +RASPITEXUTIL_SHADER_PROGRAM_T* shader_get_shader(); + +#endif /* SHADER_H */ diff --git a/makefiles/cmake/Modules/Findliblo.cmake b/makefiles/cmake/Modules/Findliblo.cmake new file mode 100644 index 000000000..36082e435 --- /dev/null +++ b/makefiles/cmake/Modules/Findliblo.cmake @@ -0,0 +1,68 @@ +# - Try to find liblo +# Once done this will define +# +# LIBLO_FOUND - system has liblo +# LIBLO_INCLUDE_DIRS - the liblo include directory +# LIBLO_LIBRARIES - Link these to use liblo +# LIBLO_DEFINITIONS - Compiler switches required for using liblo +# +# Adapted from cmake-modules Google Code project +# +# Copyright (c) 2006 Andreas Schneider +# +# (Changes for liblo) Copyright (c) 2008 Kyle Machulis +# +# Redistribution and use is allowed according to the terms of the New BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +if (LIBLO_LIBRARIES AND LIBLO_INCLUDE_DIRS) + # in cache already + set(LIBLO_FOUND TRUE) +else (LIBLO_LIBRARIES AND LIBLO_INCLUDE_DIRS) + find_path(LIBLO_INCLUDE_DIR + NAMES + lo/lo.h + PATHS + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ) + + find_library(LIBLO_LIBRARY + NAMES + lo + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ) + + set(LIBLO_INCLUDE_DIRS + ${LIBLO_INCLUDE_DIR} + ) + set(LIBLO_LIBRARIES + ${LIBLO_LIBRARY} +) + + if (LIBLO_INCLUDE_DIRS AND LIBLO_LIBRARIES) + set(LIBLO_FOUND TRUE) + endif (LIBLO_INCLUDE_DIRS AND LIBLO_LIBRARIES) + + if (LIBLO_FOUND) + if (NOT liblo_FIND_QUIETLY) + message(STATUS "Found liblo: ${LIBLO_LIBRARIES}") + endif (NOT liblo_FIND_QUIETLY) + else (LIBLO_FOUND) + if (liblo_FIND_REQUIRED) + message(FATAL_ERROR "Could not find liblo") + endif (liblo_FIND_REQUIRED) + endif (LIBLO_FOUND) + + # show the LIBLO_INCLUDE_DIRS and LIBLO_LIBRARIES variables only in the advanced view + mark_as_advanced(LIBLO_INCLUDE_DIRS LIBLO_LIBRARIES) + +endif (LIBLO_LIBRARIES AND LIBLO_INCLUDE_DIRS)