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 #include "LifeCycle.h"
70 #define UNUSED(x) ((void)x)
72 #if !defined (XKB_KEYMAP_COMPILE_NO_FLAGS)
73 #define XKB_KEYMAP_COMPILE_NO_FLAGS XKB_MAP_COMPILE_NO_FLAGS
76 static void registryHandleGlobal(
void *data,
77 struct wl_registry *registry, uint32_t
id,
78 const char *interface, uint32_t version);
79 static void registryHandleGlobalRemove(
void *data,
80 struct wl_registry *registry,
83 static const struct wl_registry_listener registryListener =
86 registryHandleGlobalRemove
89 static void shellSurfaceId(
void *data,
90 struct wl_simple_shell *wl_simple_shell,
91 struct wl_surface *surface,
93 static void shellSurfaceCreated(
void *data,
94 struct wl_simple_shell *wl_simple_shell,
97 static void shellSurfaceDestroyed(
void *data,
98 struct wl_simple_shell *wl_simple_shell,
101 static void shellSurfaceStatus(
void *data,
102 struct wl_simple_shell *wl_simple_shell,
112 static void shellGetSurfacesDone(
void *data,
113 struct wl_simple_shell *wl_simple_shell);
115 static const struct wl_simple_shell_listener shellListener =
119 shellSurfaceDestroyed,
124 typedef enum _InputState
127 InputState_attribute,
130 typedef enum _Attribute
134 Attribute_visibility,
139 typedef enum _AppMode
147 struct wl_display *display;
148 struct wl_registry *registry;
150 struct wl_compositor *compositor;
151 struct wl_simple_shell *shell;
152 struct wl_seat *seat;
153 struct wl_keyboard *keyboard;
154 struct wl_pointer *pointer;
155 struct wl_touch *touch;
156 struct wl_surface *surface;
157 struct wl_output *output;
158 struct wl_egl_window *native;
159 struct wl_callback *frameCallback;
161 struct xkb_context *xkbCtx;
162 struct xkb_keymap *xkbKeymap;
163 struct xkb_state *xkbState;
164 xkb_mod_index_t modAlt;
165 xkb_mod_index_t modCtrl;
167 EGLDisplay eglDisplay;
169 EGLSurface eglSurfaceWindow;
170 EGLContext eglContext;
171 EGLImageKHR eglImage;
172 EGLNativePixmapType eglPixmap;
175 InputState inputState;
183 uint32_t surfaceIdOther;
184 uint32_t surfaceIdCurrent;
185 float surfaceOpacity;
200 GLuint rotation_uniform;
209 int pointerX, pointerY;
213 static void processInput(
AppCtx *ctx, uint32_t sym );
214 static void drawFrame(
AppCtx *ctx );
215 static bool setupEGL(
AppCtx *ctx );
216 static void termEGL(
AppCtx *ctx );
217 static bool createSurface(
AppCtx *ctx );
218 static void resizeSurface(
AppCtx *ctx,
int dx,
int dy,
int width,
int height );
219 static void destroySurface(
AppCtx *ctx );
220 static bool setupGL(
AppCtx *ctx );
221 static bool renderGL(
AppCtx *ctx );
227 static RtUtils *sRtUtils = NULL;
228 pthread_cond_t g_cond;
229 pthread_mutex_t g_mutex;
230 AppMode g_requestMode = AppMode_Running;
232 static void signalHandler(
int signum)
234 printf(
"signalHandler: signum %d\n", signum);
237 pthread_mutex_lock(&g_mutex);
238 pthread_cond_signal(&g_cond);
239 pthread_mutex_unlock(&g_mutex);
242 static long long currentTimeMillis()
244 long long timeMillis;
247 gettimeofday(&tv, NULL);
248 timeMillis = tv.tv_sec * 1000 + tv.tv_usec / 1000;
253 static void shmFormat(
void *data,
struct wl_shm *wl_shm, uint32_t format)
257 printf(
"shm format: %X\n", format);
260 struct wl_shm_listener shmListener = {
264 static void keyboardKeymap(
void *data,
struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size )
268 if ( format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 )
270 void *map= mmap( 0, size, PROT_READ, MAP_SHARED, fd, 0 );
271 if ( map != MAP_FAILED )
275 ctx->xkbCtx= xkb_context_new( XKB_CONTEXT_NO_FLAGS );
279 printf(
"error: xkb_context_new failed\n");
283 if ( ctx->xkbKeymap )
285 xkb_keymap_unref( ctx->xkbKeymap );
288 ctx->xkbKeymap= xkb_keymap_new_from_string( ctx->xkbCtx, (
char*)map, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
289 if ( !ctx->xkbKeymap )
291 printf(
"error: xkb_keymap_new_from_string failed\n");
295 xkb_state_unref( ctx->xkbState );
298 ctx->xkbState= xkb_state_new( ctx->xkbKeymap );
299 if ( !ctx->xkbState )
301 printf(
"error: xkb_state_new failed\n");
303 if ( ctx->xkbKeymap )
305 ctx->modAlt= xkb_keymap_mod_get_index( ctx->xkbKeymap, XKB_MOD_NAME_ALT );
306 ctx->modCtrl= xkb_keymap_mod_get_index( ctx->xkbKeymap, XKB_MOD_NAME_CTRL );
316 static void keyboardEnter(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
317 struct wl_surface *surface,
struct wl_array *keys )
324 printf(
"keyboard enter surface %p\n", surface );
327 static void keyboardLeave(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
struct wl_surface *surface )
333 printf(
"keyboard leave surface %p\n", surface );
336 static void keyboardKey(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
337 uint32_t time, uint32_t key, uint32_t state )
342 xkb_keycode_t keyCode;
350 sym= xkb_state_key_get_one_sym( ctx->xkbState, keyCode );
352 if ( ctx->verboseLog )
357 if ( xkb_state_mod_index_is_active( ctx->xkbState, ctx->modCtrl, XKB_STATE_MODS_DEPRESSED) == 1 )
362 if ( xkb_state_mod_index_is_active( ctx->xkbState, ctx->modAlt, XKB_STATE_MODS_DEPRESSED) == 1 )
367 printf(
"keyboardKey: sym %X state %s ctrl %d alt %d time %u\n",
368 sym, (state == WL_KEYBOARD_KEY_STATE_PRESSED ?
"Down" :
"Up"), ctrl, alt, time);
371 if ( state == WL_KEYBOARD_KEY_STATE_PRESSED )
373 processInput( ctx, sym );
378 static void keyboardModifiers(
void *data,
struct wl_keyboard *keyboard, uint32_t serial,
379 uint32_t mods_depressed, uint32_t mods_latched,
380 uint32_t mods_locked, uint32_t group )
385 xkb_state_update_mask( ctx->xkbState, mods_depressed, mods_latched, mods_locked, 0, 0, group );
389 static void keyboardRepeatInfo(
void *data,
struct wl_keyboard *keyboard, int32_t rate, int32_t delay )
397 static const struct wl_keyboard_listener keyboardListener= {
406 static void pointerEnter(
void* data,
struct wl_pointer *pointer, uint32_t serial,
407 struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy )
414 x= wl_fixed_to_int( sx );
415 y= wl_fixed_to_int( sy );
420 printf(
"pointer enter surface %p (%d,%d)\n", surface, x, y );
423 static void pointerLeave(
void* data,
struct wl_pointer *pointer, uint32_t serial,
struct wl_surface *surface )
429 printf(
"pointer leave surface %p\n", surface );
432 static void pointerMotion(
void *data,
struct wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy )
438 x= wl_fixed_to_int( sx );
439 y= wl_fixed_to_int( sy );
444 if ( ctx->verboseLog )
446 printf(
"pointer motion surface (%d,%d) time %u\n", x, y, time );
450 static void pointerButton(
void *data,
struct wl_pointer *pointer, uint32_t serial,
451 uint32_t time, uint32_t button, uint32_t state )
457 printf(
"pointer button %u state %u (%d, %d)\n", button, state, ctx->pointerX, ctx->pointerY);
458 ctx->verboseLog= (state == WL_POINTER_BUTTON_STATE_PRESSED);
461 static void pointerAxis(
void *data,
struct wl_pointer *pointer, uint32_t time,
462 uint32_t axis, wl_fixed_t value )
469 v= wl_fixed_to_int( value );
470 printf(
"pointer axis %u value %d\n", axis, v);
473 static const struct wl_pointer_listener pointerListener = {
481 static void seatCapabilities(
void *data,
struct wl_seat *seat, uint32_t capabilities )
485 printf(
"seat %p caps: %X\n", seat, capabilities );
487 if ( capabilities & WL_SEAT_CAPABILITY_KEYBOARD )
489 printf(
" seat has keyboard\n");
490 ctx->keyboard= wl_seat_get_keyboard( ctx->seat );
491 printf(
" keyboard %p\n", ctx->keyboard );
492 wl_keyboard_add_listener( ctx->keyboard, &keyboardListener, ctx );
494 if ( capabilities & WL_SEAT_CAPABILITY_POINTER )
496 printf(
" seat has pointer\n");
497 ctx->pointer= wl_seat_get_pointer( ctx->seat );
498 printf(
" pointer %p\n", ctx->pointer );
499 wl_pointer_add_listener( ctx->pointer, &pointerListener, ctx );
501 if ( capabilities & WL_SEAT_CAPABILITY_TOUCH )
503 printf(
" seat has touch\n");
504 ctx->touch= wl_seat_get_touch( ctx->seat );
505 printf(
" touch %p\n", ctx->touch );
509 static void seatName(
void *data,
struct wl_seat *seat,
const char *name )
512 printf(
"seat %p name: %s\n", seat, name);
515 static const struct wl_seat_listener seatListener = {
520 static void outputGeometry(
void *data,
struct wl_output *output, int32_t x, int32_t y,
521 int32_t physical_width, int32_t physical_height, int32_t subpixel,
522 const char *make,
const char *model, int32_t transform )
528 UNUSED(physical_width);
529 UNUSED(physical_height);
536 static void outputMode(
void *data,
struct wl_output *output, uint32_t flags,
537 int32_t width, int32_t height, int32_t refresh )
541 if ( flags & WL_OUTPUT_MODE_CURRENT )
543 if ( (width != ctx->planeWidth) || (height != ctx->planeHeight) )
545 ctx->planeWidth= width;
546 ctx->planeHeight= height;
547 if ( ctx->verboseLog )
549 printf(
"outputMode: resize egl window to (%d,%d)\n", ctx->planeWidth, ctx->planeHeight );
551 resizeSurface( ctx, 0, 0, ctx->planeWidth, ctx->planeHeight);
556 static void outputDone(
void *data,
struct wl_output *output )
562 static void outputScale(
void *data,
struct wl_output *output, int32_t factor )
569 static const struct wl_output_listener outputListener = {
576 static void registryHandleGlobal(
void *data,
577 struct wl_registry *registry, uint32_t
id,
578 const char *interface, uint32_t version)
583 printf(
"graphics-lifecycle: registry: id %d interface (%s) version %d\n",
id, interface, version );
585 len= strlen(interface);
586 if ( (len==6) && !strncmp(interface,
"wl_shm", len)) {
587 ctx->shm= (
struct wl_shm*)wl_registry_bind(registry,
id, &wl_shm_interface, 1);
588 printf(
"shm %p\n", ctx->shm);
589 wl_shm_add_listener(ctx->shm, &shmListener, ctx);
591 else if ( (len==13) && !strncmp(interface,
"wl_compositor", len) ) {
592 ctx->compositor= (
struct wl_compositor*)wl_registry_bind(registry,
id, &wl_compositor_interface, 1);
593 printf(
"compositor %p\n", ctx->compositor);
595 else if ( (len==7) && !strncmp(interface,
"wl_seat", len) ) {
596 ctx->seat= (
struct wl_seat*)wl_registry_bind(registry,
id, &wl_seat_interface, 4);
597 printf(
"seat %p\n", ctx->seat);
598 wl_seat_add_listener(ctx->seat, &seatListener, ctx);
600 else if ( (len==9) && !strncmp(interface,
"wl_output", len) ) {
601 ctx->output= (
struct wl_output*)wl_registry_bind(registry,
id, &wl_output_interface, 2);
602 printf(
"output %p\n", ctx->output);
603 wl_output_add_listener(ctx->output, &outputListener, ctx);
605 else if ( (len==15) && !strncmp(interface,
"wl_simple_shell", len) ) {
606 if ( ctx->getShell ) {
607 ctx->shell= (
struct wl_simple_shell*)wl_registry_bind(registry,
id, &wl_simple_shell_interface, 1);
608 printf(
"shell %p\n", ctx->shell );
609 wl_simple_shell_add_listener(ctx->shell, &shellListener, ctx);
614 static void registryHandleGlobalRemove(
void *data,
615 struct wl_registry *registry,
620 static void shellSurfaceId(
void *data,
621 struct wl_simple_shell *wl_simple_shell,
622 struct wl_surface *surface,
628 sprintf( name,
"graphics-lifecycle-surface-%x", surfaceId );
629 printf(
"shell: surface created: %p id %x\n", surface, surfaceId);
630 wl_simple_shell_set_name( ctx->shell, surfaceId, name );
633 static void shellSurfaceCreated(
void *data,
634 struct wl_simple_shell *wl_simple_shell,
640 printf(
"shell: surface created: %x name: %s\n", surfaceId, name);
641 ctx->surfaceIdOther= ctx->surfaceIdCurrent;
642 ctx->surfaceIdCurrent= surfaceId;
643 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
644 printf(
"shell: surfaceCurrent: %x surfaceOther: %x\n", ctx->surfaceIdCurrent, ctx->surfaceIdOther);
647 static void shellSurfaceDestroyed(
void *data,
648 struct wl_simple_shell *wl_simple_shell,
654 printf(
"shell: surface destroyed: %x name: %s\n", surfaceId, name);
656 if ( ctx->surfaceIdCurrent == surfaceId )
658 ctx->surfaceIdCurrent= ctx->surfaceIdOther;
659 ctx->surfaceIdOther= 0;
660 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
662 if ( ctx->surfaceIdOther == surfaceId )
664 ctx->surfaceIdOther= 0;
666 printf(
"shell: surfaceCurrent: %x surfaceOther: %x\n", ctx->surfaceIdCurrent, ctx->surfaceIdOther);
669 static void shellSurfaceStatus(
void *data,
670 struct wl_simple_shell *wl_simple_shell,
683 printf(
"shell: surface: %x name: %s\n", surfaceId, name);
684 printf(
"shell: position (%d,%d,%d,%d) visible %d opacity %f zorder %f\n",
685 x, y, width, height, visible, wl_fixed_to_double(opacity), wl_fixed_to_double(zorder) );
687 ctx->surfaceVisible= visible;
690 ctx->surfaceWidth= width;
691 ctx->surfaceHeight= height;
692 ctx->surfaceOpacity= wl_fixed_to_double(opacity);
693 ctx->surfaceZOrder= wl_fixed_to_double(zorder);
696 static void shellGetSurfacesDone(
void *data,
697 struct wl_simple_shell *wl_simple_shell)
700 printf(
"shell: get all surfaces done\n");
703 #define NON_BLOCKING_ENABLED (0)
704 #define NON_BLOCKING_DISABLED (1)
706 static void setBlockingMode(
int blockingState )
708 struct termios ttystate;
711 mask= (blockingState == NON_BLOCKING_ENABLED) ? ~(ICANON|ECHO) : -1;
712 bits= (blockingState == NON_BLOCKING_ENABLED) ? 0 : (ICANON|ECHO);
716 tcgetattr(STDIN_FILENO, &ttystate);
718 ttystate.c_lflag= ((ttystate.c_lflag & mask) | bits);
720 if (blockingState == NON_BLOCKING_ENABLED)
722 ttystate.c_cc[VMIN]= 1;
725 tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
728 static bool isKeyHit()
739 FD_SET(STDIN_FILENO, &fdset);
740 select(STDIN_FILENO+1, &fdset, NULL, NULL, &tval);
742 keyHit= FD_ISSET(STDIN_FILENO, &fdset);
747 static void adjustAttribute(
AppCtx *ctx, uint32_t sym )
749 switch( ctx->attribute )
751 case Attribute_position:
772 --ctx->surfaceDHeight;
775 ++ctx->surfaceDHeight;
778 ++ctx->surfaceDWidth;
781 --ctx->surfaceDWidth;
785 case Attribute_visibility:
792 ctx->surfaceVisible= !ctx->surfaceVisible;
793 wl_simple_shell_set_visible( ctx->shell, ctx->surfaceIdCurrent, (ctx->surfaceVisible ? 1 : 0) );
797 case Attribute_opacity:
802 ctx->surfaceOpacity += 0.1;
803 if ( ctx->surfaceOpacity > 1.0 )
805 ctx->surfaceOpacity= 1.0;
807 wl_simple_shell_set_opacity( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceOpacity) );
811 ctx->surfaceOpacity -= 0.1;
812 if ( ctx->surfaceOpacity < 0.0 )
814 ctx->surfaceOpacity= 0.0;
816 wl_simple_shell_set_opacity( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceOpacity) );
820 case Attribute_zorder:
825 ctx->surfaceZOrder += 0.1;
826 if ( ctx->surfaceZOrder > 1.0 )
828 ctx->surfaceZOrder= 1.0;
830 wl_simple_shell_set_zorder( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceZOrder) );
834 ctx->surfaceZOrder -= 0.1;
835 if ( ctx->surfaceZOrder < 0.0 )
837 ctx->surfaceZOrder= 0.0;
839 wl_simple_shell_set_zorder( ctx->shell, ctx->surfaceIdCurrent, wl_fixed_from_double(ctx->surfaceZOrder) );
846 static void processInputMain(
AppCtx *ctx, uint32_t sym )
854 if ( ctx->surfaceIdCurrent )
856 adjustAttribute( ctx, sym );
860 ctx->inputState= InputState_attribute;
861 printf(
"attribute: (p) osition, (s) ize, (v) isible, (o) pacity, (z) order (x) back to main\n");
864 if ( ctx->surfaceIdCurrent )
866 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
870 if ( ctx->surfaceIdOther )
872 uint32_t temp= ctx->surfaceIdCurrent;
873 ctx->surfaceIdCurrent= ctx->surfaceIdOther;
874 ctx->surfaceIdOther= temp;
875 printf(
"shell: surfaceCurrent: %x surfaceOther: %x\n", ctx->surfaceIdCurrent, ctx->surfaceIdOther);
876 wl_simple_shell_get_status( ctx->shell, ctx->surfaceIdCurrent );
882 printf(
"get all surfaces:\n");
883 wl_simple_shell_get_surfaces( ctx->shell );
887 ctx->planeWidth= (ctx->planeWidth == 1280) ? 640 : 1280;
888 ctx->planeHeight= (ctx->planeHeight == 720) ? 360 : 720;
889 printf(
"resize egl window to (%d,%d)\n", ctx->planeWidth, ctx->planeHeight );
890 resizeSurface( ctx, 0, 0, ctx->planeWidth, ctx->planeHeight);
895 static void processInputAttribute(
AppCtx *ctx, uint32_t sym )
900 ctx->attribute= Attribute_position;
903 ctx->attribute= Attribute_size;
906 ctx->attribute= Attribute_visibility;
909 ctx->attribute= Attribute_opacity;
912 ctx->attribute= Attribute_zorder;
918 ctx->inputState= InputState_main;
921 static void processInput(
AppCtx *ctx, uint32_t sym )
923 switch( ctx->inputState )
925 case InputState_main:
926 processInputMain( ctx, sym );
928 case InputState_attribute:
929 processInputAttribute( ctx, sym );
934 static void showUsage()
937 printf(
" graphics_lifecycle [options]\n" );
938 printf(
"where [options] are:\n" );
939 printf(
" --delay <delay> : render loop delay\n" );
940 printf(
" --shell : use wl_simple_shell protocol\n" );
941 printf(
" --display <name> : wayland display to connect to\n" );
942 printf(
" --noframe : don't pace rendering with frame requests\n" );
943 printf(
" --noanimate : don't use animation\n" );
944 printf(
" -? : show usage\n" );
948 static void redraw(
void *data,
struct wl_callback *callback, uint32_t time )
952 if ( g_log ) printf(
"redraw: time %u\n", time);
953 wl_callback_destroy( callback );
955 ctx->needRedraw=
true;
958 static struct wl_callback_listener frameListener=
963 static void drawFrame(
AppCtx *ctx )
965 if ( ctx->surfaceDX || ctx->surfaceDY || ctx->surfaceDWidth || ctx->surfaceDHeight )
967 ctx->surfaceX += ctx->surfaceDX;
968 ctx->surfaceY += ctx->surfaceDY;
969 ctx->surfaceWidth += ctx->surfaceDWidth;
970 ctx->surfaceHeight += ctx->surfaceDHeight;
972 wl_simple_shell_set_geometry( ctx->shell, ctx->surfaceIdCurrent,
973 ctx->surfaceX, ctx->surfaceY, ctx->surfaceWidth, ctx->surfaceHeight );
978 ctx->frameCallback= wl_surface_frame( ctx->surface );
979 wl_callback_add_listener( ctx->frameCallback, &frameListener, ctx );
981 eglSwapBuffers(ctx->eglDisplay, ctx->eglSurfaceWindow);
984 int initGraphics(
const char* display_name,
bool paceRendering,
AppCtx *ctx)
988 printf(
"calling wl_display_connect for display name %s\n", display_name);
992 printf(
"calling wl_display_connect for default display\n");
994 ctx->display= wl_display_connect(display_name);
995 printf(
"wl_display_connect: display=%p\n", ctx->display);
998 printf(
"error: unable to connect to primary display\n");
1002 printf(
"calling wl_display_get_registry\n");
1003 ctx->registry= wl_display_get_registry(ctx->display);
1004 printf(
"wl_display_get_registry: registry=%p\n", ctx->registry);
1005 if ( !ctx->registry )
1007 printf(
"error: unable to get display registry\n");
1013 ctx->planeWidth= 1280;
1014 ctx->planeHeight= 720;
1015 wl_registry_add_listener(ctx->registry, ®istryListener, ctx);
1017 wl_display_roundtrip(ctx->display);
1021 ctx->surfaceWidth= 1280;
1022 ctx->surfaceHeight= 720;
1030 if ( paceRendering )
1038 void destroyGraphics(
AppCtx* ctx)
1040 if ( ctx->compositor )
1042 wl_compositor_destroy( ctx->compositor );
1048 wl_simple_shell_destroy( ctx->shell );
1054 if ( ctx->xkbState )
1056 xkb_state_unref( ctx->xkbState );
1060 if ( ctx->xkbKeymap )
1062 xkb_keymap_unref( ctx->xkbKeymap );
1068 xkb_context_unref( ctx->xkbCtx );
1074 wl_pointer_destroy(ctx->pointer);
1078 if ( ctx->keyboard )
1080 wl_keyboard_destroy(ctx->keyboard);
1086 wl_seat_destroy(ctx->seat);
1092 wl_output_destroy(ctx->output);
1096 if ( ctx->registry )
1098 wl_registry_destroy(ctx->registry);
1104 wl_display_disconnect(ctx->display);
1109 void runGraphicsIteration(
AppCtx* ctx,
bool paceRendering,
int delay)
1111 if ( wl_display_dispatch( ctx->display ) == -1 )
1116 if ( !paceRendering )
1123 eglSwapBuffers(ctx->eglDisplay, ctx->eglSurfaceWindow);
1125 else if ( ctx->needRedraw )
1127 ctx->needRedraw=
false;
1131 if ( ctx->getShell )
1135 uint32_t sym= XKB_KEY_NoSymbol;
1136 int c= fgetc(stdin);
1165 processInput(ctx, sym);
1168 tcflush(STDIN_FILENO,TCIFLUSH);
1172 if ( ctx->surfaceDX || ctx->surfaceDY || ctx->surfaceDWidth || ctx->surfaceDHeight )
1175 ctx->surfaceDX= ctx->surfaceDY= ctx->surfaceDWidth= ctx->surfaceDHeight= 0;
1185 pthread_mutex_lock(&g_mutex);
1186 g_requestMode = AppMode_Suspended;
1187 pthread_mutex_unlock(&g_mutex);
1190 void onResume(
const char * p)
1192 pthread_mutex_lock(&g_mutex);
1193 g_requestMode = AppMode_Running;
1194 pthread_cond_signal(&g_cond);
1195 pthread_mutex_unlock(&g_mutex);
1202 rc = sRtUtils->initRt();
1207 const char* objectName = getenv(
"PX_WAYLAND_CLIENT_REMOTE_OBJECT_NAME");
1208 if (!objectName) objectName =
"GRAPHICS_LIFECYLE_RT";
1209 printf(
"Register RT object: %s\n", objectName);
1213 rc = rtRemoteRegisterObject(objectName, sLifeCycle);
1217 printf(
"Failed to register Graphics LifeCycle client to rt!\n");
1231 printf(
"before Graphics LifeCycle destruction\n"); fflush(stdout);
1234 printf(
"after Graphics LifeCycle destruction\n"); fflush(stdout);
1236 printf(
"before rt utils destruction\n"); fflush(stdout);
1237 if(sRtUtils)
delete sRtUtils;
1239 printf(
"after rt utils destruction\n"); fflush(stdout);
1242 void processLifeCycleChange(
const char* display_name,
bool paceRendering,
AppCtx *ctx)
1244 pthread_mutex_lock(&g_mutex);
1247 if(g_requestMode == AppMode_Suspended)
1251 printf(
"Graphics App is going into a suspend state\n");
1252 destroyGraphics(ctx);
1253 ctx->appMode = g_requestMode;
1254 pthread_cond_wait(&g_cond, &g_mutex);
1258 if(g_requestMode == AppMode_Running && ctx->appMode != g_requestMode)
1260 printf(
"Graphics App is going into a resume state\n");
1261 initGraphics(display_name, paceRendering, ctx);
1262 ctx->appMode = g_requestMode;
1265 pthread_mutex_unlock(&g_mutex);
1269 #define NUM_EVENTS (20)
1270 int main(
int argc,
char** argv)
1274 struct sigaction sigint;
1276 const char *display_name= 0;
1277 bool paceRendering=
true;
1281 printf(
"graphics_lifecycle: v1.0\n" );
1283 memset( &ctx, 0,
sizeof(
AppCtx) );
1284 ctx.verboseLog =
true;
1286 pthread_cond_init(&g_cond,NULL);
1287 pthread_mutex_init(&g_mutex,NULL);
1291 for(
int i= 1; i < argc; ++i )
1293 if ( !strcmp( (
const char*)argv[i],
"--delay") )
1295 printf(
"got delay: i %d argc %d\n", i, argc );
1298 int v= atoi(argv[++i]);
1299 printf(
"v=%d\n", v);
1303 printf(
"using delay=%d\n", delay );
1307 else if (!strcmp( (
const char*)argv[i],
"--shell" ) )
1311 else if ( !strcmp( (
const char*)argv[i],
"--display") )
1316 display_name= argv[i];
1319 else if (!strcmp( (
const char*)argv[i],
"--noframe" ) )
1321 paceRendering=
false;
1323 else if (!strcmp( (
const char*)argv[i],
"--log" ) )
1327 else if (!strcmp( (
const char*)argv[i],
"--noanimate" ) )
1329 ctx.noAnimation=
true;
1331 else if ( !strcmp( (
const char*)argv[i],
"-?" ) )
1338 ctx.startTime= currentTimeMillis();
1340 sigint.sa_handler = signalHandler;
1341 sigemptyset(&sigint.sa_mask);
1342 sigint.sa_flags = SA_RESETHAND;
1343 sigaction(SIGINT, &sigint, NULL);
1345 setBlockingMode(NON_BLOCKING_ENABLED);
1347 ctx.inputState= InputState_main;
1348 ctx.attribute= Attribute_position;
1350 nRC = initGraphics(display_name, paceRendering, &ctx);
1357 runGraphicsIteration(&ctx, paceRendering, delay);
1358 processLifeCycleChange(display_name, paceRendering, &ctx);
1363 printf(
"graphics_lifecycle: exiting...\n");
1365 setBlockingMode(NON_BLOCKING_DISABLED);
1366 if(ctx.appMode != AppMode_Suspended)
1368 printf(
"Destroying graphics on exit because not suspended!\n");
1369 destroyGraphics(&ctx);
1373 printf(
"graphics_lifecycle: exit\n");
1378 #define RED_SIZE (8)
1379 #define GREEN_SIZE (8)
1380 #define BLUE_SIZE (8)
1381 #define ALPHA_SIZE (8)
1382 #define DEPTH_SIZE (0)
1384 static bool setupEGL(
AppCtx *ctx )
1387 EGLint major, minor;
1390 EGLConfig *eglConfigs= 0;
1392 EGLint redSize, greenSize, blueSize, alphaSize, depthSize;
1393 EGLint ctxAttrib[3];
1399 ctx->eglDisplay = eglGetDisplay((NativeDisplayType)ctx->display);
1400 printf(
"eglDisplay=%p\n", ctx->eglDisplay );
1401 if ( ctx->eglDisplay == EGL_NO_DISPLAY )
1403 printf(
"error: EGL not available\n" );
1410 b= eglInitialize( ctx->eglDisplay, &major, &minor );
1413 printf(
"error: unable to initialize EGL display\n" );
1416 printf(
"eglInitiialize: major: %d minor: %d\n", major, minor );
1421 b= eglGetConfigs( ctx->eglDisplay, NULL, 0, &configCount );
1424 printf(
"error: unable to get count of EGL configurations: %X\n", eglGetError() );
1427 printf(
"Number of EGL configurations: %d\n", configCount );
1429 eglConfigs= (EGLConfig*)malloc( configCount*
sizeof(EGLConfig) );
1432 printf(
"error: unable to alloc memory for EGL configurations\n");
1437 attr[i++]= EGL_RED_SIZE;
1438 attr[i++]= RED_SIZE;
1439 attr[i++]= EGL_GREEN_SIZE;
1440 attr[i++]= GREEN_SIZE;
1441 attr[i++]= EGL_BLUE_SIZE;
1442 attr[i++]= BLUE_SIZE;
1443 attr[i++]= EGL_DEPTH_SIZE;
1444 attr[i++]= DEPTH_SIZE;
1445 attr[i++]= EGL_STENCIL_SIZE;
1447 attr[i++]= EGL_SURFACE_TYPE;
1448 attr[i++]= EGL_WINDOW_BIT;
1449 attr[i++]= EGL_RENDERABLE_TYPE;
1450 attr[i++]= EGL_OPENGL_ES2_BIT;
1451 attr[i++]= EGL_NONE;
1456 b= eglChooseConfig( ctx->eglDisplay, attr, eglConfigs, configCount, &configCount );
1459 printf(
"error: eglChooseConfig failed: %X\n", eglGetError() );
1462 printf(
"eglChooseConfig: matching configurations: %d\n", configCount );
1467 for( i= 0; i < configCount; ++i )
1469 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_RED_SIZE, &redSize );
1470 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_GREEN_SIZE, &greenSize );
1471 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_BLUE_SIZE, &blueSize );
1472 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_ALPHA_SIZE, &alphaSize );
1473 eglGetConfigAttrib( ctx->eglDisplay, eglConfigs[i], EGL_DEPTH_SIZE, &depthSize );
1475 printf(
"config %d: red: %d green: %d blue: %d alpha: %d depth: %d\n",
1476 i, redSize, greenSize, blueSize, alphaSize, depthSize );
1477 if ( (redSize == RED_SIZE) &&
1478 (greenSize == GREEN_SIZE) &&
1479 (blueSize == BLUE_SIZE) &&
1480 (alphaSize == ALPHA_SIZE) &&
1481 (depthSize >= DEPTH_SIZE) )
1483 printf(
"choosing config %d\n", i);
1487 if ( i == configCount )
1489 printf(
"error: no suitable configuration available\n");
1492 ctx->eglConfig= eglConfigs[i];
1494 ctxAttrib[0]= EGL_CONTEXT_CLIENT_VERSION;
1496 ctxAttrib[2]= EGL_NONE;
1501 ctx->eglContext= eglCreateContext( ctx->eglDisplay, ctx->eglConfig, EGL_NO_CONTEXT, ctxAttrib );
1502 if ( ctx->eglContext == EGL_NO_CONTEXT )
1504 printf(
"eglCreateContext failed: %X\n", eglGetError() );
1507 printf(
"eglCreateContext: eglContext %p\n", ctx->eglContext );
1522 static void termEGL(
AppCtx *ctx )
1526 eglMakeCurrent( ctx->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
1528 destroySurface( ctx );
1530 eglTerminate( ctx->eglDisplay );
1535 static bool createSurface(
AppCtx *ctx )
1540 ctx->surface= wl_compositor_create_surface(ctx->compositor);
1541 printf(
"surface=%p\n", ctx->surface);
1542 if ( !ctx->surface )
1544 printf(
"error: unable to create wayland surface\n");
1548 ctx->native= wl_egl_window_create(ctx->surface, ctx->planeWidth, ctx->planeHeight);
1551 printf(
"error: unable to create wl_egl_window\n");
1554 printf(
"wl_egl_window %p\n", ctx->native);
1559 ctx->eglSurfaceWindow= eglCreateWindowSurface( ctx->eglDisplay,
1561 (EGLNativeWindowType)ctx->native,
1563 if ( ctx->eglSurfaceWindow == EGL_NO_SURFACE )
1565 printf(
"eglCreateWindowSurface: A: error %X\n", eglGetError() );
1566 ctx->eglSurfaceWindow= eglCreateWindowSurface( ctx->eglDisplay,
1568 (EGLNativeWindowType)NULL,
1570 if ( ctx->eglSurfaceWindow == EGL_NO_SURFACE )
1572 printf(
"eglCreateWindowSurface: B: error %X\n", eglGetError() );
1576 printf(
"eglCreateWindowSurface: eglSurfaceWindow %p\n", ctx->eglSurfaceWindow );
1581 b= eglMakeCurrent( ctx->eglDisplay, ctx->eglSurfaceWindow, ctx->eglSurfaceWindow, ctx->eglContext );
1584 printf(
"error: eglMakeCurrent failed: %X\n", eglGetError() );
1588 eglSwapInterval( ctx->eglDisplay, 1 );
1595 static void destroySurface(
AppCtx *ctx )
1597 if ( ctx->eglSurfaceWindow )
1599 eglDestroySurface( ctx->eglDisplay, ctx->eglSurfaceWindow );
1601 wl_egl_window_destroy( ctx->native );
1603 eglDestroyContext(ctx->eglDisplay, ctx->eglContext);
1606 wl_surface_destroy( ctx->surface );
1611 static void resizeSurface(
AppCtx *ctx,
int dx,
int dy,
int width,
int height )
1613 wl_egl_window_resize( ctx->native, width, height, dx, dy );
1616 static const char *vert_shader_text =
1617 "uniform mat4 rotation;\n"
1618 "attribute vec4 pos;\n"
1619 "attribute vec4 color;\n"
1620 "varying vec4 v_color;\n"
1622 " gl_Position = rotation * pos;\n"
1623 " v_color = color;\n"
1626 static const char *frag_shader_text =
1627 "precision mediump float;\n"
1628 "varying vec4 v_color;\n"
1630 " gl_FragColor = v_color;\n"
1633 static GLuint createShader(
AppCtx *ctx, GLenum shaderType,
const char *shaderSource )
1640 shader= glCreateShader( shaderType );
1643 glShaderSource( shader, 1, (
const char **)&shaderSource, NULL );
1644 glCompileShader( shader );
1645 glGetShaderiv( shader, GL_COMPILE_STATUS, &shaderStatus );
1646 if ( !shaderStatus )
1648 glGetShaderInfoLog( shader,
sizeof(logText), &length, logText );
1649 printf(
"Error compiling %s shader: %*s\n",
1650 ((shaderType == GL_VERTEX_SHADER) ?
"vertex" :
"fragment"),
1659 static bool setupGL(
AppCtx *ctx )
1666 frag= createShader(ctx, GL_FRAGMENT_SHADER, frag_shader_text);
1667 vert= createShader(ctx, GL_VERTEX_SHADER, vert_shader_text);
1669 program= glCreateProgram();
1670 glAttachShader(program, frag);
1671 glAttachShader(program, vert);
1672 glLinkProgram(program);
1674 glGetProgramiv(program, GL_LINK_STATUS, &status);
1679 glGetProgramInfoLog(program, 1000, &len, log);
1680 fprintf(stderr,
"Error: linking:\n%*s\n", len, log);
1684 glUseProgram(program);
1689 glBindAttribLocation(program, ctx->gl.pos,
"pos");
1690 glBindAttribLocation(program, ctx->gl.col,
"color");
1691 glLinkProgram(program);
1693 ctx->gl.rotation_uniform= glGetUniformLocation(program,
"rotation");
1699 static bool renderGL(
AppCtx *ctx )
1701 static const GLfloat verts[3][2] = {
1706 static const GLfloat colors[3][4] = {
1712 GLfloat rotation[4][4] = {
1718 static const uint32_t speed_div = 5;
1721 glViewport( 0, 0, ctx->planeWidth, ctx->planeHeight );
1722 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
1723 glClear(GL_COLOR_BUFFER_BIT);
1725 ctx->currTime= currentTimeMillis();
1727 angle = ctx->noAnimation ? 0.0 : ((ctx->currTime-ctx->startTime) / speed_div) % 360 * M_PI / 180.0;
1728 rotation[0][0] = cos(angle);
1729 rotation[0][2] = sin(angle);
1730 rotation[2][0] = -sin(angle);
1731 rotation[2][2] = cos(angle);
1733 glUniformMatrix4fv(ctx->gl.rotation_uniform, 1, GL_FALSE, (GLfloat *) rotation);
1735 glVertexAttribPointer(ctx->gl.pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
1736 glVertexAttribPointer(ctx->gl.col, 4, GL_FLOAT, GL_FALSE, 0, colors);
1737 glEnableVertexAttribArray(ctx->gl.pos);
1738 glEnableVertexAttribArray(ctx->gl.col);
1740 glDrawArrays(GL_TRIANGLES, 0, 3);
1742 glDisableVertexAttribArray(ctx->gl.pos);
1743 glDisableVertexAttribArray(ctx->gl.col);
1745 GLenum err= glGetError();
1746 if ( err != GL_NO_ERROR )
1748 printf(
"renderGL: glGetError() = %X\n", err );