56 #include <EGL/eglext.h>
58 #include <GLES2/gl2.h>
59 #include <GLES2/gl2ext.h>
61 #include <xkbcommon/xkbcommon.h>
63 #include "wayland-client.h"
64 #include "wayland-egl.h"
65 #include "simpleshell-client-protocol.h"
67 #define UNUSED(x) ((void)x)
69 #if !defined (XKB_KEYMAP_COMPILE_NO_FLAGS)
70 #define XKB_KEYMAP_COMPILE_NO_FLAGS XKB_MAP_COMPILE_NO_FLAGS
73 static void registryHandleGlobal(
void *data,
74 struct wl_registry *registry, uint32_t
id,
75 const char *interface, uint32_t version);
76 static void registryHandleGlobalRemove(
void *data,
77 struct wl_registry *registry,
80 static const struct wl_registry_listener registryListener =
83 registryHandleGlobalRemove
86 static void shellSurfaceId(
void *data,
87 struct wl_simple_shell *wl_simple_shell,
88 struct wl_surface *surface,
90 static void shellSurfaceCreated(
void *data,
91 struct wl_simple_shell *wl_simple_shell,
94 static void shellSurfaceDestroyed(
void *data,
95 struct wl_simple_shell *wl_simple_shell,
98 static void shellSurfaceStatus(
void *data,
99 struct wl_simple_shell *wl_simple_shell,
109 static void shellGetSurfacesDone(
void *data,
110 struct wl_simple_shell *wl_simple_shell);
112 static const struct wl_simple_shell_listener shellListener =
116 shellSurfaceDestroyed,
121 typedef enum _InputState
124 InputState_attribute,
127 typedef enum _Attribute
131 Attribute_visibility,
138 struct wl_display *display;
139 struct wl_registry *registry;
141 struct wl_compositor *compositor;
142 struct wl_simple_shell *shell;
143 struct wl_seat *seat;
144 struct wl_keyboard *keyboard;
145 struct wl_pointer *pointer;
146 struct wl_touch *touch;
147 struct wl_surface *surface;
148 struct wl_output *output;
149 struct wl_egl_window *native;
150 struct wl_callback *frameCallback;
152 struct xkb_context *xkbCtx;
153 struct xkb_keymap *xkbKeymap;
154 struct xkb_state *xkbState;
155 xkb_mod_index_t modAlt;
156 xkb_mod_index_t modCtrl;
158 EGLDisplay eglDisplay;
160 EGLSurface eglSurfaceWindow;
161 EGLContext eglContext;
162 EGLImageKHR eglImage;
163 EGLNativePixmapType eglPixmap;
166 InputState inputState;
174 uint32_t surfaceIdOther;
175 uint32_t surfaceIdCurrent;
176 float surfaceOpacity;
191 GLuint rotation_uniform;
200 int pointerX, pointerY;
204 static void processInput(
AppCtx *ctx, uint32_t sym );
205 static void drawFrame(
AppCtx *ctx );
206 static bool setupEGL(
AppCtx *ctx );
207 static void termEGL(
AppCtx *ctx );
208 static bool createSurface(
AppCtx *ctx );
209 static void resizeSurface(
AppCtx *ctx,
int dx,
int dy,
int width,
int height );
210 static void destroySurface(
AppCtx *ctx );
211 static bool setupGL(
AppCtx *ctx );
212 static bool renderGL(
AppCtx *ctx );
217 static void signalHandler(
int signum)
219 printf(
"signalHandler: signum %d\n", signum);
223 static long long currentTimeMillis()
225 long long timeMillis;
228 gettimeofday(&tv, NULL);
229 timeMillis = tv.tv_sec * 1000 + tv.tv_usec / 1000;
234 static void shmFormat(
void *data,
struct wl_shm *wl_shm, uint32_t format)
238 printf(
"shm format: %X\n", format);
241 struct wl_shm_listener shmListener = {
245 static void keyboardKeymap(
void *data,
struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size )
249 if ( format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 )
251 void *map= mmap( 0, size, PROT_READ, MAP_SHARED, fd, 0 );
252 if ( map != MAP_FAILED )
256 ctx->xkbCtx= xkb_context_new( XKB_CONTEXT_NO_FLAGS );
260 printf(
"error: xkb_context_new failed\n");
264 if ( ctx->xkbKeymap )
266 xkb_keymap_unref( ctx->xkbKeymap );
269 ctx->xkbKeymap= xkb_keymap_new_from_string( ctx->xkbCtx, (
char*)map, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
270 if ( !ctx->xkbKeymap )
272 printf(
"error: xkb_keymap_new_from_string failed\n");
276 xkb_state_unref( ctx->xkbState );
279 ctx->xkbState= xkb_state_new( ctx->xkbKeymap );
280 if ( !ctx->xkbState )
282 printf(
"error: xkb_state_new failed\n");
284 if ( ctx->xkbKeymap )
286 ctx->modAlt= xkb_keymap_mod_get_index( ctx->xkbKeymap, XKB_MOD_NAME_ALT );
287 ctx->modCtrl= xkb_keymap_mod_get_index( ctx->xkbKeymap, XKB_MOD_NAME_CTRL );
297 static void keyboardEnter(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
298 struct wl_surface *surface,
struct wl_array *keys )
305 printf(
"keyboard enter surface %p\n", surface );
308 static void keyboardLeave(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
struct wl_surface *surface )
314 printf(
"keyboard leave surface %p\n", surface );
317 static void keyboardKey(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
318 uint32_t time, uint32_t key, uint32_t state )
323 xkb_keycode_t keyCode;
331 sym= xkb_state_key_get_one_sym( ctx->xkbState, keyCode );
333 if ( ctx->verboseLog )
338 if ( xkb_state_mod_index_is_active( ctx->xkbState, ctx->modCtrl, XKB_STATE_MODS_DEPRESSED) == 1 )
343 if ( xkb_state_mod_index_is_active( ctx->xkbState, ctx->modAlt, XKB_STATE_MODS_DEPRESSED) == 1 )
348 printf(
"keyboardKey: sym %X state %s ctrl %d alt %d time %u\n",
349 sym, (state == WL_KEYBOARD_KEY_STATE_PRESSED ?
"Down" :
"Up"), ctrl, alt, time);
352 if ( state == WL_KEYBOARD_KEY_STATE_PRESSED )
354 processInput( ctx, sym );
359 static void keyboardModifiers(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
360 uint32_t mods_depressed, uint32_t mods_latched,
361 uint32_t mods_locked, uint32_t group )
366 xkb_state_update_mask( ctx->xkbState, mods_depressed, mods_latched, mods_locked, 0, 0, group );
370 static void keyboardRepeatInfo(
void *data,
struct wl_keyboard *keyboard, int32_t rate, int32_t delay )
378 static const struct wl_keyboard_listener keyboardListener= {
387 static void pointerEnter(
void* data,
struct wl_pointer *pointer, uint32_t serial,
388 struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy )
395 x= wl_fixed_to_int( sx );
396 y= wl_fixed_to_int( sy );
401 printf(
"pointer enter surface %p (%d,%d)\n", surface, x, y );
404 static void pointerLeave(
void* data,
struct wl_pointer *pointer, uint32_t serial,
struct wl_surface *surface )
410 printf(
"pointer leave surface %p\n", surface );
413 static void pointerMotion(
void *data,
struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy )
419 x= wl_fixed_to_int( sx );
420 y= wl_fixed_to_int( sy );
425 if ( ctx->verboseLog )
427 printf(
"pointer motion surface (%d,%d) time %u\n", x, y, time );
431 static void pointerButton(
void *data,
struct wl_pointer *pointer, uint32_t serial,
432 uint32_t time, uint32_t button, uint32_t state )
438 printf(
"pointer button %u state %u (%d, %d)\n", button, state, ctx->pointerX, ctx->pointerY);
439 ctx->verboseLog= (state == WL_POINTER_BUTTON_STATE_PRESSED);
442 static void pointerAxis(
void *data,
struct wl_pointer *pointer, uint32_t time,
443 uint32_t axis, wl_fixed_t value )
450 v= wl_fixed_to_int( value );
451 printf(
"pointer axis %u value %d\n", axis, v);
454 static const struct wl_pointer_listener pointerListener = {
462 static void seatCapabilities(
void *data,
struct wl_seat *seat, uint32_t capabilities )
466 printf(
"seat %p caps: %X\n", seat, capabilities );
468 if ( capabilities & WL_SEAT_CAPABILITY_KEYBOARD )
470 printf(
" seat has keyboard\n");
471 ctx->keyboard= wl_seat_get_keyboard( ctx->seat );
472 printf(
" keyboard %p\n", ctx->keyboard );
473 wl_keyboard_add_listener( ctx->keyboard, &keyboardListener, ctx );
475 if ( capabilities & WL_SEAT_CAPABILITY_POINTER )
477 printf(
" seat has pointer\n");
478 ctx->pointer= wl_seat_get_pointer( ctx->seat );
479 printf(
" pointer %p\n", ctx->pointer );
480 wl_pointer_add_listener( ctx->pointer, &pointerListener, ctx );
482 if ( capabilities & WL_SEAT_CAPABILITY_TOUCH )
484 printf(
" seat has touch\n");
485 ctx->touch= wl_seat_get_touch( ctx->seat );
486 printf(
" touch %p\n", ctx->touch );
490 static void seatName(
void *data,
struct wl_seat *seat,
const char *name )
493 printf(
"seat %p name: %s\n", seat, name);
496 static const struct wl_seat_listener seatListener = {
501 static void outputGeometry(
void *data,
struct wl_output *output, int32_t x, int32_t y,
502 int32_t physical_width, int32_t physical_height, int32_t subpixel,
503 const char *make,
const char *model, int32_t transform )
509 UNUSED(physical_width);
510 UNUSED(physical_height);
517 static void outputMode(
void *data,
struct wl_output *output, uint32_t flags,
518 int32_t width, int32_t height, int32_t refresh )
522 if ( flags & WL_OUTPUT_MODE_CURRENT )
524 if ( (width != ctx->planeWidth) || (height != ctx->planeHeight) )
526 ctx->planeWidth= width;
527 ctx->planeHeight= height;
528 if ( ctx->verboseLog )
530 printf(
"outputMode: resize egl window to (%d,%d)\n", ctx->planeWidth, ctx->planeHeight );
532 resizeSurface( ctx, 0, 0, ctx->planeWidth, ctx->planeHeight);
537 static void outputDone(
void *data,
struct wl_output *output )
543 static void outputScale(
void *data,
struct wl_output *output, int32_t factor )
550 static const struct wl_output_listener outputListener = {
557 static void registryHandleGlobal(
void *data,
558 struct wl_registry *registry, uint32_t
id,
559 const char *interface, uint32_t version)
564 printf(
"rne-triangle: registry: id %d interface (%s) version %d\n",
id, interface, version );
566 len= strlen(interface);
567 if ( (len==6) && !strncmp(interface,
"wl_shm", len)) {
568 ctx->shm= (
struct wl_shm*)wl_registry_bind(registry,
id, &wl_shm_interface, 1);
569 printf(
"shm %p\n", ctx->shm);
570 wl_shm_add_listener(ctx->shm, &shmListener, ctx);
572 else if ( (len==13) && !strncmp(interface,
"wl_compositor", len) ) {
573 ctx->compositor= (
struct wl_compositor*)wl_registry_bind(registry,
id, &wl_compositor_interface, 1);
574 printf(
"compositor %p\n", ctx->compositor);
576 else if ( (len==7) && !strncmp(interface,
"wl_seat", len) ) {
577 ctx->seat= (
struct wl_seat*)wl_registry_bind(registry,
id, &wl_seat_interface, 4);
578 printf(
"seat %p\n", ctx->seat);
579 wl_seat_add_listener(ctx->seat, &seatListener, ctx);
581 else if ( (len==9) && !strncmp(interface,
"wl_output", len) ) {
582 ctx->output= (
struct wl_output*)wl_registry_bind(registry,
id, &wl_output_interface, 2);
583 printf(
"output %p\n", ctx->output);
584 wl_output_add_listener(ctx->output, &outputListener, ctx);
586 else if ( (len==15) && !strncmp(interface,
"wl_simple_shell", len) ) {
587 if ( ctx->getShell ) {
588 ctx->shell= (
struct wl_simple_shell*)wl_registry_bind(registry,
id, &wl_simple_shell_interface, 1);
589 printf(
"shell %p\n", ctx->shell );
590 wl_simple_shell_add_listener(ctx->shell, &shellListener, ctx);
595 static void registryHandleGlobalRemove(
void *data,
596 struct wl_registry *registry,
601 static void shellSurfaceId(
void *data,
602 struct wl_simple_shell *wl_simple_shell,
603 struct wl_surface *surface,
609 sprintf( name,
"rne-triangle-surface-%x", surfaceId );
610 printf(
"shell: surface created: %p id %x\n", surface, surfaceId);
611 wl_simple_shell_set_name( ctx->shell, surfaceId, name );
614 static void shellSurfaceCreated(
void *data,
615 struct wl_simple_shell *wl_simple_shell,
621 printf(
"shell: surface created: %x name: %s\n", surfaceId, name);
622 ctx->surfaceIdOther= ctx->surfaceIdCurrent;
623 ctx->surfaceIdCurrent= surfaceId;
624 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
625 printf(
"shell: surfaceCurrent: %x surfaceOther: %x\n", ctx->surfaceIdCurrent, ctx->surfaceIdOther);
628 static void shellSurfaceDestroyed(
void *data,
629 struct wl_simple_shell *wl_simple_shell,
635 printf(
"shell: surface destroyed: %x name: %s\n", surfaceId, name);
637 if ( ctx->surfaceIdCurrent == surfaceId )
639 ctx->surfaceIdCurrent= ctx->surfaceIdOther;
640 ctx->surfaceIdOther= 0;
641 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
643 if ( ctx->surfaceIdOther == surfaceId )
645 ctx->surfaceIdOther= 0;
647 printf(
"shell: surfaceCurrent: %x surfaceOther: %x\n", ctx->surfaceIdCurrent, ctx->surfaceIdOther);
650 static void shellSurfaceStatus(
void *data,
651 struct wl_simple_shell *wl_simple_shell,
664 printf(
"shell: surface: %x name: %s\n", surfaceId, name);
665 printf(
"shell: position (%d,%d,%d,%d) visible %d opacity %f zorder %f\n",
666 x, y, width, height, visible, wl_fixed_to_double(opacity), wl_fixed_to_double(zorder) );
668 ctx->surfaceVisible= visible;
671 ctx->surfaceWidth= width;
672 ctx->surfaceHeight= height;
673 ctx->surfaceOpacity= wl_fixed_to_double(opacity);
674 ctx->surfaceZOrder= wl_fixed_to_double(zorder);
677 static void shellGetSurfacesDone(
void *data,
678 struct wl_simple_shell *wl_simple_shell)
681 printf(
"shell: get all surfaces done\n");
684 #define NON_BLOCKING_ENABLED (0)
685 #define NON_BLOCKING_DISABLED (1)
687 static void setBlockingMode(
int blockingState )
689 struct termios ttystate;
692 mask= (blockingState == NON_BLOCKING_ENABLED) ? ~(ICANON|ECHO) : -1;
693 bits= (blockingState == NON_BLOCKING_ENABLED) ? 0 : (ICANON|ECHO);
697 tcgetattr(STDIN_FILENO, &ttystate);
699 ttystate.c_lflag= ((ttystate.c_lflag & mask) | bits);
701 if (blockingState == NON_BLOCKING_ENABLED)
703 ttystate.c_cc[VMIN]= 1;
706 tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
709 static bool isKeyHit()
720 FD_SET(STDIN_FILENO, &fdset);
721 select(STDIN_FILENO+1, &fdset, NULL, NULL, &tval);
723 keyHit= FD_ISSET(STDIN_FILENO, &fdset);
728 static void adjustAttribute(
AppCtx *ctx, uint32_t sym )
730 switch( ctx->attribute )
732 case Attribute_position:
753 --ctx->surfaceDHeight;
756 ++ctx->surfaceDHeight;
759 ++ctx->surfaceDWidth;
762 --ctx->surfaceDWidth;
766 case Attribute_visibility:
773 ctx->surfaceVisible= !ctx->surfaceVisible;
774 wl_simple_shell_set_visible( ctx->shell, ctx->surfaceIdCurrent, (ctx->surfaceVisible ? 1 : 0) );
778 case Attribute_opacity:
783 ctx->surfaceOpacity += 0.1;
784 if ( ctx->surfaceOpacity > 1.0 )
786 ctx->surfaceOpacity= 1.0;
788 wl_simple_shell_set_opacity( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceOpacity) );
792 ctx->surfaceOpacity -= 0.1;
793 if ( ctx->surfaceOpacity < 0.0 )
795 ctx->surfaceOpacity= 0.0;
797 wl_simple_shell_set_opacity( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceOpacity) );
801 case Attribute_zorder:
806 ctx->surfaceZOrder += 0.1;
807 if ( ctx->surfaceZOrder > 1.0 )
809 ctx->surfaceZOrder= 1.0;
811 wl_simple_shell_set_zorder( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceZOrder) );
815 ctx->surfaceZOrder -= 0.1;
816 if ( ctx->surfaceZOrder < 0.0 )
818 ctx->surfaceZOrder= 0.0;
820 wl_simple_shell_set_zorder( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceZOrder) );
827 static void processInputMain(
AppCtx *ctx, uint32_t sym )
835 if ( ctx->surfaceIdCurrent )
837 adjustAttribute( ctx, sym );
841 ctx->inputState= InputState_attribute;
842 printf(
"attribute: (p) osition, (s) ize, (v) isible, (o) pacity, (z) order (x) back to main\n");
845 if ( ctx->surfaceIdCurrent )
847 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
851 if ( ctx->surfaceIdOther )
853 uint32_t temp= ctx->surfaceIdCurrent;
854 ctx->surfaceIdCurrent= ctx->surfaceIdOther;
855 ctx->surfaceIdOther= temp;
856 printf(
"shell: surfaceCurrent: %x surfaceOther: %x\n", ctx->surfaceIdCurrent, ctx->surfaceIdOther);
857 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
863 printf(
"get all surfaces:\n");
864 wl_simple_shell_get_surfaces( ctx->shell );
868 ctx->planeWidth= (ctx->planeWidth == 1280) ? 640 : 1280;
869 ctx->planeHeight= (ctx->planeHeight == 720) ? 360 : 720;
870 printf(
"resize egl window to (%d,%d)\n", ctx->planeWidth, ctx->planeHeight );
871 resizeSurface( ctx, 0, 0, ctx->planeWidth, ctx->planeHeight);
876 static void processInputAttribute(
AppCtx *ctx, uint32_t sym )
881 ctx->attribute= Attribute_position;
884 ctx->attribute= Attribute_size;
887 ctx->attribute= Attribute_visibility;
890 ctx->attribute= Attribute_opacity;
893 ctx->attribute= Attribute_zorder;
899 ctx->inputState= InputState_main;
902 static void processInput(
AppCtx *ctx, uint32_t sym )
904 switch( ctx->inputState )
906 case InputState_main:
907 processInputMain( ctx, sym );
909 case InputState_attribute:
910 processInputAttribute( ctx, sym );
915 static void showUsage()
918 printf(
" rne_triangle [options]\n" );
919 printf(
"where [options] are:\n" );
920 printf(
" --delay <delay> : render loop delay\n" );
921 printf(
" --shell : use wl_simple_shell protocol\n" );
922 printf(
" --display <name> : wayland display to connect to\n" );
923 printf(
" --noframe : don't pace rendering with frame requests\n" );
924 printf(
" --noanimate : don't use animation\n" );
925 printf(
" -? : show usage\n" );
929 static void redraw(
void *data,
struct wl_callback *callback, uint32_t time )
933 if ( g_log ) printf(
"redraw: time %u\n", time);
934 wl_callback_destroy( callback );
936 ctx->needRedraw=
true;
939 static struct wl_callback_listener frameListener=
944 static void drawFrame(
AppCtx *ctx )
946 if ( ctx->surfaceDX || ctx->surfaceDY || ctx->surfaceDWidth || ctx->surfaceDHeight )
948 ctx->surfaceX += ctx->surfaceDX;
949 ctx->surfaceY += ctx->surfaceDY;
950 ctx->surfaceWidth += ctx->surfaceDWidth;
951 ctx->surfaceHeight += ctx->surfaceDHeight;
953 wl_simple_shell_set_geometry( ctx->shell, ctx->surfaceIdCurrent,
954 ctx->surfaceX, ctx->surfaceY, ctx->surfaceWidth, ctx->surfaceHeight );
959 ctx->frameCallback= wl_surface_frame( ctx->surface );
960 wl_callback_add_listener( ctx->frameCallback, &frameListener, ctx );
962 eglSwapBuffers(ctx->eglDisplay, ctx->eglSurfaceWindow);
965 #define NUM_EVENTS (20)
966 int main(
int argc,
char** argv)
970 struct sigaction sigint;
971 struct wl_display *display= 0;
972 struct wl_registry *registry= 0;
975 const char *display_name= 0;
976 bool paceRendering=
true;
979 printf(
"rne_triangle: v1.0\n" );
981 memset( &ctx, 0,
sizeof(
AppCtx) );
983 for(
int i= 1; i < argc; ++i )
985 if ( !strcmp( (
const char*)argv[i],
"--delay") )
987 printf(
"got delay: i %d argc %d\n", i, argc );
990 int v= atoi(argv[++i]);
995 printf(
"using delay=%d\n", delay );
999 else if (!strcmp( (
const char*)argv[i],
"--shell" ) )
1003 else if ( !strcmp( (
const char*)argv[i],
"--display") )
1008 display_name= argv[i];
1011 else if (!strcmp( (
const char*)argv[i],
"--noframe" ) )
1013 paceRendering=
false;
1015 else if (!strcmp( (
const char*)argv[i],
"--log" ) )
1019 else if (!strcmp( (
const char*)argv[i],
"--noanimate" ) )
1021 ctx.noAnimation=
true;
1023 else if ( !strcmp( (
const char*)argv[i],
"-?" ) )
1030 ctx.startTime= currentTimeMillis();
1034 printf(
"calling wl_display_connect for display name %s\n", display_name);
1038 printf(
"calling wl_display_connect for default display\n");
1040 display= wl_display_connect(display_name);
1041 printf(
"wl_display_connect: display=%p\n", display);
1044 printf(
"error: unable to connect to primary display\n");
1049 printf(
"calling wl_display_get_registry\n");
1050 registry= wl_display_get_registry(display);
1051 printf(
"wl_display_get_registry: registry=%p\n", registry);
1054 printf(
"error: unable to get display registry\n");
1059 ctx.display= display;
1060 ctx.registry= registry;
1063 ctx.planeWidth= 1280;
1064 ctx.planeHeight= 720;
1065 wl_registry_add_listener(registry, ®istryListener, &ctx);
1067 wl_display_roundtrip(ctx.display);
1071 ctx.surfaceWidth= 1280;
1072 ctx.surfaceHeight= 720;
1076 createSurface(&ctx);
1080 if ( paceRendering )
1085 sigint.sa_handler = signalHandler;
1086 sigemptyset(&sigint.sa_mask);
1087 sigint.sa_flags = SA_RESETHAND;
1088 sigaction(SIGINT, &sigint, NULL);
1090 setBlockingMode(NON_BLOCKING_ENABLED);
1092 ctx.inputState= InputState_main;
1093 ctx.attribute= Attribute_position;
1098 if ( wl_display_dispatch( ctx.display ) == -1 )
1103 if ( !paceRendering )
1110 eglSwapBuffers(ctx.eglDisplay, ctx.eglSurfaceWindow);
1112 else if ( ctx.needRedraw )
1114 ctx.needRedraw=
false;
1122 uint32_t sym= XKB_KEY_NoSymbol;
1123 int c= fgetc(stdin);
1152 processInput(&ctx, sym);
1155 tcflush(STDIN_FILENO,TCIFLUSH);
1159 if ( ctx.surfaceDX || ctx.surfaceDY || ctx.surfaceDWidth || ctx.surfaceDHeight )
1162 ctx.surfaceDX= ctx.surfaceDY= ctx.surfaceDWidth= ctx.surfaceDHeight= 0;
1170 printf(
"rne_triangle: exiting...\n");
1172 setBlockingMode(NON_BLOCKING_DISABLED);
1174 if ( ctx.compositor )
1176 wl_compositor_destroy( ctx.compositor );
1182 wl_simple_shell_destroy( ctx.shell );
1190 xkb_state_unref( ctx.xkbState );
1194 if ( ctx.xkbKeymap )
1196 xkb_keymap_unref( ctx.xkbKeymap );
1202 xkb_context_unref( ctx.xkbCtx );
1208 wl_pointer_destroy(ctx.pointer);
1214 wl_keyboard_destroy(ctx.keyboard);
1220 wl_seat_destroy(ctx.seat);
1226 wl_output_destroy(ctx.output);
1232 wl_registry_destroy(registry);
1238 wl_display_disconnect(display);
1242 printf(
"rne_triangle: exit\n");
1247 #define RED_SIZE (8)
1248 #define GREEN_SIZE (8)
1249 #define BLUE_SIZE (8)
1250 #define ALPHA_SIZE (8)
1251 #define DEPTH_SIZE (0)
1253 static bool setupEGL(
AppCtx *ctx )
1256 EGLint major, minor;
1259 EGLConfig *eglConfigs= 0;
1261 EGLint redSize, greenSize, blueSize, alphaSize, depthSize;
1262 EGLint ctxAttrib[3];
1268 ctx->eglDisplay = eglGetDisplay((NativeDisplayType)ctx->display);
1269 printf(
"eglDisplay=%p\n", ctx->eglDisplay );
1270 if ( ctx->eglDisplay == EGL_NO_DISPLAY )
1272 printf(
"error: EGL not available\n" );
1279 b= eglInitialize( ctx->eglDisplay, &major, &minor );
1282 printf(
"error: unable to initialize EGL display\n" );
1285 printf(
"eglInitiialize: major: %d minor: %d\n", major, minor );
1290 b= eglGetConfigs( ctx->eglDisplay, NULL, 0, &configCount );
1293 printf(
"error: unable to get count of EGL configurations: %X\n", eglGetError() );
1296 printf(
"Number of EGL configurations: %d\n", configCount );
1298 eglConfigs= (EGLConfig*)malloc( configCount*
sizeof(EGLConfig) );
1301 printf(
"error: unable to alloc memory for EGL configurations\n");
1306 attr[i++]= EGL_RED_SIZE;
1307 attr[i++]= RED_SIZE;
1308 attr[i++]= EGL_GREEN_SIZE;
1309 attr[i++]= GREEN_SIZE;
1310 attr[i++]= EGL_BLUE_SIZE;
1311 attr[i++]= BLUE_SIZE;
1312 attr[i++]= EGL_DEPTH_SIZE;
1313 attr[i++]= DEPTH_SIZE;
1314 attr[i++]= EGL_STENCIL_SIZE;
1316 attr[i++]= EGL_SURFACE_TYPE;
1317 attr[i++]= EGL_WINDOW_BIT;
1318 attr[i++]= EGL_RENDERABLE_TYPE;
1319 attr[i++]= EGL_OPENGL_ES2_BIT;
1320 attr[i++]= EGL_NONE;
1325 b= eglChooseConfig( ctx->eglDisplay, attr, eglConfigs, configCount, &configCount );
1328 printf(
"error: eglChooseConfig failed: %X\n", eglGetError() );
1331 printf(
"eglChooseConfig: matching configurations: %d\n", configCount );
1336 for( i= 0; i < configCount; ++i )
1338 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_RED_SIZE, &redSize );
1339 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_GREEN_SIZE, &greenSize );
1340 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_BLUE_SIZE, &blueSize );
1341 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_ALPHA_SIZE, &alphaSize );
1342 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_DEPTH_SIZE, &depthSize );
1344 printf(
"config %d: red: %d green: %d blue: %d alpha: %d depth: %d\n",
1345 i, redSize, greenSize, blueSize, alphaSize, depthSize );
1346 if ( (redSize == RED_SIZE) &&
1347 (greenSize == GREEN_SIZE) &&
1348 (blueSize == BLUE_SIZE) &&
1349 (alphaSize == ALPHA_SIZE) &&
1350 (depthSize >= DEPTH_SIZE) )
1352 printf(
"choosing config %d\n", i);
1356 if ( i == configCount )
1358 printf(
"error: no suitable configuration available\n");
1361 ctx->eglConfig= eglConfigs[i];
1363 ctxAttrib[0]= EGL_CONTEXT_CLIENT_VERSION;
1365 ctxAttrib[2]= EGL_NONE;
1370 ctx->eglContext= eglCreateContext( ctx->eglDisplay, ctx->eglConfig, EGL_NO_CONTEXT, ctxAttrib );
1371 if ( ctx->eglContext == EGL_NO_CONTEXT )
1373 printf(
"eglCreateContext failed: %X\n", eglGetError() );
1376 printf(
"eglCreateContext: eglContext %p\n", ctx->eglContext );
1391 static void termEGL(
AppCtx *ctx )
1395 eglMakeCurrent( ctx->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
1397 destroySurface( ctx );
1399 eglTerminate( ctx->eglDisplay );
1404 static bool createSurface(
AppCtx *ctx )
1409 ctx->surface= wl_compositor_create_surface(ctx->compositor);
1410 printf(
"surface=%p\n", ctx->surface);
1411 if ( !ctx->surface )
1413 printf(
"error: unable to create wayland surface\n");
1417 ctx->native= wl_egl_window_create(ctx->surface, ctx->planeWidth, ctx->planeHeight);
1420 printf(
"error: unable to create wl_egl_window\n");
1423 printf(
"wl_egl_window %p\n", ctx->native);
1428 ctx->eglSurfaceWindow= eglCreateWindowSurface( ctx->eglDisplay,
1430 (EGLNativeWindowType)ctx->native,
1432 if ( ctx->eglSurfaceWindow == EGL_NO_SURFACE )
1434 printf(
"eglCreateWindowSurface: A: error %X\n", eglGetError() );
1435 ctx->eglSurfaceWindow= eglCreateWindowSurface( ctx->eglDisplay,
1437 (EGLNativeWindowType)NULL,
1439 if ( ctx->eglSurfaceWindow == EGL_NO_SURFACE )
1441 printf(
"eglCreateWindowSurface: B: error %X\n", eglGetError() );
1445 printf(
"eglCreateWindowSurface: eglSurfaceWindow %p\n", ctx->eglSurfaceWindow );
1450 b= eglMakeCurrent( ctx->eglDisplay, ctx->eglSurfaceWindow, ctx->eglSurfaceWindow, ctx->eglContext );
1453 printf(
"error: eglMakeCurrent failed: %X\n", eglGetError() );
1457 eglSwapInterval( ctx->eglDisplay, 1 );
1464 static void destroySurface(
AppCtx *ctx )
1466 if ( ctx->eglSurfaceWindow )
1468 eglDestroySurface( ctx->eglDisplay, ctx->eglSurfaceWindow );
1470 wl_egl_window_destroy( ctx->native );
1474 wl_surface_destroy( ctx->surface );
1479 static void resizeSurface(
AppCtx *ctx,
int dx,
int dy,
int width,
int height )
1481 wl_egl_window_resize( ctx->native, width, height, dx, dy );
1484 static const char *vert_shader_text =
1485 "uniform mat4 rotation;\n"
1486 "attribute vec4 pos;\n"
1487 "attribute vec4 color;\n"
1488 "varying vec4 v_color;\n"
1490 " gl_Position = rotation * pos;\n"
1491 " v_color = color;\n"
1494 static const char *frag_shader_text =
1495 "precision mediump float;\n"
1496 "varying vec4 v_color;\n"
1498 " gl_FragColor = v_color;\n"
1501 static GLuint createShader(
AppCtx *ctx, GLenum shaderType,
const char *shaderSource )
1508 shader= glCreateShader( shaderType );
1511 glShaderSource( shader, 1, (
const char **)&shaderSource, NULL );
1512 glCompileShader( shader );
1513 glGetShaderiv( shader, GL_COMPILE_STATUS, &shaderStatus );
1514 if ( !shaderStatus )
1516 glGetShaderInfoLog( shader,
sizeof(logText), &length, logText );
1517 printf(
"Error compiling %s shader: %*s\n",
1518 ((shaderType == GL_VERTEX_SHADER) ?
"vertex" :
"fragment"),
1527 static bool setupGL(
AppCtx *ctx )
1534 frag= createShader(ctx, GL_FRAGMENT_SHADER, frag_shader_text);
1535 vert= createShader(ctx, GL_VERTEX_SHADER, vert_shader_text);
1537 program= glCreateProgram();
1538 glAttachShader(program, frag);
1539 glAttachShader(program, vert);
1540 glLinkProgram(program);
1542 glGetProgramiv(program, GL_LINK_STATUS, &status);
1547 glGetProgramInfoLog(program, 1000, &len, log);
1548 fprintf(stderr,
"Error: linking:\n%*s\n", len, log);
1552 glUseProgram(program);
1557 glBindAttribLocation(program, ctx->gl.pos,
"pos");
1558 glBindAttribLocation(program, ctx->gl.col,
"color");
1559 glLinkProgram(program);
1561 ctx->gl.rotation_uniform= glGetUniformLocation(program,
"rotation");
1567 static bool renderGL(
AppCtx *ctx )
1569 static const GLfloat verts[3][2] = {
1574 static const GLfloat colors[3][4] = {
1580 GLfloat rotation[4][4] = {
1586 static const uint32_t speed_div = 5;
1589 glViewport( 0, 0, ctx->planeWidth, ctx->planeHeight );
1590 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1591 glClear(GL_COLOR_BUFFER_BIT);
1593 ctx->currTime= currentTimeMillis();
1595 angle = ctx->noAnimation ? 0.0 : ((ctx->currTime-ctx->startTime) / speed_div) % 360 * M_PI / 180.0;
1596 rotation[0][0] = cos(angle);
1597 rotation[0][2] = sin(angle);
1598 rotation[2][0] = -sin(angle);
1599 rotation[2][2] = cos(angle);
1601 glUniformMatrix4fv(ctx->gl.rotation_uniform, 1, GL_FALSE, (GLfloat *) rotation);
1603 glVertexAttribPointer(ctx->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
1604 glVertexAttribPointer(ctx->gl.col, 4, GL_FLOAT, GL_FALSE, 0, colors);
1605 glEnableVertexAttribArray(ctx->gl.pos);
1606 glEnableVertexAttribArray(ctx->gl.col);
1608 glDrawArrays(GL_TRIANGLES, 0, 3);
1610 glDisableVertexAttribArray(ctx->gl.pos);
1611 glDisableVertexAttribArray(ctx->gl.col);
1613 GLenum err= glGetError();
1614 if ( err != GL_NO_ERROR )
1616 printf(
"renderGL: glGetError() = %X\n", err );