CMake: cleaned build of IpcModules
[profile/ivi/layer-management.git] / LayerManagerControl / src / analyze.cpp
1 /***************************************************************************
2  *
3  * Copyright 2012 BMW Car IT GmbH
4  *
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  ****************************************************************************/
19
20 #include "ilm_client.h"
21 #include "LMControl.h"
22
23 #include <algorithm>
24 using std::find;
25
26 #include <cstdio>
27
28 #include <iterator>
29 using std::iterator;
30
31 #include <iostream>
32 using std::cout;
33 using std::cin;
34 using std::endl;
35
36 #include <iomanip>
37 using std::dec;
38 using std::hex;
39 using std::left;
40 using std::right;
41 using std::setw;
42
43 #include <cmath>
44 using std::max;
45 using std::min;
46
47 #include <string>
48 using std::string;
49
50 #include <vector>
51 using std::vector;
52
53 namespace
54 {
55 void analyzePrintHelper(string tag, string flag, string description)
56 {
57     cout << left << setw(25) << tag << " | " << setw(7) << flag << " | " << description << endl;
58 }
59
60 void analyzeVisibilityAndOpacity(t_ilm_surface targetSurfaceId, t_scene_data& scene)
61 {
62     t_ilm_layer targetSurfaceLayer = scene.surfaceLayer[targetSurfaceId];
63     ilmSurfaceProperties& targetSurfaceProperties = scene.surfaceProperties[targetSurfaceId];
64     ilmLayerProperties& targetLayerProperties = scene.layerProperties[targetSurfaceLayer];
65     string tag;
66     string flag;
67     char description[300] = "";
68
69     //check visibility
70     tag = "Surface Visibility";
71     if (targetSurfaceProperties.visibility == ILM_FALSE)
72     {
73         flag = "PROBLEM";
74         sprintf(description, "Surface %i visibility set to false", targetSurfaceId);
75     }
76     else
77     {
78         flag = "OK";
79         sprintf(description, "%s", "");
80     }
81
82     analyzePrintHelper(tag, flag, description);
83
84     tag = "Layer Visibility";
85     if (targetLayerProperties.visibility == ILM_FALSE)
86     {
87         flag = "PROBLEM";
88         sprintf(description, "Layer %i visibility set to false.", targetSurfaceLayer);
89     }
90     else
91     {
92         flag = "OK";
93         sprintf(description, "%s", "");
94     }
95
96     analyzePrintHelper(tag, flag, description);
97
98     //check opacity
99     tag = "Surface Opacity";
100     if (targetSurfaceProperties.opacity <= 0.2)
101     {
102         flag = "PROBLEM";
103         sprintf(description, "Surface %i opacity set to %f, it is (almost) invisible", targetSurfaceId, targetSurfaceProperties.opacity);
104     }
105     else if (targetSurfaceProperties.opacity < 1.0)
106     {
107         flag = "WARNING";
108         sprintf(description, "Surface %i opacity set to %f, it might not be easy to see", targetSurfaceId, targetSurfaceProperties.opacity);
109     }
110     else
111     {
112         flag = "OK";
113         sprintf(description, "%s", "");
114     }
115
116     analyzePrintHelper(tag, flag, description);
117
118     tag = "Layer Opacity";
119     if (targetLayerProperties.opacity <= 0.2)
120     {
121         flag = "PROBLEM";
122         sprintf(description, "Layer %i opacity set to %f, it is (almost) invisible", targetSurfaceLayer, targetLayerProperties.opacity);
123     }
124     else if (targetLayerProperties.opacity < 1.0)
125     {
126         flag = "WARNING";
127         sprintf(description, "Layer %i opacity set to %f, it might not be easy to see", targetSurfaceLayer, targetLayerProperties.opacity);
128     }
129     else
130     {
131         flag = "OK";
132         sprintf(description, "%s", "");
133     }
134
135     analyzePrintHelper(tag, flag, description);
136 }
137
138 void analyzeSurfaceDimensions(t_ilm_surface targetSurfaceId, t_scene_data& scene)
139 {
140     ilmSurfaceProperties& targetSurfaceProperties = scene.surfaceProperties[targetSurfaceId];
141     string tag;
142     string flag;
143     char description[300] = "";
144
145     t_ilm_uint minDimension = 32;
146
147     tag = "Surface dest width";
148     if (targetSurfaceProperties.destWidth <= minDimension)
149     {
150         flag = "PROBLEM";
151         sprintf(description, "Surface %i has [destWidth=%i]", targetSurfaceId, targetSurfaceProperties.destWidth);
152     }
153     else
154     {
155         flag = "OK";
156         sprintf(description, "%s", "");
157     }
158
159     analyzePrintHelper(tag, flag, description);
160
161     tag = "Surface source width";
162     if (targetSurfaceProperties.sourceWidth <= minDimension)
163     {
164         flag = "PROBLEM";
165         sprintf(description, "Surface %i has [sourceWidth=%i]", targetSurfaceId, targetSurfaceProperties.sourceWidth);
166     }
167     else
168     {
169         flag = "OK";
170         sprintf(description, "%s", "");
171     }
172
173     analyzePrintHelper(tag, flag, description);
174
175     tag = "Surface original width";
176     if (targetSurfaceProperties.origSourceWidth <= minDimension)
177     {
178         flag = "PROBLEM";
179         sprintf(description, "Surface %i has [origSourceWidth=%i]", targetSurfaceId, targetSurfaceProperties.origSourceWidth);
180     }
181     else
182     {
183         flag = "OK";
184         sprintf(description, "%s", "");
185     }
186
187     analyzePrintHelper(tag, flag, description);
188
189     tag = "Surface dest height";
190     if (targetSurfaceProperties.destHeight <= minDimension)
191     {
192         flag = "PROBLEM";
193         sprintf(description, "Surface %i has [destHeight=%i]", targetSurfaceId, targetSurfaceProperties.destHeight);
194     }
195     else
196     {
197         flag = "OK";
198         sprintf(description, "%s", "");
199     }
200
201     analyzePrintHelper(tag, flag, description);
202
203     tag = "Surface source height";
204     if (targetSurfaceProperties.sourceHeight <= minDimension)
205     {
206         flag = "PROBLEM";
207         sprintf(description, "Surface %i has [sourceHeight=%i]", targetSurfaceId, targetSurfaceProperties.sourceHeight);
208     }
209     else
210     {
211         flag = "OK";
212         sprintf(description, "%s", "");
213     }
214
215     analyzePrintHelper(tag, flag, description);
216
217     tag = "Surface original height";
218     if (targetSurfaceProperties.origSourceHeight <= minDimension)
219     {
220         flag = "PROBLEM";
221         sprintf(description, "Surface %i has [origSourceHeight=%i]", targetSurfaceId, targetSurfaceProperties.origSourceHeight);
222     }
223     else
224     {
225         flag = "OK";
226         sprintf(description, "%s", "");
227     }
228
229     analyzePrintHelper(tag, flag, description);
230 }
231
232 void analyzeLayerDimensions(t_ilm_surface targetSurfaceId, t_scene_data& scene)
233 {
234     t_ilm_layer targetSurfaceLayer = scene.surfaceLayer[targetSurfaceId];
235     ilmLayerProperties& targetLayerProperties = scene.layerProperties[targetSurfaceLayer];
236     t_ilm_uint minDimension = 32;
237
238     string tag;
239     string flag;
240     char description[300] = "";
241     tag = "Layer dest width";
242     if (targetLayerProperties.destWidth <= minDimension)
243     {
244         flag = "PROBLEM";
245         sprintf(description, "Layer %i has [destWidth=%i]", targetSurfaceLayer, targetLayerProperties.destWidth);
246     }
247     else
248     {
249         flag = "OK";
250         sprintf(description, "%s", "");
251     }
252
253     analyzePrintHelper(tag, flag, description);
254
255     tag = "Layer source width";
256     if (targetLayerProperties.sourceWidth <= minDimension)
257     {
258         flag = "PROBLEM";
259         sprintf(description, "Layer %i has [sourceWidth=%i]", targetSurfaceLayer, targetLayerProperties.sourceWidth);
260     }
261     else
262     {
263         flag = "OK";
264         sprintf(description, "%s", "");
265     }
266
267     analyzePrintHelper(tag, flag, description);
268
269     tag = "Layer original width";
270     if (targetLayerProperties.origSourceWidth <= minDimension)
271     {
272         flag = "PROBLEM";
273         sprintf(description, "Layer %i has [origSourceWidth=%i]", targetSurfaceLayer, targetLayerProperties.origSourceWidth);
274     }
275     else
276     {
277         flag = "OK";
278         sprintf(description, "%s", "");
279     }
280
281     analyzePrintHelper(tag, flag, description);
282
283     tag = "Layer dest height";
284     if (targetLayerProperties.destHeight <= minDimension)
285     {
286         flag = "PROBLEM";
287         sprintf(description, "Layer %i has [destHeight=%i]", targetSurfaceLayer, targetLayerProperties.destHeight);
288     }
289     else
290     {
291         flag = "OK";
292         sprintf(description, "%s", "");
293     }
294
295     analyzePrintHelper(tag, flag, description);
296
297     tag = "Layer source height";
298     if (targetLayerProperties.sourceHeight <= minDimension)
299     {
300         flag = "PROBLEM";
301         sprintf(description, "Layer %i has [sourceHeight=%i]", targetSurfaceLayer, targetLayerProperties.sourceHeight);
302     }
303     else
304     {
305         flag = "OK";
306         sprintf(description, "%s", "");
307     }
308
309     analyzePrintHelper(tag, flag, description);
310
311     tag = "Layer original source";
312     if (targetLayerProperties.origSourceHeight <= minDimension)
313     {
314         flag = "PROBLEM";
315         sprintf(description, "Layer %i has [origSourceHeight=%i]", targetSurfaceLayer, targetLayerProperties.origSourceHeight);
316     }
317     else
318     {
319         flag = "OK";
320         sprintf(description, "%s", "");
321     }
322
323     analyzePrintHelper(tag, flag, description);
324 }
325
326 void analyzeDimensions(t_ilm_surface targetSurfaceId, t_scene_data& scene)
327 {
328     analyzeSurfaceDimensions(targetSurfaceId, scene);
329     analyzeLayerDimensions(targetSurfaceId, scene);
330 }
331
332 void analyzeSurfaceCheckInsideLayer(t_ilm_surface targetSurfaceId, t_scene_data& scene)
333 {
334     t_ilm_layer targetSurfaceLayer = scene.surfaceLayer[targetSurfaceId];
335     tuple4 targetSurfaceCoordinates = getSurfaceScreenCoordinates(&scene, targetSurfaceId);
336     ilmLayerProperties& targetLayerProperties = scene.layerProperties[targetSurfaceLayer];
337     string tag;
338     string flag;
339     char description[300] = "";
340
341     tuple4 layerCoordinates(targetLayerProperties.destX,
342             targetLayerProperties.destY,
343             targetLayerProperties.destX + targetLayerProperties.destWidth,
344             targetLayerProperties.destY + targetLayerProperties.destHeight);
345
346     tag = "Surface inside Layer";
347     if (!inside(targetSurfaceCoordinates, layerCoordinates))
348     {
349         flag = "PROBLEM";
350         sprintf(description, "Surface %i is not viewed completely insde the destination region of layer %i",
351                 targetSurfaceId, targetSurfaceLayer);
352     }
353     else
354     {
355         flag = "OK";
356         sprintf(description, "%s", "");
357     }
358
359     analyzePrintHelper(tag, flag, description);
360 }
361
362 void analyzeOcclusion(t_ilm_surface targetSurfaceId,
363         map<t_ilm_surface, t_ilm_layer>& surfaceLayers,
364         map<t_ilm_surface, ilmSurfaceProperties>& surfaceProperties,
365         map<t_ilm_layer, ilmLayerProperties>& layerProperties,
366         vector<t_ilm_surface>& allSurfaces, tuple4 targetSurfaceCoordinates)
367 {
368     string tag;
369     string flag;
370     char description[300] = "";
371
372     vector<t_ilm_surface> occludingSurfaces;
373
374     vector<t_ilm_surface>::iterator it = find(allSurfaces.begin(), allSurfaces.end(), targetSurfaceId);
375
376     t_ilm_bool occluded = ILM_FALSE;
377     tag = "Occlusion";
378     ++it;
379     for (; it != allSurfaces.end(); ++it)
380     {
381         t_ilm_surface surfaceId = *it;
382         t_ilm_layer surfaceLayer = surfaceLayers[surfaceId];
383
384         //if surface or layer invisible: neglect
385         if (layerProperties[surfaceLayer].visibility == ILM_FALSE || surfaceProperties[surfaceId].visibility == ILM_FALSE)
386             continue;
387
388         //if multiplication of their opacity is zero: neglect
389         if (layerProperties[surfaceLayer].opacity * surfaceProperties[surfaceId].opacity == 0)
390             continue;
391
392         //coordinates of the surface on screen
393         t_ilm_int horizontalScale = layerProperties[surfaceLayer].destWidth / layerProperties[surfaceLayer].sourceWidth;
394         t_ilm_int surfaceX1 = layerProperties[surfaceLayer].destX + horizontalScale
395                 * (surfaceProperties[surfaceId].destX - layerProperties[surfaceLayer].sourceX);
396         t_ilm_int surfaceX2 = surfaceX1 + horizontalScale * surfaceProperties[surfaceId].destWidth;
397
398         t_ilm_int verticalScale = layerProperties[surfaceLayer].destHeight / layerProperties[surfaceLayer].sourceHeight;
399         t_ilm_int surfaceY1 = layerProperties[surfaceLayer].destY + verticalScale
400                 * (surfaceProperties[surfaceId].destY - layerProperties[surfaceLayer].sourceY);
401         t_ilm_int surfaceY2 = surfaceY1 + verticalScale * surfaceProperties[surfaceId].destHeight;
402
403         tuple4 surfaceCoordinates(surfaceX1, surfaceY1, surfaceX2, surfaceY2);
404
405         //if the surface is completely occluded
406         if (inside(targetSurfaceCoordinates, surfaceCoordinates))
407         {
408             flag = "PROBLEM";
409             sprintf(description, "Surface %i is completely occluded by surface %i", targetSurfaceId, surfaceId);
410             analyzePrintHelper(tag, flag, description);
411
412             occluded = ILM_TRUE;
413         }
414         //if the surface is partially occluded
415         else if (intersect(targetSurfaceCoordinates, surfaceCoordinates))
416         {
417             flag = "PROBLEM";
418             sprintf(description, "Surface %i is partially occluded by surface %i", targetSurfaceId, surfaceId);
419             analyzePrintHelper(tag, flag, description);
420             occluded = ILM_TRUE;
421         }
422     }
423
424     if (!occluded)
425     {
426         flag = "OK";
427         sprintf(description, "%s", "");
428         analyzePrintHelper(tag, flag, description);
429     }
430 }
431
432 void analyzeOcclusion(t_ilm_surface targetSurfaceId, t_scene_data& scene)
433 {
434     string tag;
435     string flag;
436     char description[300] = "";
437
438     vector<t_ilm_surface> renderedSurfaces = getSceneRenderOrder(&scene);
439     vector<t_ilm_surface> occludingSurfaces;
440
441     vector<t_ilm_surface>::iterator it = find(renderedSurfaces.begin(), renderedSurfaces.end(), targetSurfaceId);
442
443     tuple4 targetSurfaceCoordinates = getSurfaceScreenCoordinates(&scene, targetSurfaceId);
444
445     t_ilm_bool occluded = ILM_FALSE;
446     tag = "Occlusion";
447     ++it;
448     for (; it != renderedSurfaces.end(); ++it)
449     {
450         t_ilm_surface surfaceId = *it;
451         t_ilm_layer surfaceLayer = scene.surfaceLayer[surfaceId];
452
453         //if surface or layer invisible: neglect
454         if (scene.layerProperties[surfaceLayer].visibility == ILM_FALSE || scene.surfaceProperties[surfaceId].visibility == ILM_FALSE)
455             continue;
456
457         //if multiplication of their opacity is zero: neglect
458         if (scene.layerProperties[surfaceLayer].opacity * scene.surfaceProperties[surfaceId].opacity == 0)
459             continue;
460
461         //coordinates of the surface on screen
462         tuple4 surfaceCoordinates = getSurfaceScreenCoordinates(&scene, surfaceId);
463
464         //if the surface is completely occluded
465         if (inside(targetSurfaceCoordinates, surfaceCoordinates))
466         {
467             flag = "PROBLEM";
468             sprintf(description, "Surface %i is completely occluded by surface %i", targetSurfaceId, surfaceId);
469             analyzePrintHelper(tag, flag, description);
470
471             occluded = ILM_TRUE;
472         }
473         //if the surface is partially occluded
474         else if (intersect(targetSurfaceCoordinates, surfaceCoordinates))
475         {
476             flag = "PROBLEM";
477             sprintf(description, "Surface %i is partially occluded by surface %i", targetSurfaceId, surfaceId);
478             analyzePrintHelper(tag, flag, description);
479             occluded = ILM_TRUE;
480         }
481     }
482
483     if (!occluded)
484     {
485         flag = "OK";
486         sprintf(description, "%s", "");
487         analyzePrintHelper(tag, flag, description);
488     }
489 }
490
491 t_ilm_bool analyzeCheckSurfaceExists(t_ilm_surface targetSurfaceId, t_scene_data& scene)
492 {
493     t_ilm_bool exists = ILM_FALSE;
494
495     string tag;
496     string flag;
497     char description[300] = "";
498
499     tag = "Surface existance";
500     //check if surface exists
501     if (find(scene.surfaces.begin(), scene.surfaces.end(), targetSurfaceId)
502             == scene.surfaces.end())
503     {
504         flag = "PROBLEM";
505         sprintf(description, "There is no surface with ID %i", targetSurfaceId);
506     }
507     else
508     {
509         exists = ILM_TRUE;
510         flag = "OK";
511         sprintf(description, "%s", "");
512     }
513
514     analyzePrintHelper(tag, flag, description);
515
516     return exists;
517 }
518
519 t_ilm_bool analyzeCheckRendered(t_ilm_surface targetSurfaceId, t_scene_data& scene)
520 {
521     t_ilm_bool onLayer = ILM_FALSE;
522     t_ilm_bool layerOnScreen = ILM_FALSE;
523     //is surface on layer?
524     map<t_ilm_surface, t_ilm_layer>::iterator surfaceLayerIt = scene.surfaceLayer.find(targetSurfaceId);
525
526     if (surfaceLayerIt != scene.surfaceLayer.end())
527     {
528         onLayer = ILM_TRUE;
529         t_ilm_layer layer = (*surfaceLayerIt).second;
530
531         //is layer on screen?
532         layerOnScreen = scene.layerScreen.find(layer) != scene.layerScreen.end();
533     }
534
535     //output
536     string tag;
537     string flag;
538     char description[300] = "";
539
540     tag = "Surface on layer";
541     if (!onLayer)
542     {
543         flag = "PROBLEM";
544         sprintf(description, "Surface %i is not on any layer", targetSurfaceId);
545     }
546     else
547     {
548         flag = "OK";
549         sprintf(description, "%s", "");
550     }
551
552     analyzePrintHelper(tag, flag, description);
553
554     if (onLayer)
555     {
556         tag = "Layer on screen";
557         if (!layerOnScreen)
558         {
559             flag = "PROBLEM";
560             sprintf(description, "Layer %i is not on any screen", scene.surfaceLayer[targetSurfaceId]);
561         }
562         else
563         {
564             flag = "OK";
565             sprintf(description, "%s", "");
566         }
567
568         analyzePrintHelper(tag, flag, description);
569     }
570
571     return onLayer && layerOnScreen;
572 }
573
574 t_ilm_bool analyzeSharedNative(t_ilm_surface targetSurfaceId, t_scene_data& scene)
575 {
576     string tag;
577     string flag;
578     char description[300] = "";
579
580     tag = "Shared native";
581
582     t_ilm_bool shared = ILM_FALSE;
583
584     //native of the target surface
585     t_ilm_uint targetNative = scene.surfaceProperties[targetSurfaceId].nativeSurface;
586
587     //iterate all surface properties
588     for (map<t_ilm_surface, ilmSurfaceProperties>::iterator it = scene.surfaceProperties.begin();
589             it != scene.surfaceProperties.end(); ++it)
590     {
591         t_ilm_surface surface = (*it).first;
592         ilmSurfaceProperties& properties = (*it).second;
593         //if there is a surface that has the same surface as the target surface
594         if (surface != targetSurfaceId && properties.nativeSurface == targetNative)
595         {
596             shared = ILM_TRUE;
597
598             flag = "WARNING";
599             sprintf(description, "Surface %i shares native that has ID %i with surface %i",
600                     targetSurfaceId, targetNative, surface);
601             analyzePrintHelper(tag, flag, description);
602         }
603     }
604
605     if (!shared)
606     {
607         flag = "OK";
608         sprintf(description, "%s", "");
609         analyzePrintHelper(tag, flag, description);
610     }
611
612     return !shared;
613 }
614
615 t_ilm_bool analyzeUpdateCounter(t_ilm_surface targetSurfaceId, t_scene_data& scene)
616 {
617     ilmSurfaceProperties& targetSurfaceProperties = scene.surfaceProperties[targetSurfaceId];
618
619     t_ilm_bool problem = targetSurfaceProperties.updateCounter == 0;
620     string tag;
621     string flag;
622     char description[300] = "";
623
624     tag = "Update Counter";
625     //check if surface counter was updated since its creation
626     if (problem)
627     {
628         flag = "PROBLEM";
629         sprintf(description, "Surface %i update counter is %i, no content was added to the surface since its creation",
630                 targetSurfaceId, targetSurfaceProperties.updateCounter);
631     }
632     else
633     {
634         flag = "OK";
635         sprintf(description, "%s", "");
636     }
637
638     analyzePrintHelper(tag, flag, description);
639
640     return !problem;
641 }
642 } //end of anonymous namespace
643
644
645 t_ilm_bool analyzeSurface(t_ilm_surface targetSurfaceId)
646 {
647     t_scene_data scene;
648     captureSceneData(&scene);
649
650     if (!analyzeCheckSurfaceExists(targetSurfaceId, scene))
651         return ILM_TRUE;
652
653     if (!analyzeCheckRendered(targetSurfaceId, scene))
654         return ILM_TRUE;
655
656     //check no visibility or low opacity
657     analyzeVisibilityAndOpacity(targetSurfaceId, scene);
658
659     //check small dimensions
660     analyzeDimensions(targetSurfaceId, scene);
661
662     //check if surface is completely inside the destination region of the layer
663     analyzeSurfaceCheckInsideLayer(targetSurfaceId, scene);
664
665     //get occluding visible surfaces
666     analyzeOcclusion(targetSurfaceId, scene);
667
668     //check if the surface has been updated (if it has any content)
669     analyzeUpdateCounter(targetSurfaceId, scene);
670
671     //check if the surface shares the native with another surface
672     analyzeSharedNative(targetSurfaceId, scene);
673
674     return ILM_TRUE;
675 }