1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/libdisplay/GonkDisplayICS.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,233 @@ 1.4 +/* Copyright 2013 Mozilla Foundation and Mozilla contributors 1.5 + * 1.6 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.7 + * you may not use this file except in compliance with the License. 1.8 + * You may obtain a copy of the License at 1.9 + * 1.10 + * http://www.apache.org/licenses/LICENSE-2.0 1.11 + * 1.12 + * Unless required by applicable law or agreed to in writing, software 1.13 + * distributed under the License is distributed on an "AS IS" BASIS, 1.14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.15 + * See the License for the specific language governing permissions and 1.16 + * limitations under the License. 1.17 + */ 1.18 + 1.19 +#include "GonkDisplayICS.h" 1.20 +#include <ui/FramebufferNativeWindow.h> 1.21 + 1.22 +#include <hardware/hardware.h> 1.23 +#include <hardware/gralloc.h> 1.24 +#include <hardware/hwcomposer.h> 1.25 +#include <hardware_legacy/power.h> 1.26 +#include <cutils/log.h> 1.27 +#include <fcntl.h> 1.28 + 1.29 +#include "mozilla/FileUtils.h" 1.30 +#include "mozilla/NullPtr.h" 1.31 +#include "mozilla/FileUtils.h" 1.32 + 1.33 +#include "BootAnimation.h" 1.34 + 1.35 +using namespace android; 1.36 + 1.37 + 1.38 +namespace { 1.39 +static const char* kSleepFile = "/sys/power/wait_for_fb_sleep"; 1.40 +static const char* kWakeFile = "/sys/power/wait_for_fb_wake"; 1.41 +static mozilla::GonkDisplay::OnEnabledCallbackType sEnabledCallback; 1.42 +static pthread_t sFramebufferWatchThread; 1.43 + 1.44 +static void * 1.45 +frameBufferWatcher(void *) 1.46 +{ 1.47 + int len = 0; 1.48 + char buf; 1.49 + 1.50 + while (true) { 1.51 + // Cannot use epoll here because kSleepFile and kWakeFile are 1.52 + // always ready to read and blocking. 1.53 + { 1.54 + mozilla::ScopedClose fd(open(kSleepFile, O_RDONLY, 0)); 1.55 + do { 1.56 + len = read(fd.get(), &buf, 1); 1.57 + } while (len < 0 && errno == EINTR); 1.58 + NS_WARN_IF_FALSE(len >= 0, "WAIT_FOR_FB_SLEEP failed"); 1.59 + } 1.60 + sEnabledCallback(false); 1.61 + 1.62 + { 1.63 + mozilla::ScopedClose fd(open(kWakeFile, O_RDONLY, 0)); 1.64 + do { 1.65 + len = read(fd.get(), &buf, 1); 1.66 + } while (len < 0 && errno == EINTR); 1.67 + NS_WARN_IF_FALSE(len >= 0, "WAIT_FOR_FB_WAKE failed"); 1.68 + } 1.69 + sEnabledCallback(true); 1.70 + } 1.71 + 1.72 + return nullptr; 1.73 +} 1.74 + 1.75 +} // anonymous namespace 1.76 + 1.77 + 1.78 +namespace mozilla { 1.79 + 1.80 +static GonkDisplayICS* sGonkDisplay = nullptr; 1.81 + 1.82 +static int 1.83 +FramebufferNativeWindowCancelBufferNoop(ANativeWindow* aWindow, 1.84 + android_native_buffer_t* aBuffer) 1.85 +{ 1.86 + return 0; 1.87 +} 1.88 + 1.89 +GonkDisplayICS::GonkDisplayICS() 1.90 + : mModule(nullptr) 1.91 + , mHwc(nullptr) 1.92 +{ 1.93 + // Some gralloc HALs need this in order to open the 1.94 + // framebuffer device after we restart with the screen off. 1.95 + // 1.96 + // this *must* run BEFORE allocating the 1.97 + // FramebufferNativeWindow. 1.98 + set_screen_state(1); 1.99 + 1.100 + // For some devices, it takes a while for the framebuffer to become 1.101 + // usable. So we wait until the framebuffer has woken up before we 1.102 + // try to open it. 1.103 + { 1.104 + char buf; 1.105 + int len = 0; 1.106 + ScopedClose fd(open("/sys/power/wait_for_fb_wake", O_RDONLY, 0)); 1.107 + do { 1.108 + len = read(fd.get(), &buf, 1); 1.109 + } while (len < 0 && errno == EINTR); 1.110 + if (len < 0) { 1.111 + LOGE("BootAnimation: wait_for_fb_sleep failed errno: %d", errno); 1.112 + } 1.113 + } 1.114 + 1.115 + mFBSurface = new FramebufferNativeWindow(); 1.116 + 1.117 + // ICS FramebufferNativeWindow doesn't set the |cancelBuffer| 1.118 + // function pointer. 1.119 + // It will crash when deleting the EGL window surface. 1.120 + if (!mFBSurface->cancelBuffer) { 1.121 + mFBSurface->cancelBuffer = FramebufferNativeWindowCancelBufferNoop; 1.122 + } 1.123 + 1.124 + int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); 1.125 + LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); 1.126 + if (!err) { 1.127 + err = hwc_open(mModule, &mHwc); 1.128 + LOGE_IF(err, "%s device failed to initialize (%s)", 1.129 + HWC_HARDWARE_COMPOSER, strerror(-err)); 1.130 + } 1.131 + 1.132 + xdpi = mFBSurface->xdpi; 1.133 + 1.134 + const framebuffer_device_t *fbdev = mFBSurface->getDevice(); 1.135 + surfaceformat = fbdev->format; 1.136 + 1.137 + StartBootAnimation(); 1.138 +} 1.139 + 1.140 +GonkDisplayICS::~GonkDisplayICS() 1.141 +{ 1.142 + if (mHwc) 1.143 + hwc_close(mHwc); 1.144 +} 1.145 + 1.146 +ANativeWindow* 1.147 +GonkDisplayICS::GetNativeWindow() 1.148 +{ 1.149 + StopBootAnimation(); 1.150 + return static_cast<ANativeWindow *>(mFBSurface.get()); 1.151 +} 1.152 + 1.153 +void 1.154 +GonkDisplayICS::SetEnabled(bool enabled) 1.155 +{ 1.156 + set_screen_state(enabled); 1.157 +} 1.158 + 1.159 +void 1.160 +GonkDisplayICS::OnEnabled(OnEnabledCallbackType callback) 1.161 +{ 1.162 + if (sEnabledCallback) 1.163 + return; 1.164 + sEnabledCallback = callback; 1.165 + 1.166 + // Watching screen on/off state by using a pthread 1.167 + // which implicitly calls exit() when the main thread ends 1.168 + if (pthread_create(&sFramebufferWatchThread, NULL, frameBufferWatcher, NULL)) { 1.169 + NS_RUNTIMEABORT("Failed to create framebufferWatcherThread, aborting..."); 1.170 + } 1.171 +} 1.172 + 1.173 + 1.174 +void* 1.175 +GonkDisplayICS::GetHWCDevice() 1.176 +{ 1.177 + return mHwc; 1.178 +} 1.179 + 1.180 +void* 1.181 +GonkDisplayICS::GetFBSurface() 1.182 +{ 1.183 + return mFBSurface.get(); 1.184 +} 1.185 + 1.186 +bool 1.187 +GonkDisplayICS::SwapBuffers(EGLDisplay dpy, EGLSurface sur) 1.188 +{ 1.189 + // Should be called when composition rendering is complete for a frame. 1.190 + // Only HWC v1.0 needs this call. ICS gonk always needs the call. 1.191 + mFBSurface->compositionComplete(); 1.192 + 1.193 + if (!mHwc) 1.194 + return eglSwapBuffers(dpy, sur); 1.195 + 1.196 + mHwc->prepare(mHwc, nullptr); 1.197 + return !mHwc->set(mHwc, dpy, sur, 0); 1.198 +} 1.199 + 1.200 +ANativeWindowBuffer* 1.201 +GonkDisplayICS::DequeueBuffer() 1.202 +{ 1.203 + ANativeWindow *window = static_cast<ANativeWindow *>(mFBSurface.get()); 1.204 + ANativeWindowBuffer *buf = nullptr; 1.205 + window->dequeueBuffer(window, &buf); 1.206 + return buf; 1.207 +} 1.208 + 1.209 +bool 1.210 +GonkDisplayICS::QueueBuffer(ANativeWindowBuffer *buf) 1.211 +{ 1.212 + ANativeWindow *window = static_cast<ANativeWindow *>(mFBSurface.get()); 1.213 + return !window->queueBuffer(window, buf); 1.214 +} 1.215 + 1.216 +void 1.217 +GonkDisplayICS::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur) 1.218 +{ 1.219 + eglSwapBuffers(dpy, sur); 1.220 +} 1.221 + 1.222 +void 1.223 +GonkDisplayICS::SetFBReleaseFd(int fd) 1.224 +{ 1.225 +} 1.226 + 1.227 +__attribute__ ((visibility ("default"))) 1.228 +GonkDisplay* 1.229 +GetGonkDisplay() 1.230 +{ 1.231 + if (!sGonkDisplay) 1.232 + sGonkDisplay = new GonkDisplayICS(); 1.233 + return sGonkDisplay; 1.234 +} 1.235 + 1.236 +} // namespace mozilla