1/*
2// Copyright (c) 2014 Intel Corporation 
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include <common/utils/HwcTrace.h>
18#include <Hwcomposer.h>
19#include <common/base/DisplayAnalyzer.h>
20
21namespace android {
22namespace intel {
23
24DisplayAnalyzer::DisplayAnalyzer()
25    : mInitialized(false),
26      mCachedNumDisplays(0),
27      mCachedDisplays(0),
28      mPendingEvents(),
29      mEventMutex()
30{
31}
32
33DisplayAnalyzer::~DisplayAnalyzer()
34{
35}
36
37bool DisplayAnalyzer::initialize()
38{
39    mCachedNumDisplays = 0;
40    mCachedDisplays = 0;
41    mPendingEvents.clear();
42    mInitialized = true;
43
44    return true;
45}
46
47void DisplayAnalyzer::deinitialize()
48{
49    mPendingEvents.clear();
50    mInitialized = false;
51}
52
53void DisplayAnalyzer::analyzeContents(
54        size_t numDisplays, hwc_display_contents_1_t** displays)
55{
56    // cache and use them only in this context during analysis
57    mCachedNumDisplays = numDisplays;
58    mCachedDisplays = displays;
59
60    handlePendingEvents();
61}
62
63void DisplayAnalyzer::postHotplugEvent(bool connected)
64{
65    // handle hotplug event (vsync switch) asynchronously
66    Event e;
67    e.type = HOTPLUG_EVENT;
68    e.bValue = connected;
69    postEvent(e);
70    Hwcomposer::getInstance().invalidate();
71}
72
73void DisplayAnalyzer::postEvent(Event& e)
74{
75    Mutex::Autolock lock(mEventMutex);
76    mPendingEvents.add(e);
77}
78
79bool DisplayAnalyzer::getEvent(Event& e)
80{
81    Mutex::Autolock lock(mEventMutex);
82    if (mPendingEvents.size() == 0) {
83        return false;
84    }
85    e = mPendingEvents[0];
86    mPendingEvents.removeAt(0);
87    return true;
88}
89
90void DisplayAnalyzer::handlePendingEvents()
91{
92    // handle one event per analysis to avoid blocking surface flinger
93    // some event may take lengthy time to process
94    Event e;
95    if (!getEvent(e)) {
96        return;
97    }
98
99    switch (e.type) {
100    case HOTPLUG_EVENT:
101        handleHotplugEvent(e.bValue);
102        break;
103    }
104}
105
106void DisplayAnalyzer::handleHotplugEvent(bool connected)
107{
108    if (connected) {
109        for (int i = 0; i < mCachedNumDisplays; i++) {
110            setCompositionType(i, HWC_FRAMEBUFFER, true);
111        }
112    }
113}
114
115void DisplayAnalyzer::setCompositionType(hwc_display_contents_1_t *display, int type)
116{
117    for (size_t i = 0; i < display->numHwLayers - 1; i++) {
118        hwc_layer_1_t *layer = &display->hwLayers[i];
119        if (layer) layer->compositionType = type;
120    }
121}
122
123void DisplayAnalyzer::setCompositionType(int device, int type, bool reset)
124{
125    hwc_display_contents_1_t *content = mCachedDisplays[device];
126    if (content == NULL) {
127        ELOGTRACE("Invalid device %d", device);
128        return;
129    }
130
131    // don't need to set geometry changed if layers are just needed to be marked
132    if (reset) {
133        content->flags |= HWC_GEOMETRY_CHANGED;
134    }
135
136    setCompositionType(content, type);
137}
138
139} // namespace intel
140} // namespace android
141
142