1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,322 @@ 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 "GonkDisplayJB.h" 1.20 +#if ANDROID_VERSION == 17 1.21 +#include <gui/SurfaceTextureClient.h> 1.22 +#else 1.23 +#include <gui/Surface.h> 1.24 +#include <gui/GraphicBufferAlloc.h> 1.25 +#endif 1.26 + 1.27 +#include <hardware/hardware.h> 1.28 +#include <hardware/hwcomposer.h> 1.29 +#include <hardware/power.h> 1.30 +#include <suspend/autosuspend.h> 1.31 + 1.32 +#if ANDROID_VERSION == 17 1.33 +#include "GraphicBufferAlloc.h" 1.34 +#endif 1.35 +#include "BootAnimation.h" 1.36 + 1.37 +using namespace android; 1.38 + 1.39 +namespace mozilla { 1.40 + 1.41 +static GonkDisplayJB* sGonkDisplay = nullptr; 1.42 + 1.43 +GonkDisplayJB::GonkDisplayJB() 1.44 + : mList(nullptr) 1.45 + , mModule(nullptr) 1.46 + , mFBModule(nullptr) 1.47 + , mHwc(nullptr) 1.48 + , mFBDevice(nullptr) 1.49 + , mEnabledCallback(nullptr) 1.50 + , mPowerModule(nullptr) 1.51 +{ 1.52 + int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mFBModule); 1.53 + ALOGW_IF(err, "%s module not found", GRALLOC_HARDWARE_MODULE_ID); 1.54 + if (!err) { 1.55 + err = framebuffer_open(mFBModule, &mFBDevice); 1.56 + ALOGW_IF(err, "could not open framebuffer"); 1.57 + } 1.58 + 1.59 + if (!err && mFBDevice) { 1.60 + mWidth = mFBDevice->width; 1.61 + mHeight = mFBDevice->height; 1.62 + xdpi = mFBDevice->xdpi; 1.63 + /* The emulator actually reports RGBA_8888, but EGL doesn't return 1.64 + * any matching configuration. We force RGBX here to fix it. */ 1.65 + surfaceformat = HAL_PIXEL_FORMAT_RGBX_8888; 1.66 + } 1.67 + 1.68 + err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); 1.69 + ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); 1.70 + if (!err) { 1.71 + err = hwc_open_1(mModule, &mHwc); 1.72 + ALOGE_IF(err, "%s device failed to initialize (%s)", 1.73 + HWC_HARDWARE_COMPOSER, strerror(-err)); 1.74 + } 1.75 + 1.76 + /* Fallback on the FB rendering path instead of trying to support HWC 1.0 */ 1.77 + if (!err && mHwc->common.version == HWC_DEVICE_API_VERSION_1_0) { 1.78 + hwc_close_1(mHwc); 1.79 + mHwc = nullptr; 1.80 + } 1.81 + 1.82 + if (!err && mHwc) { 1.83 + if (mFBDevice) { 1.84 + framebuffer_close(mFBDevice); 1.85 + mFBDevice = nullptr; 1.86 + } 1.87 + 1.88 + int32_t values[3]; 1.89 + const uint32_t attrs[] = { 1.90 + HWC_DISPLAY_WIDTH, 1.91 + HWC_DISPLAY_HEIGHT, 1.92 + HWC_DISPLAY_DPI_X, 1.93 + HWC_DISPLAY_NO_ATTRIBUTE 1.94 + }; 1.95 + mHwc->getDisplayAttributes(mHwc, 0, 0, attrs, values); 1.96 + 1.97 + mWidth = values[0]; 1.98 + mHeight = values[1]; 1.99 + xdpi = values[2] / 1000.0f; 1.100 + surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888; 1.101 + } 1.102 + 1.103 + err = hw_get_module(POWER_HARDWARE_MODULE_ID, 1.104 + (hw_module_t const**)&mPowerModule); 1.105 + if (!err) 1.106 + mPowerModule->init(mPowerModule); 1.107 + ALOGW_IF(err, "Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err)); 1.108 + 1.109 + mAlloc = new GraphicBufferAlloc(); 1.110 + 1.111 + status_t error; 1.112 + uint32_t usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER; 1.113 + mBootAnimBuffer = mAlloc->createGraphicBuffer(mWidth, mHeight, surfaceformat, usage, &error); 1.114 + if (error != NO_ERROR || !mBootAnimBuffer.get()) { 1.115 + ALOGI("Trying to create BRGA format framebuffer"); 1.116 + surfaceformat = HAL_PIXEL_FORMAT_BGRA_8888; 1.117 + mBootAnimBuffer = mAlloc->createGraphicBuffer(mWidth, mHeight, surfaceformat, usage, &error); 1.118 + } 1.119 + 1.120 +#if ANDROID_VERSION >= 19 1.121 + sp<BufferQueue> bq = new BufferQueue(mAlloc); 1.122 +#else 1.123 + sp<BufferQueue> bq = new BufferQueue(true, mAlloc); 1.124 +#endif 1.125 + mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, bq); 1.126 + 1.127 +#if ANDROID_VERSION == 17 1.128 + sp<SurfaceTextureClient> stc = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(mFBSurface->getBufferQueue())); 1.129 +#else 1.130 + sp<Surface> stc = new Surface(static_cast<sp<IGraphicBufferProducer> >(bq)); 1.131 +#endif 1.132 + mSTClient = stc; 1.133 + 1.134 + mList = (hwc_display_contents_1_t *)malloc(sizeof(*mList) + (sizeof(hwc_layer_1_t)*2)); 1.135 + if (mHwc) 1.136 + mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0); 1.137 + 1.138 + if (error == NO_ERROR && mBootAnimBuffer.get()) { 1.139 + ALOGI("Starting bootanimation with (%d) format framebuffer", surfaceformat); 1.140 + StartBootAnimation(); 1.141 + } else 1.142 + ALOGW("Couldn't show bootanimation (%s)", strerror(-error)); 1.143 +} 1.144 + 1.145 +GonkDisplayJB::~GonkDisplayJB() 1.146 +{ 1.147 + if (mHwc) 1.148 + hwc_close_1(mHwc); 1.149 + if (mFBDevice) 1.150 + framebuffer_close(mFBDevice); 1.151 + free(mList); 1.152 +} 1.153 + 1.154 +ANativeWindow* 1.155 +GonkDisplayJB::GetNativeWindow() 1.156 +{ 1.157 + return mSTClient.get(); 1.158 +} 1.159 + 1.160 +void 1.161 +GonkDisplayJB::SetEnabled(bool enabled) 1.162 +{ 1.163 + if (enabled) { 1.164 + autosuspend_disable(); 1.165 + mPowerModule->setInteractive(mPowerModule, true); 1.166 + } 1.167 + 1.168 + if (mHwc) 1.169 + mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, !enabled); 1.170 + else if (mFBDevice->enableScreen) 1.171 + mFBDevice->enableScreen(mFBDevice, enabled); 1.172 + 1.173 + if (mEnabledCallback) 1.174 + mEnabledCallback(enabled); 1.175 + 1.176 + if (!enabled) { 1.177 + autosuspend_enable(); 1.178 + mPowerModule->setInteractive(mPowerModule, false); 1.179 + } 1.180 +} 1.181 + 1.182 +void 1.183 +GonkDisplayJB::OnEnabled(OnEnabledCallbackType callback) 1.184 +{ 1.185 + mEnabledCallback = callback; 1.186 +} 1.187 + 1.188 +void* 1.189 +GonkDisplayJB::GetHWCDevice() 1.190 +{ 1.191 + return mHwc; 1.192 +} 1.193 + 1.194 +void* 1.195 +GonkDisplayJB::GetFBSurface() 1.196 +{ 1.197 + return mFBSurface.get(); 1.198 +} 1.199 + 1.200 +bool 1.201 +GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur) 1.202 +{ 1.203 + StopBootAnimation(); 1.204 + mBootAnimBuffer = nullptr; 1.205 + 1.206 + // Should be called when composition rendering is complete for a frame. 1.207 + // Only HWC v1.0 needs this call. 1.208 + // HWC > v1.0 case, do not call compositionComplete(). 1.209 + // mFBDevice is present only when HWC is v1.0. 1.210 + if (mFBDevice && mFBDevice->compositionComplete) { 1.211 + mFBDevice->compositionComplete(mFBDevice); 1.212 + } 1.213 + 1.214 +#if ANDROID_VERSION == 17 1.215 + mList->dpy = dpy; 1.216 + mList->sur = sur; 1.217 +#else 1.218 + mList->outbuf = nullptr; 1.219 + mList->outbufAcquireFenceFd = -1; 1.220 +#endif 1.221 + eglSwapBuffers(dpy, sur); 1.222 + return Post(mFBSurface->lastHandle, mFBSurface->GetPrevFBAcquireFd()); 1.223 +} 1.224 + 1.225 +bool 1.226 +GonkDisplayJB::Post(buffer_handle_t buf, int fence) 1.227 +{ 1.228 + if (!mHwc) { 1.229 + if (fence >= 0) 1.230 + close(fence); 1.231 + return !mFBDevice->post(mFBDevice, buf); 1.232 + } 1.233 + 1.234 + hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = {NULL}; 1.235 + const hwc_rect_t r = { 0, 0, mWidth, mHeight }; 1.236 + displays[HWC_DISPLAY_PRIMARY] = mList; 1.237 + mList->retireFenceFd = -1; 1.238 + mList->numHwLayers = 2; 1.239 + mList->flags = HWC_GEOMETRY_CHANGED; 1.240 + mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER; 1.241 + mList->hwLayers[0].hints = 0; 1.242 + /* Skip this layer so the hwc module doesn't complain about null handles */ 1.243 + mList->hwLayers[0].flags = HWC_SKIP_LAYER; 1.244 + mList->hwLayers[0].backgroundColor = {0}; 1.245 + mList->hwLayers[0].acquireFenceFd = -1; 1.246 + mList->hwLayers[0].releaseFenceFd = -1; 1.247 + /* hwc module checks displayFrame even though it shouldn't */ 1.248 + mList->hwLayers[0].displayFrame = r; 1.249 + mList->hwLayers[1].compositionType = HWC_FRAMEBUFFER_TARGET; 1.250 + mList->hwLayers[1].hints = 0; 1.251 + mList->hwLayers[1].flags = 0; 1.252 + mList->hwLayers[1].handle = buf; 1.253 + mList->hwLayers[1].transform = 0; 1.254 + mList->hwLayers[1].blending = HWC_BLENDING_PREMULT; 1.255 +#if ANDROID_VERSION >= 19 1.256 + if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_3) { 1.257 + mList->hwLayers[1].sourceCropf.left = 0; 1.258 + mList->hwLayers[1].sourceCropf.top = 0; 1.259 + mList->hwLayers[1].sourceCropf.right = mWidth; 1.260 + mList->hwLayers[1].sourceCropf.bottom = mHeight; 1.261 + } else { 1.262 + mList->hwLayers[1].sourceCrop = r; 1.263 + } 1.264 +#else 1.265 + mList->hwLayers[1].sourceCrop = r; 1.266 +#endif 1.267 + mList->hwLayers[1].displayFrame = r; 1.268 + mList->hwLayers[1].visibleRegionScreen.numRects = 1; 1.269 + mList->hwLayers[1].visibleRegionScreen.rects = &mList->hwLayers[1].displayFrame; 1.270 + mList->hwLayers[1].acquireFenceFd = fence; 1.271 + mList->hwLayers[1].releaseFenceFd = -1; 1.272 +#if ANDROID_VERSION == 18 1.273 + mList->hwLayers[1].planeAlpha = 0xFF; 1.274 +#endif 1.275 + mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays); 1.276 + int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays); 1.277 + mFBSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd); 1.278 + if (mList->retireFenceFd >= 0) 1.279 + close(mList->retireFenceFd); 1.280 + return !err; 1.281 +} 1.282 + 1.283 +ANativeWindowBuffer* 1.284 +GonkDisplayJB::DequeueBuffer() 1.285 +{ 1.286 + return static_cast<ANativeWindowBuffer*>(mBootAnimBuffer.get()); 1.287 +} 1.288 + 1.289 +bool 1.290 +GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf) 1.291 +{ 1.292 + bool success = Post(buf->handle, -1); 1.293 + return success; 1.294 +} 1.295 + 1.296 +void 1.297 +GonkDisplayJB::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur) 1.298 +{ 1.299 + StopBootAnimation(); 1.300 + mBootAnimBuffer = nullptr; 1.301 + eglSwapBuffers(dpy, sur); 1.302 +} 1.303 + 1.304 +void 1.305 +GonkDisplayJB::SetFBReleaseFd(int fd) 1.306 +{ 1.307 + mFBSurface->setReleaseFenceFd(fd); 1.308 +} 1.309 + 1.310 +int 1.311 +GonkDisplayJB::GetPrevFBAcquireFd() 1.312 +{ 1.313 + return mFBSurface->GetPrevFBAcquireFd(); 1.314 +} 1.315 + 1.316 +__attribute__ ((visibility ("default"))) 1.317 +GonkDisplay* 1.318 +GetGonkDisplay() 1.319 +{ 1.320 + if (!sGonkDisplay) 1.321 + sGonkDisplay = new GonkDisplayJB(); 1.322 + return sGonkDisplay; 1.323 +} 1.324 + 1.325 +} // namespace mozilla