/* // Copyright (c) 2014 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #include <common/utils/HwcTrace.h> #include <Hwcomposer.h> #include <common/base/DisplayAnalyzer.h> namespace android { namespace intel { DisplayAnalyzer::DisplayAnalyzer() : mInitialized(false), mCachedNumDisplays(0), mCachedDisplays(0), mPendingEvents(), mEventMutex() { } DisplayAnalyzer::~DisplayAnalyzer() { } bool DisplayAnalyzer::initialize() { mCachedNumDisplays = 0; mCachedDisplays = 0; mPendingEvents.clear(); mInitialized = true; return true; } void DisplayAnalyzer::deinitialize() { mPendingEvents.clear(); mInitialized = false; } void DisplayAnalyzer::analyzeContents( size_t numDisplays, hwc_display_contents_1_t** displays) { // cache and use them only in this context during analysis mCachedNumDisplays = numDisplays; mCachedDisplays = displays; handlePendingEvents(); } void DisplayAnalyzer::postHotplugEvent(bool connected) { // handle hotplug event (vsync switch) asynchronously Event e; e.type = HOTPLUG_EVENT; e.bValue = connected; postEvent(e); Hwcomposer::getInstance().invalidate(); } void DisplayAnalyzer::postEvent(Event& e) { Mutex::Autolock lock(mEventMutex); mPendingEvents.add(e); } bool DisplayAnalyzer::getEvent(Event& e) { Mutex::Autolock lock(mEventMutex); if (mPendingEvents.size() == 0) { return false; } e = mPendingEvents[0]; mPendingEvents.removeAt(0); return true; } void DisplayAnalyzer::handlePendingEvents() { // handle one event per analysis to avoid blocking surface flinger // some event may take lengthy time to process Event e; if (!getEvent(e)) { return; } switch (e.type) { case HOTPLUG_EVENT: handleHotplugEvent(e.bValue); break; } } void DisplayAnalyzer::handleHotplugEvent(bool connected) { if (connected) { for (int i = 0; i < mCachedNumDisplays; i++) { setCompositionType(i, HWC_FRAMEBUFFER, true); } } } void DisplayAnalyzer::setCompositionType(hwc_display_contents_1_t *display, int type) { for (size_t i = 0; i < display->numHwLayers - 1; i++) { hwc_layer_1_t *layer = &display->hwLayers[i]; if (layer) layer->compositionType = type; } } void DisplayAnalyzer::setCompositionType(int device, int type, bool reset) { hwc_display_contents_1_t *content = mCachedDisplays[device]; if (content == NULL) { ELOGTRACE("Invalid device %d", device); return; } // don't need to set geometry changed if layers are just needed to be marked if (reset) { content->flags |= HWC_GEOMETRY_CHANGED; } setCompositionType(content, type); } } // namespace intel } // namespace android