diff --git a/dxt_compress/dxt_common.h b/dxt_compress/dxt_common.h index 39bbe0d12..0f6759a3e 100644 --- a/dxt_compress/dxt_common.h +++ b/dxt_compress/dxt_common.h @@ -71,7 +71,8 @@ */ enum dxt_format { DXT_FORMAT_RGB = 0, - DXT_FORMAT_YUV = 1 + DXT_FORMAT_YUV = 1, + DXT_FORMAT_YUV422 = 2 }; /** @@ -150,4 +151,4 @@ dxt_image_destroy(DXT_IMAGE_TYPE* image); int dxt_image_compressed_destroy(unsigned char* image_compressed); -#endif // DXT_COMMON_H \ No newline at end of file +#endif // DXT_COMMON_H diff --git a/dxt_compress/dxt_encoder.c b/dxt_compress/dxt_encoder.c index 5be87554f..f0313fd7d 100644 --- a/dxt_compress/dxt_encoder.c +++ b/dxt_compress/dxt_encoder.c @@ -51,15 +51,60 @@ struct dxt_encoder // Compressed texture GLuint texture_compressed_id; + GLuint texture_yuv422; + // Framebuffer GLuint fbo_id; // Program and shader handles GLhandleARB program_compress; GLhandleARB shader_fragment_compress; - GLhandleARB shader_vertex_compress; + GLhandleARB shader_vertex_compress; + + GLhandleARB yuv422_to_444_program; + GLhandleARB yuv422_to_444_fp; + GLuint fbo444_id; }; +int dxt_prepare_yuv422_shader(struct dxt_encoder *encoder); + +int dxt_prepare_yuv422_shader(struct dxt_encoder *encoder) { + encoder->yuv422_to_444_fp = 0; + encoder->yuv422_to_444_fp = dxt_shader_create_from_source(fp_yuv422_to_yuv_444, GL_FRAGMENT_SHADER_ARB); + if ( encoder->yuv422_to_444_fp == 0) { + printf("Failed to compile YUV422->YUV444 fragment program!\n"); + return 0; + } + + encoder->yuv422_to_444_program = glCreateProgramObjectARB(); + glAttachObjectARB(encoder->yuv422_to_444_program, encoder->shader_vertex_compress); + glAttachObjectARB(encoder->yuv422_to_444_program, encoder->yuv422_to_444_fp); + glLinkProgramARB(encoder->yuv422_to_444_program); + + char log[32768]; + glGetInfoLogARB(encoder->yuv422_to_444_program, 32768, NULL, (GLchar*)log); + if ( strlen(log) > 0 ) + printf("Link Log: %s\n", log); + + glGenTextures(1, &encoder->texture_yuv422); + glBindTexture(GL_TEXTURE_2D, encoder->texture_yuv422); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, encoder->width / 2, encoder->height, + 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + + glUseProgramObjectARB(encoder->yuv422_to_444_program); + glUniform1i(glGetUniformLocation(encoder->yuv422_to_444_program, "image"), 0); + glUniform2f(glGetUniformLocation(encoder->yuv422_to_444_program, "imageSize"), encoder->width, encoder->height); + + // Create fbo + glGenFramebuffersEXT(1, &encoder->fbo444_id); + return 1; +} + + /** Documented at declaration */ struct dxt_encoder* dxt_encoder_create(enum dxt_type type, int width, int height, enum dxt_format format) @@ -73,7 +118,7 @@ dxt_encoder_create(enum dxt_type type, int width, int height, enum dxt_format fo encoder->format = format; // Create empty data - GLubyte * data = NULL; + /*GLubyte * data = NULL; int data_size = 0; dxt_encoder_buffer_allocate(encoder, &data, &data_size); // Create empty compressed texture @@ -88,7 +133,7 @@ dxt_encoder_create(enum dxt_type type, int width, int height, enum dxt_format fo else glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, encoder->width, encoder->height, 0, data_size, data); // Free empty data - dxt_encoder_buffer_free(data); + dxt_encoder_buffer_free(data);*/ // Create fbo glGenFramebuffersEXT(1, &encoder->fbo_id); @@ -134,29 +179,43 @@ dxt_encoder_create(enum dxt_type type, int width, int height, enum dxt_format fo glGetInfoLogARB(encoder->program_compress, 32768, NULL, (GLchar*)log); if ( strlen(log) > 0 ) printf("Link Log: %s\n", log); - + + glGenTextures(1, &encoder->texture_id); glBindTexture(GL_TEXTURE_2D, encoder->texture_id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, DXT_IMAGE_GL_FORMAT, encoder->width, encoder->height, 0, GL_RGBA, DXT_IMAGE_GL_TYPE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, DXT_IMAGE_GL_FORMAT, encoder->width, encoder->height, 0, GL_RGBA, GL_BYTE, NULL); - glViewport(0, 0, encoder->width / 4, encoder->height / 4); - glDisable(GL_DEPTH_TEST); - + //glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); + + if(format == DXT_FORMAT_YUV422) { + if(!dxt_prepare_yuv422_shader(encoder)) + return NULL; + } + glBindTexture(GL_TEXTURE_2D, encoder->texture_id); glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, encoder->width / 4, encoder->height / 4); + glDisable(GL_DEPTH_TEST); + // User compress program and set image size parameters glUseProgramObjectARB(encoder->program_compress); - glUniform1i(glGetUniformLocation(encoder->program_compress, "imageFormat"), encoder->format); + glUniform1i(glGetUniformLocation(encoder->program_compress, "image"), 0); + if(format == DXT_FORMAT_YUV422) { + glUniform1i(glGetUniformLocation(encoder->program_compress, "imageFormat"), DXT_FORMAT_YUV); + } else { + glUniform1i(glGetUniformLocation(encoder->program_compress, "imageFormat"), encoder->format); + } glUniform2f(glGetUniformLocation(encoder->program_compress, "imageSize"), encoder->width, encoder->height); // Render to framebuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, encoder->fbo_id); - + return encoder; } @@ -187,9 +246,41 @@ int dxt_encoder_compress(struct dxt_encoder* encoder, DXT_IMAGE_TYPE* image, unsigned char* image_compressed) { TIMER_INIT(); - + TIMER_START(); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGBA, DXT_IMAGE_GL_TYPE, image); + if(encoder->format == DXT_FORMAT_YUV422) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, encoder->fbo444_id); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, encoder->texture_id, 0); + //assert(GL_FRAMEBUFFER_COMPLETE_EXT == glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); + glBindTexture(GL_TEXTURE_2D, encoder->texture_yuv422); + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport( 0, 0, encoder->width, encoder->height); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width / 2, encoder->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, image); + glUseProgramObjectARB(encoder->yuv422_to_444_program); + + //glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0); + glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0); + glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0); + glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0); + glEnd(); + + glPopAttrib(); + + //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + glUseProgramObjectARB(encoder->program_compress); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, encoder->fbo_id); + glBindTexture(GL_TEXTURE_2D, encoder->texture_id); + + //gl_check_error(); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGBA, DXT_IMAGE_GL_TYPE, image); + } #ifdef DEBUG glFinish(); #endif diff --git a/dxt_compress/yuv422_to_yuv444.glsl b/dxt_compress/yuv422_to_yuv444.glsl new file mode 100644 index 000000000..6eb3c0a2f --- /dev/null +++ b/dxt_compress/yuv422_to_yuv444.glsl @@ -0,0 +1,17 @@ +#version 130 + +#extension GL_EXT_gpu_shader4 : enable + +#define lerp mix + +in vec4 TEX0; +uniform sampler2D image; +uniform vec2 imageSize; +out vec4 color; + +void main() +{ + color.rgba = texture(image, TEX0.xy).grba; // store Y0UVY1 ro rgba + if(TEX0.x * imageSize.x / 2 - floor(TEX0.x * imageSize.x / 2) > 0.25) + color.r = color.a; // use Y1 instead of Y0 +} diff --git a/ultragrid/Makefile.in b/ultragrid/Makefile.in index db2431ef8..4db108669 100644 --- a/ultragrid/Makefile.in +++ b/ultragrid/Makefile.in @@ -107,7 +107,8 @@ src/video_display/sage_wrapper.o: src/video_display/sage_wrapper.cxx ../dxt_compress/dxt_glsl.h:../dxt_compress/compress_vp.glsl \ ../dxt_compress/compress_dxt1_fp.glsl ../dxt_compress/compress_dxt5ycocg_fp.glsl \ - ../dxt_compress/display_fp.glsl ../dxt_compress/display_dxt5ycocg_fp.glsl + ../dxt_compress/display_fp.glsl ../dxt_compress/display_dxt5ycocg_fp.glsl \ + ../dxt_compress/yuv422_to_yuv444.glsl echo "/**" > $@ echo " * GLSL source codes for DXT compressions" >> $@ echo " *" >> $@ @@ -133,6 +134,10 @@ src/video_display/sage_wrapper.o: src/video_display/sage_wrapper.cxx echo "static const char fp_display_dxt5ycocg[] = " >> $@ cat ../dxt_compress/display_dxt5ycocg_fp.glsl | sed 's/\(.*\)/ \"\1\\n\"/' >> $@ echo ";" >> $@ + # yuv 422 to yuv 444 shader + echo "static const char fp_yuv422_to_yuv_444[] = " >> $@ + cat ../dxt_compress/yuv422_to_yuv444.glsl | sed 's/\(.*\)/ \"\1\\n\"/' >> $@ + echo ";" >> $@ # ------------------------------------------------------------------------------------------------- diff --git a/ultragrid/configure.ac b/ultragrid/configure.ac index f1fe0d000..1896c45c8 100644 --- a/ultragrid/configure.ac +++ b/ultragrid/configure.ac @@ -203,6 +203,7 @@ if test ! $no_x ; then fi fi X_LIBS+=" -lX11" + X_OBJ="src/x11_common.o" CFLAGS+="" HAVE_X11=yes fi @@ -688,7 +689,7 @@ AC_CHECK_HEADER(GL/glx.h, FOUND_GLX_H=yes) AC_CHECK_LIB(GL, glXCreateNewContext, FOUND_GLX_L=yes) if test "$HAVE_X11" = yes -a "$FOUND_GLEW_L" = yes -a "$FOUND_GLEW_H" = yes -a "$FOUND_GLX_L" = yes -a "$FOUND_GLX_H" = yes \ - -a ! expr "$host_os" : ".*darwin.*" > /dev/null # not mac, just for now + -a `expr "$host_os" : ".*darwin.*"` -eq 0 # not mac, just for now then LIBS+=" -lGLEW -lGL -lX11" AC_DEFINE([HAVE_DXT_GLSL], [1], [Build with DXT_GLSL support]) diff --git a/ultragrid/src/dxt_glsl_compress.c b/ultragrid/src/dxt_glsl_compress.c index e9a3a31d8..ce7cf0ef5 100644 --- a/ultragrid/src/dxt_glsl_compress.c +++ b/ultragrid/src/dxt_glsl_compress.c @@ -54,8 +54,10 @@ #include #include #include +#include #include #include +#include "x11_common.h" /* * GLX context creation overtaken from: @@ -66,8 +68,9 @@ struct video_compress { struct dxt_encoder *encoder; struct video_frame out; - char *decoded, *repacked; + char *decoded; unsigned int configured:1; + unsigned int interlaced_input:1; }; static void configure_with(struct video_compress *s, struct video_frame *frame); @@ -338,6 +341,8 @@ static void configure_with(struct video_compress *s, struct video_frame *frame) codec_t tmp = s->out.color_spec; enum dxt_format format; + assert(frame->width % 4 == 0 && frame->height % 4 == 0); + glx_init(); memcpy(&s->out, frame, sizeof(struct video_frame)); @@ -358,19 +363,23 @@ static void configure_with(struct video_compress *s, struct video_frame *frame) case Vuy2: case DVS8: s->out.decoder = (decoder_t) memcpy; - format = DXT_FORMAT_YUV; + format = DXT_FORMAT_YUV422; break; case v210: s->out.decoder = (decoder_t) vc_copylinev210; - format = DXT_FORMAT_YUV; + format = DXT_FORMAT_YUV422; break; case DVS10: s->out.decoder = (decoder_t) vc_copylineDVS10; - format = DXT_FORMAT_YUV; + format = DXT_FORMAT_YUV422; break; - /*case DXT1: + case DXT1: + case DXT5: fprintf(stderr, "Input frame is already comperssed!"); - exit(128);*/ + exit(128); + default: + fprintf(stderr, "Unknown codec: %d\n", s->out.color_spec); + exit(128); } s->out.src_bpp = get_bpp(s->out.color_spec); s->out.src_linesize = s->out.width * s->out.src_bpp; @@ -378,11 +387,14 @@ static void configure_with(struct video_compress *s, struct video_frame *frame) (format == DXT_FORMAT_RGB ? 4 /*RGBA*/: 2/*YUV 422*/); /* We will deinterlace the output frame */ + if(s->out.aux & AUX_INTERLACED) + s->interlaced_input = TRUE; + else + s->interlaced_input = FALSE; s->out.aux &= ~AUX_INTERLACED; s->out.color_spec = tmp; - if(s->out.color_spec == DXT1) { s->encoder = dxt_encoder_create(DXT_TYPE_DXT1, frame->width, frame->height, format); s->out.aux |= AUX_RGB; @@ -393,9 +405,13 @@ static void configure_with(struct video_compress *s, struct video_frame *frame) s->out.data_len = frame->width * frame->height; } + if(!s->encoder) { + fprintf(stderr, "[DXT GLSL] Failed to create encoder.\n"); + exit(128); + } + s->out.data = (char *) malloc(s->out.data_len); s->decoded = malloc(4 * frame->width * frame->height); - s->repacked = malloc(4 * frame->width * frame->height); s->configured = TRUE; } @@ -407,7 +423,17 @@ struct video_compress * dxt_glsl_init(char * opts) s = (struct video_compress *) malloc(sizeof(struct video_compress)); s->out.data = NULL; s->decoded = NULL; - s->repacked = NULL; + + x11_enter_thread(); + + if(opts && strcmp(opts, "help") == 0) { + printf("DXT GLSL comperssion usage:\n"); + printf("\t-cg:DXT1\n"); + printf("\t\tcompress with DXT1\n"); + printf("\t-cg:DXT5_YCoCg\n"); + printf("\t\tcompress with DXT5_YCoCg\n"); + return NULL; + } if(opts) { if(strcasecmp(opts, "DXT5_YCoCg") == 0) { @@ -437,35 +463,22 @@ struct video_frame * dxt_glsl_compress(void *arg, struct video_frame * tx) configure_with(s, tx); - line1 = (unsigned char *)tx->data; - line2 = s->decoded; + line1 = (unsigned char *) tx->data; + line2 = (unsigned char *) s->decoded; - for (x = 0; x < tx->height; ++x) { + for (x = 0; x < (int) tx->height; ++x) { s->out.decoder(line2, line1, s->out.src_linesize, s->out.rshift, s->out.gshift, s->out.bshift); line1 += s->out.src_linesize; line2 += s->out.dst_linesize; } - if(tx->color_spec == RGBA || - tx->color_spec == R10k) { - dxt_encoder_compress(s->encoder, s->decoded, s->out.data); - } else { - const count = s->out.width * s->out.height; - /* Repack the data to YUV 4:4:4 Format */ - for (x = 0; x < count; x += 2) { - s->repacked[4 * x] = s->decoded[2 * x + 1]; //Y1 - s->repacked[4 * x + 1] = s->decoded[2 * x]; //U1 - s->repacked[4 * x + 2] = s->decoded[2 * x + 2]; //V1 - //s->repacked[4 * x + 3] = 255; //Alpha + if(s->interlaced_input) + vc_deinterlace((unsigned char *) s->decoded, s->out.dst_linesize, tx->height); - s->repacked[4 * x + 4] = s->decoded[2 * x + 3]; //Y2 - s->repacked[4 * x + 5] = s->decoded[2 * x]; //U1 - s->repacked[4 * x + 6] = s->decoded[2 * x + 2]; //V1 - //s->repacked[4 * x + 7] = 255; //Alpha - } - dxt_encoder_compress(s->encoder, s->repacked, s->out.data); - } + dxt_encoder_compress(s->encoder, + (unsigned char *) s->decoded, + (unsigned char *) s->out.data); return &s->out; } diff --git a/ultragrid/src/main.c b/ultragrid/src/main.c index e3041d1f4..f8e5460a5 100644 --- a/ultragrid/src/main.c +++ b/ultragrid/src/main.c @@ -164,6 +164,8 @@ static void usage(void) printf("\n"); printf("\t-c \tcompress video\n"); printf("\n"); + printf("\t-cg \tcompress video with OpenGL (see -cg:help for more options)\n"); + printf("\n"); printf("\t-i \tiHDTV compatibility mode\n"); printf("\n"); printf("\taddress(es) \tdestination address\n"); diff --git a/ultragrid/src/video_display/gl.c b/ultragrid/src/video_display/gl.c index 3fca89591..8f47d8acf 100644 --- a/ultragrid/src/video_display/gl.c +++ b/ultragrid/src/video_display/gl.c @@ -60,7 +60,7 @@ #include #include #include - +#include "x11_common.h" #ifdef FREEGLUT #include #endif /* FREEGLUT */ @@ -219,6 +219,10 @@ void gl_check_error() void * display_gl_init(char *fmt, unsigned int flags) { UNUSED(flags); struct state_gl *s; + +#ifndef HAVE_MACOSX + x11_enter_thread(); +#endif glutInit(&uv_argc, uv_argv); s = (struct state_gl *) calloc(1,sizeof(struct state_gl)); diff --git a/ultragrid/src/video_display/sdl.c b/ultragrid/src/video_display/sdl.c index b32b7a9c2..27fadd72d 100644 --- a/ultragrid/src/video_display/sdl.c +++ b/ultragrid/src/video_display/sdl.c @@ -64,6 +64,7 @@ void NSApplicationLoad(); #else /* HAVE_MACOSX */ #include +#include "x11_common.h" #endif /* HAVE_MACOSX */ #include @@ -611,6 +612,10 @@ void *display_sdl_init(char *fmt, unsigned int flags) s = (struct state_sdl *)calloc(1, sizeof(struct state_sdl)); s->magic = MAGIC_SDL; +#ifndef HAVE_MACOSX + x11_enter_thread(); +#endif + if (fmt != NULL) { if (strcmp(fmt, "help") == 0) { show_help(); diff --git a/ultragrid/src/x11_common.c b/ultragrid/src/x11_common.c new file mode 100644 index 000000000..56340a1fe --- /dev/null +++ b/ultragrid/src/x11_common.c @@ -0,0 +1,58 @@ +/* + * FILE: x11_common.c + * AUTHORS: Martin Benes + * Lukas Hejtmanek + * Petr Holub + * Milos Liska + * Jiri Matela + * Dalibor Matura <255899@mail.muni.cz> + * Ian Wesley-Smith + * + * Copyright (c) 2005-2010 CESNET z.s.p.o. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the CESNET 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 AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED 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 AUTHORS 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 "config.h" +#include +#include +#include + +static pthread_once_t XInitThreadsHasRun = PTHREAD_ONCE_INIT; + + void x11_enter_thread(void) + { + pthread_once(&XInitThreadsHasRun, XInitThreads); + } diff --git a/ultragrid/src/x11_common.h b/ultragrid/src/x11_common.h new file mode 100644 index 000000000..c0c7b8539 --- /dev/null +++ b/ultragrid/src/x11_common.h @@ -0,0 +1,48 @@ +/* + * FILE: x11_common.h + * AUTHORS: Martin Benes + * Lukas Hejtmanek + * Petr Holub + * Milos Liska + * Jiri Matela + * Dalibor Matura <255899@mail.muni.cz> + * Ian Wesley-Smith + * + * Copyright (c) 2005-2010 CESNET z.s.p.o. + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the CESNET 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 AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED 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 AUTHORS 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. + * + */ + +void x11_enter_thread(void);