[dali_2.1.22] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / adaptors / scripts / dalireslog.sh
1 #!/bin/bash
2 PATH=/bin:/usr/bin:/sbin:/usr/sbin
3 # Log resource analyser tool for Dali
4 # Monitors resource usage of last run Dali app
5 # Shows memory uploaded to GPU or normal RAM
6 # Texture atlas usage usually reflects used Font atlases
7
8 set -u
9
10 #global variables
11 TERM_W=0       # latest width of terminal window
12 TERM_H=0       # latest height of terminal window
13 SEPARATOR_H=5  # 5 lines in info bar
14 CURPAGE=0      # current page number
15 MAXFILENO=0    # maximum lines to display from resourcelist
16 MAXP=0         # number of pages
17
18 DLOGTEMPFILE=/tmp/dalidlog.txt
19 DLOGUTIL=/usr/bin/dlogutil
20 USING_DLOG=
21 INPUTFILE=""
22
23
24
25 #possible states
26 # ID| Desc                             | Color     | Tags
27 #---+----------------------------------+-----------+-------
28 # 0.| loaded in CPU memory             |  [CPU]    | [LOAD]
29 # 1.| present in both memories         |  [CPUGPU] | [LOAD] [UPLOAD]
30 # 2.| GPU memory only, buffer discarded|  [GPU]    | [UPLOAD] [DELBUF]
31 # 3.| loaded but discarded later on    |  [DISC]   | [LOAD] [DELBUF] or [DELBUF] [DELTEXTURE]
32
33 #colors for marking resource state
34 COLOR_CPU=5
35 COLOR_CPUGPU=1
36 COLOR_GPU=2
37 COLOR_DISC=6
38
39 declare -a COLORS=( $COLOR_CPU $COLOR_CPUGPU $COLOR_GPU $COLOR_DISC )
40
41 declare -a FILENAMES_G=( )
42 declare -a BITMAPS_G=( )
43 declare -a TEXTURES_G=( )
44 declare -a STATES_G=( )
45 declare -a SIZES_G=( )
46 declare -a SIZE_DETAILS_G=( )
47
48 ATLASMEM=0
49 ATLAS_NO=0
50
51 CPUMEM=0
52 GPUMEM=0
53
54 #process ID of last running Dali app
55 PID_G=0
56
57 #distinguish texture atlases from framebuffer textures
58 BITMAP_ID_ATLAS=0
59 BITMAP_ID_FB_TEXTURE="-"
60
61 ###################################string formatting, command line and error handling
62 function error
63 {
64   echo "Error: $1"
65   cleanup
66   exit 1
67 }
68
69 function usage
70 {
71     echo "usage: ./dalireslog.sh [FILE]"
72     echo "if FILE isn't specified script will try to use dlogutil"
73 }
74
75 function getTermSize
76 {
77     TERM_W=$(tput cols)
78     TERM_H=$(tput lines)
79
80     let MAXFILENO=$(($TERM_H-$SEPARATOR_H-2)) #leave space for keyboard shortcuts and separator itself
81     let MAXP=${#FILENAMES_G[@]}/$MAXFILENO
82
83     # don't show empty page if list just fits on screen
84     local rmd=0
85     let rmd=${#FILENAMES_G[@]}%$MAXFILENO
86     if [ $rmd -eq 0 ]
87     then
88         let MAXP-=1;
89     fi
90 }
91
92 # print string, notifying user if it doesn't fit in one line. takes one parameter
93 function printString
94 {
95     echo -n ${1:0:$TERM_W}
96     if [[ $TERM_W -lt ${#1} ]]
97     then
98         tput cub 1;
99         tput setab 1; tput smso; echo -n '>'; tput el; tput rmso
100         return 1
101     else
102         tput el
103         return 0
104     fi
105 }
106
107 # print string, clear until end of line, print newline. takes one parameter
108 function printLine
109 {
110     printString "$1"
111     local RET=$?
112     printf '\n'
113     return $RET
114 }
115
116 function parseCmdLine
117 {
118     if [[ $# -lt 1 ]]
119     then
120         # try using dlogutil
121         if [[ ! -e "$DLOGUTIL" ]]
122         then
123             echo "dlogutil not installed"
124             usage
125             exit 1
126         fi
127
128         INPUTFILE="$DLOGTEMPFILE"
129         USING_DLOG=true
130     else
131         # check if help is requested
132         if [[ $1 == '-h' || $1 == '--help' ]]
133         then
134             usage
135             exit 0
136         # try reading from file
137         else
138             INPUTFILE=$1
139             if [[ ! -e "$INPUTFILE" ]]
140             then
141                 echo cannot read file "$INPUTFILE"
142                 usage
143                 exit 1
144             fi
145         fi
146     fi
147 }
148
149 # print filename or basename or "..." depending on terminal size, takes one parameter
150 function printPath
151 {
152     if [ -z "$1" ]
153     then
154         echo "ERROR in printPath";
155         cleanup; exit 1
156     fi
157
158     FILENAME="$1"
159     FBASENAME=$(basename $FILENAME)
160     if [[ ${#FILENAME} -lt $TERM_W ]]
161     then
162         printLine "$FILENAME"
163     else
164         if [[ ${#FBASENAME} -lt $TERM_W ]]
165         then
166             printLine "$FBASENAME"
167         else
168             printLine ...
169         fi
170     fi
171 }
172
173 ###################################memory query functions
174 function getGpuMemUsage
175 {
176   GPUMEM=0
177   local i=0
178   for state in ${STATES_G[@]}
179   do
180     if [[ $state == 1 || $state == 2 ]]
181     then
182       let GPUMEM+=${SIZES_G[$i]}
183     fi
184     let i+=1
185   done
186   return $GPUMEM
187 }
188
189 function getCpuMemUsage
190 {
191   CPUMEM=0
192   local i=0
193   for state in ${STATES_G[@]}
194   do
195     if [[ $state == 0 || $state == 1 ]]
196     then
197       let CPUMEM+=${SIZES_G[$i]}
198     fi
199     let i+=1
200   done
201   return $CPUMEM
202 }
203
204 function getAtlasNumber
205 {
206   ATLAS_NO=0
207   local i=0
208   for bitmap in ${BITMAPS_G[@]}
209   do
210     if [[ $bitmap == 0 && ${STATES_G[$i]} == 2 ]]
211     then
212       let ATLAS_NO+=1
213     fi
214     let i+=1
215   done
216   return $ATLAS_NO
217 }
218
219 function getAtlasMemUsage
220 {
221   ATLASMEM=0
222   local i=0
223   for bitmap in ${BITMAPS_G[@]}
224   do
225     if [[ $bitmap == 0 && ${STATES_G[$i]} == 2 ]]
226     then
227       let ATLASMEM+=${SIZES_G[$i]}
228     fi
229     let i+=1
230   done
231   return $ATLASMEM
232 }
233
234 ##################################global arrays manipulation
235 #adds record to resource list
236 #params: filename, bitmap, texture, state, size, size detail
237 function addRecord
238 {
239   if [ $# -ne 6 ]
240   then
241     error "addRecord - number of arguments is $#"
242   fi
243   FILENAMES_G+=("$1")
244   BITMAPS_G+=("$2")
245   TEXTURES_G+=("$3")
246   STATES_G+=("$4")
247   SIZES_G+=("$5")
248   SIZE_DETAILS_G+=("$6")
249 }
250
251 #adds image resource to list
252 #params: filename, bitmap, size, size detail
253 function fileLoaded
254 {
255   if [ $# -ne 4 ]
256   then
257     error "fileLoaded"
258   fi
259   FILENAMES_G+=("$1")
260   BITMAPS_G+=("$2")
261   SIZES_G+=("$3")
262   SIZE_DETAILS_G+=("$4")
263   TEXTURES_G+=(0)
264   STATES_G+=(0)
265 }
266
267 #params: texture, size, size detail
268 function atlasUploaded
269 {
270   FILENAMES_G+=("-")
271   BITMAPS_G+=("$BITMAP_ID_ATLAS")
272   TEXTURES_G+=("$1")
273   STATES_G+=(2)
274   SIZES_G+=("$2")
275   SIZE_DETAILS_G+=("$3")
276 }
277
278 #params: size, size detail
279 function frameBufUploaded
280 {
281   FILENAMES_G+=("$1")
282   BITMAPS_G+=("$BITMAP_ID_FB_TEXTURE")
283   TEXTURES_G+=("$2")
284   STATES_G+=(2)
285   SIZES_G+=("$3")
286   SIZE_DETAILS_G+=("$4")
287 }
288
289
290 ##################################log parsing functions
291 function checkLoaded
292 {
293   if [[ "$1" =~ .*DALI.*[LOAD].*file\ (.*)\ to\ Bitmap\ (.*)\ -\ size\ ([[:digit:]]*)\ bytes\ (.*) ]]
294   then
295     local FILENAME="${BASH_REMATCH[1]}"
296     local BITMAP="${BASH_REMATCH[2]}"
297     local SIZE="${BASH_REMATCH[3]}"
298     local SIZE_DETAILS="${BASH_REMATCH[4]}"
299
300     local found=0
301
302     #check if file was loaded before with same size
303     local i=0
304     if [ ${#FILENAMES_G[@]} -ne 0 ]
305     then
306
307     for filenameIter in ${FILENAMES_G[@]}
308     do
309       if [[ "$filenameIter" == "$FILENAME" ]]
310       then
311         if [[ ${SIZES_G[$i]} == "$SIZE" && ${SIZE_DETAILS_G[$i]} == "$SIZE_DETAILS" ]]
312         then
313           found=1
314           case ${STATES_G[$i]} in
315             0) #CPU
316               BITMAPS_G[$i]="$BITMAP"
317               ;;
318             1) #CPUGPU
319               BITMAPS_G[$i]="$BITMAP"
320               ;;
321             2) #GPU
322               STATES_G[$i]=1 #GPU->CPUGPU  loaded into memory again
323               BITMAPS_G[$i]="$BITMAP"
324               ;;
325             3) #DISC
326               #previously discarded, load again
327               STATES_G[$i]=0
328               BITMAPS_G[$i]="$BITMAP"
329               ;;
330             *)
331               error "checkLoaded - unknown state"
332               ;;
333           esac
334         else
335           #filename is same, but its loaded in different size
336           :
337         fi
338       fi
339       let i+=1
340     done
341     fi
342
343     if [ $found -ne 1 ]
344     then
345       fileLoaded "$FILENAME" "$BITMAP" "$SIZE" "$SIZE_DETAILS"
346     fi
347
348     return 0
349   else
350     error "checkLoaded"
351   fi
352 }
353
354 function checkUploaded
355 {
356   if [[ "$1" =~ .*DALI.*[UPLOAD].*Bitmap\ (.*)\ to\ Texture\ (.*)\ -\ size\ ([[:digit:]]*)\ bytes\ (.*) ]]
357   then
358     local BITMAP="${BASH_REMATCH[1]}"
359     local TEXTURE="${BASH_REMATCH[2]}"
360     local SIZE="${BASH_REMATCH[3]}"
361     local SIZE_DETAILS="${BASH_REMATCH[4]}"
362
363     local i=0
364     local lastIdx=-1
365
366     if [[ "$BITMAP" =~ \(nil\) ]]
367     then
368       atlasUploaded $TEXTURE $SIZE "$SIZE_DETAILS"
369       return 0
370     else
371       #not a texture atlas
372       if [ ${#BITMAPS_G[@]} -ne $BITMAP_ID_ATLAS ]
373       then
374         for bitmap in ${BITMAPS_G[@]}
375         do
376           if [ $bitmap == $BITMAP ]
377           then
378             lastIdx=$i
379           fi
380         let i+=1
381         done
382       fi
383     fi
384
385     if [ $lastIdx != -1 ]
386     then
387       #Bitmap found
388       if [[ ${TEXTURES_G[$lastIdx]} == 0 && ${STATES_G[$lastIdx]} == 0 ]]
389       then
390         #File loaded in memory -> upload to GPU
391         TEXTURES_G[$lastIdx]="$TEXTURE"
392         STATES_G[$lastIdx]=1
393       elif [[ ${FILENAMES_G[$lastIdx]} == "-" && ${STATES_G[$lastIdx]} == 1 ]]
394       then
395         #BufferImage already in memory and GPU mem. -> updated
396         SIZES_G[$lastIdx]=$SIZE
397         SIZE_DETAILS_G[$lastIdx]="$SIZE_DETAILS"
398       else
399         #bitmap uploaded to new texture
400         addRecord ${FILENAMES_G[$lastIdx]} $BITMAP $TEXTURE 1 $SIZE "$SIZE_DETAILS"
401       fi
402     else
403       #bitmapImage - not loaded from file
404       #newly added
405       addRecord "-" $BITMAP $TEXTURE 1 $SIZE "$SIZE_DETAILS"
406     fi
407     return 0
408   elif [[ "$1" =~ .*DALI.*[UPLOAD].*FrameBufferTexture\ (.*)\ GL\ Texture\ (.*)\ -\ size\ ([[:digit:]]*)\ bytes\ (.*) ]]
409   then
410     local FBTEXTURE="${BASH_REMATCH[1]}"
411     local TEXTURE="${BASH_REMATCH[2]}"
412     local SIZE="${BASH_REMATCH[3]}"
413     local SIZE_DETAILS="${BASH_REMATCH[4]}"
414     frameBufUploaded "$FBTEXTURE" "$TEXTURE" "$SIZE" "$SIZE_DETAILS"
415     return 0
416   else
417     echo "$1"
418     error "checkUploaded"
419   fi
420 }
421
422 function checkDeletedBuf
423 {
424   if [[ "$1" =~ .*DALI.*[DELBUF].*Bitmap\ (.*)\ -\ .*size\ (.*) ]]
425   then
426     local BITMAP=${BASH_REMATCH[1]}
427     local i=0
428
429     for bitmap in ${BITMAPS_G[@]}
430     do
431       if [ $bitmap == "$BITMAP" ]
432       then
433         case ${STATES_G[$i]} in
434         0)
435             STATES_G[$i]=3 #CPU->DISC
436             ;;
437         1)
438             STATES_G[$i]=2 #CPUGPU->GPU
439             ;;
440         2)
441             #GPU->?
442             #probably previously freed bitmap buffer but memory is reused since
443             ;;
444         3)
445             #DISC->?
446             #probably previously freed but memory is reused since
447             ;;
448         *)
449             error "checkDeletedBuf - unkown state"
450             ;;
451         esac
452       fi
453     let i+=1
454     done
455
456     return 0
457   else
458     echo "$1"
459     error "checkDeletedBuf"
460   fi
461 }
462
463 function checkDeletedTexture
464 {
465   if [[ "$1" =~ .*DALI.*[DELTEXTURE].*Texture\ (.*)\ -\ size\ (.*) ]]
466   then
467     local TEXTURE="${BASH_REMATCH[1]}"
468     local i=0
469     local lastIdx=-1
470
471     for texture in ${TEXTURES_G[@]}
472     do
473       if [ $texture == $TEXTURE ]
474       then
475         lastIdx=$i
476       fi
477     let i+=1
478     done
479
480     if [ $lastIdx != -1 ]
481     then
482       case ${STATES_G[$lastIdx]} in
483       0)
484           #CPU->?
485           echo "$1"
486           error "checkDeletedTexture - state CPU"
487           ;;
488       1)
489           STATES_G[$lastIdx]=0 #CPUGPU->CPU
490           ;;
491       2)
492           STATES_G[$lastIdx]=3 #GPU->DISC
493           ;;
494       3)
495           #DISC->?
496           echo "$1"
497           error "checkDeletedTexture - state DISC"
498           ;;
499       *)
500           error "checkDeletedTexture - unkown state"
501           ;;
502       esac
503     else
504       echo "$1"
505       error "checkDeletedTexture - texture not uploaded"
506     fi
507     return 0
508   else
509     echo "$1"
510     error "checkDeletedTexture"
511   fi
512 }
513
514 function processLine
515 {
516   if [[ "$1" =~ .*DALI.*\ \[(.*)\].* ]]
517   then
518     RESCMD=${BASH_REMATCH[1]}
519     case "$RESCMD" in
520     LOAD)
521         checkLoaded "$1"
522         ;;
523     UPLOAD)
524         checkUploaded "$1"
525         ;;
526     DELBUF)
527         checkDeletedBuf "$1"
528         ;;
529     DELTEXTURE)
530         checkDeletedTexture "$1"
531         ;;
532     INIT)
533         ;;
534     FIN)
535         return 1 #end of last log session
536         ;;
537     *)
538         error "Unkown command $RESCMD"
539         ;;
540     esac
541   fi
542   return 0
543 }
544
545 function parseFile
546 {
547   if [ -z "$1" ]
548   then
549     echo "ERROR in parseFile";
550     cleanup; exit 1
551   fi
552
553   #return if file does not contain dali resource log
554   if ! grep -q -m 1 -E "DALI.*\[INIT\]" $1
555   then
556     return 1
557   fi
558
559   #find last resource log session
560   local LOGBUFFER=$(sed -n 'H; /DALI.*\[INIT\]/h; ${g;p;}' $1)
561
562   while read -r line
563   do
564     #show PID of last process
565     PID_G=$(echo "$line" | sed 's/[^0-9]*\([0-9]*\).*/\1/')
566     if [ ! -z "$PID_G" ]
567     then
568       break
569     fi
570   done <<< "$LOGBUFFER"
571
572   while read -r line
573   do
574     if ! processLine "$line" #stop parsing at the end of last session
575     then
576       break
577     fi
578   done <<< "$LOGBUFFER"
579 }
580
581 ##################################draw and main functions
582 function redraw
583 {
584   tput cup 0 0 #move cursor to top left
585
586   # print info (4 lines)
587   tput bold
588   printLine "PID: $PID_G"
589   printLine "MEM 3D: $GPUMEM"
590   printLine "MEM Atlas: $ATLASMEM";
591   printLine "MEM CPU: $CPUMEM"
592   printLine "Number of atlases: $ATLAS_NO";
593   tput sgr0
594
595   # separator bar (colored bar with (actual/number of files) count)
596   tput cup $SEPARATOR_H 0
597   local PAGEIND="$(expr $CURPAGE + 1)/$(expr $MAXP + 1)"
598   local FILL_W=0
599   let FILL_W=$TERM_W-${#PAGEIND}
600   tput setab 4; printf $PAGEIND%"$FILL_W"s; printf '\n'; tput sgr0
601
602   # print filenames
603   local count=0
604   local index=0
605   let index=$CURPAGE*$MAXFILENO
606
607   filecount=${#FILENAMES_G[@]}
608
609   tput setaf 252
610
611   while [[ $count -lt $MAXFILENO ]]
612   do
613     if [[ $index -lt $filecount ]]
614     then
615       tput setab ${COLORS[${STATES_G[$index]}]}
616 #     printPath "${FILENAMES_G[$count]}"
617       printLine "${FILENAMES_G[$index]} ${SIZES_G[$index]} ${SIZE_DETAILS_G[$index]}"
618     else
619       tput sgr0
620       printLine "" #clear remaining lines to fill screen
621     fi
622     let count+=1
623     let index+=1
624   done
625
626   # print keyboard shortcuts
627   tput setab 4; tput bold
628   IFS= printString "  |  n: next page  |  p: previous page  |  ^C: exit  |  Resource state: "
629   # print color codes
630   if [[ $TERM_W -gt 100 ]]
631   then
632     tput setab ${COLORS[0]}
633     echo -n " CPU "
634     tput setab ${COLORS[1]}
635     echo -n " CPUGPU "
636     tput setab ${COLORS[2]}
637     echo -n " GPU "
638     tput setab ${COLORS[3]}
639     echo -n " DISCARDED "
640   fi
641
642   tput sgr0
643 }
644
645 function readInput
646 {
647     local key
648     read -n1 -t 0.3 key
649
650     case "$key" in
651         'p')
652             if [[ $CURPAGE -ne 0 ]]
653             then
654               let CURPAGE-=1
655             fi
656             ;;
657         'n')
658             if [[ $CURPAGE -lt $MAXP ]]
659             then
660               let CURPAGE+=1
661             fi
662             ;;
663     esac
664 }
665
666 function initVars
667 {
668   FILENAMES_G=( )
669   BITMAPS_G=( )
670   TEXTURES_G=( )
671   SIZES_G=( )
672   SIZE_DETAILS_G=( )
673   STATES_G=( )
674 }
675
676 function cleanup
677 {
678   tput cup 9999 0 #go to bottom of screen
679   tput cnorm #show cursor
680   tput sgr0
681   if [ -f "$DLOGTEMPFILE" ]
682   then
683     rm "$DLOGTEMPFILE"
684   fi
685 }
686
687 function update
688 {
689   initVars
690   if [ -n "$USING_DLOG" ]
691   then
692     if [ -f "$DLOGTEMPFILE" ]
693     then
694       rm "$DLOGTEMPFILE"
695     fi
696     "$DLOGUTIL" DALI:I -d -f "$DLOGTEMPFILE" 2>/dev/null
697   fi
698
699   if [ ! -e "$INPUTFILE" ]
700   then
701     return 1
702   fi
703
704   parseFile "$INPUTFILE"
705
706   if [[ $? -gt 0 || ${#STATES_G[@]} -lt 1 ]]
707   then
708     return 1
709   fi
710
711   getCpuMemUsage
712   getGpuMemUsage
713   getAtlasMemUsage
714   getAtlasNumber
715
716   getTermSize
717   readInput
718   redraw
719 }
720
721 function main
722 {
723   parseCmdLine $@
724
725   if [ -z "$INPUTFILE" ]
726   then
727     echo No input file specified;
728     cleanup
729     exit 1
730   fi
731
732   tput civis #hide cursor
733   tput clear #clear screen
734
735   echo "waiting for log..."
736
737   while [ 1 ]
738   do
739     update
740 #    sleep 0.3  # we are now reading input for 0.3
741   done
742
743   cleanup
744 }
745
746 trap "cleanup; exit 0" SIGINT SIGTERM  #reset terminal when ^C is pressed
747 # trap "getTermSize" SIGWINCH            #handle window resize
748
749 main $@