widget/gonk/libdisplay/GonkDisplayJB.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* Copyright 2013 Mozilla Foundation and Mozilla contributors
michael@0 2 *
michael@0 3 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 4 * you may not use this file except in compliance with the License.
michael@0 5 * You may obtain a copy of the License at
michael@0 6 *
michael@0 7 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 8 *
michael@0 9 * Unless required by applicable law or agreed to in writing, software
michael@0 10 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 12 * See the License for the specific language governing permissions and
michael@0 13 * limitations under the License.
michael@0 14 */
michael@0 15
michael@0 16 #include "GonkDisplayJB.h"
michael@0 17 #if ANDROID_VERSION == 17
michael@0 18 #include <gui/SurfaceTextureClient.h>
michael@0 19 #else
michael@0 20 #include <gui/Surface.h>
michael@0 21 #include <gui/GraphicBufferAlloc.h>
michael@0 22 #endif
michael@0 23
michael@0 24 #include <hardware/hardware.h>
michael@0 25 #include <hardware/hwcomposer.h>
michael@0 26 #include <hardware/power.h>
michael@0 27 #include <suspend/autosuspend.h>
michael@0 28
michael@0 29 #if ANDROID_VERSION == 17
michael@0 30 #include "GraphicBufferAlloc.h"
michael@0 31 #endif
michael@0 32 #include "BootAnimation.h"
michael@0 33
michael@0 34 using namespace android;
michael@0 35
michael@0 36 namespace mozilla {
michael@0 37
michael@0 38 static GonkDisplayJB* sGonkDisplay = nullptr;
michael@0 39
michael@0 40 GonkDisplayJB::GonkDisplayJB()
michael@0 41 : mList(nullptr)
michael@0 42 , mModule(nullptr)
michael@0 43 , mFBModule(nullptr)
michael@0 44 , mHwc(nullptr)
michael@0 45 , mFBDevice(nullptr)
michael@0 46 , mEnabledCallback(nullptr)
michael@0 47 , mPowerModule(nullptr)
michael@0 48 {
michael@0 49 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mFBModule);
michael@0 50 ALOGW_IF(err, "%s module not found", GRALLOC_HARDWARE_MODULE_ID);
michael@0 51 if (!err) {
michael@0 52 err = framebuffer_open(mFBModule, &mFBDevice);
michael@0 53 ALOGW_IF(err, "could not open framebuffer");
michael@0 54 }
michael@0 55
michael@0 56 if (!err && mFBDevice) {
michael@0 57 mWidth = mFBDevice->width;
michael@0 58 mHeight = mFBDevice->height;
michael@0 59 xdpi = mFBDevice->xdpi;
michael@0 60 /* The emulator actually reports RGBA_8888, but EGL doesn't return
michael@0 61 * any matching configuration. We force RGBX here to fix it. */
michael@0 62 surfaceformat = HAL_PIXEL_FORMAT_RGBX_8888;
michael@0 63 }
michael@0 64
michael@0 65 err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
michael@0 66 ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
michael@0 67 if (!err) {
michael@0 68 err = hwc_open_1(mModule, &mHwc);
michael@0 69 ALOGE_IF(err, "%s device failed to initialize (%s)",
michael@0 70 HWC_HARDWARE_COMPOSER, strerror(-err));
michael@0 71 }
michael@0 72
michael@0 73 /* Fallback on the FB rendering path instead of trying to support HWC 1.0 */
michael@0 74 if (!err && mHwc->common.version == HWC_DEVICE_API_VERSION_1_0) {
michael@0 75 hwc_close_1(mHwc);
michael@0 76 mHwc = nullptr;
michael@0 77 }
michael@0 78
michael@0 79 if (!err && mHwc) {
michael@0 80 if (mFBDevice) {
michael@0 81 framebuffer_close(mFBDevice);
michael@0 82 mFBDevice = nullptr;
michael@0 83 }
michael@0 84
michael@0 85 int32_t values[3];
michael@0 86 const uint32_t attrs[] = {
michael@0 87 HWC_DISPLAY_WIDTH,
michael@0 88 HWC_DISPLAY_HEIGHT,
michael@0 89 HWC_DISPLAY_DPI_X,
michael@0 90 HWC_DISPLAY_NO_ATTRIBUTE
michael@0 91 };
michael@0 92 mHwc->getDisplayAttributes(mHwc, 0, 0, attrs, values);
michael@0 93
michael@0 94 mWidth = values[0];
michael@0 95 mHeight = values[1];
michael@0 96 xdpi = values[2] / 1000.0f;
michael@0 97 surfaceformat = HAL_PIXEL_FORMAT_RGBA_8888;
michael@0 98 }
michael@0 99
michael@0 100 err = hw_get_module(POWER_HARDWARE_MODULE_ID,
michael@0 101 (hw_module_t const**)&mPowerModule);
michael@0 102 if (!err)
michael@0 103 mPowerModule->init(mPowerModule);
michael@0 104 ALOGW_IF(err, "Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
michael@0 105
michael@0 106 mAlloc = new GraphicBufferAlloc();
michael@0 107
michael@0 108 status_t error;
michael@0 109 uint32_t usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
michael@0 110 mBootAnimBuffer = mAlloc->createGraphicBuffer(mWidth, mHeight, surfaceformat, usage, &error);
michael@0 111 if (error != NO_ERROR || !mBootAnimBuffer.get()) {
michael@0 112 ALOGI("Trying to create BRGA format framebuffer");
michael@0 113 surfaceformat = HAL_PIXEL_FORMAT_BGRA_8888;
michael@0 114 mBootAnimBuffer = mAlloc->createGraphicBuffer(mWidth, mHeight, surfaceformat, usage, &error);
michael@0 115 }
michael@0 116
michael@0 117 #if ANDROID_VERSION >= 19
michael@0 118 sp<BufferQueue> bq = new BufferQueue(mAlloc);
michael@0 119 #else
michael@0 120 sp<BufferQueue> bq = new BufferQueue(true, mAlloc);
michael@0 121 #endif
michael@0 122 mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, bq);
michael@0 123
michael@0 124 #if ANDROID_VERSION == 17
michael@0 125 sp<SurfaceTextureClient> stc = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(mFBSurface->getBufferQueue()));
michael@0 126 #else
michael@0 127 sp<Surface> stc = new Surface(static_cast<sp<IGraphicBufferProducer> >(bq));
michael@0 128 #endif
michael@0 129 mSTClient = stc;
michael@0 130
michael@0 131 mList = (hwc_display_contents_1_t *)malloc(sizeof(*mList) + (sizeof(hwc_layer_1_t)*2));
michael@0 132 if (mHwc)
michael@0 133 mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0);
michael@0 134
michael@0 135 if (error == NO_ERROR && mBootAnimBuffer.get()) {
michael@0 136 ALOGI("Starting bootanimation with (%d) format framebuffer", surfaceformat);
michael@0 137 StartBootAnimation();
michael@0 138 } else
michael@0 139 ALOGW("Couldn't show bootanimation (%s)", strerror(-error));
michael@0 140 }
michael@0 141
michael@0 142 GonkDisplayJB::~GonkDisplayJB()
michael@0 143 {
michael@0 144 if (mHwc)
michael@0 145 hwc_close_1(mHwc);
michael@0 146 if (mFBDevice)
michael@0 147 framebuffer_close(mFBDevice);
michael@0 148 free(mList);
michael@0 149 }
michael@0 150
michael@0 151 ANativeWindow*
michael@0 152 GonkDisplayJB::GetNativeWindow()
michael@0 153 {
michael@0 154 return mSTClient.get();
michael@0 155 }
michael@0 156
michael@0 157 void
michael@0 158 GonkDisplayJB::SetEnabled(bool enabled)
michael@0 159 {
michael@0 160 if (enabled) {
michael@0 161 autosuspend_disable();
michael@0 162 mPowerModule->setInteractive(mPowerModule, true);
michael@0 163 }
michael@0 164
michael@0 165 if (mHwc)
michael@0 166 mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, !enabled);
michael@0 167 else if (mFBDevice->enableScreen)
michael@0 168 mFBDevice->enableScreen(mFBDevice, enabled);
michael@0 169
michael@0 170 if (mEnabledCallback)
michael@0 171 mEnabledCallback(enabled);
michael@0 172
michael@0 173 if (!enabled) {
michael@0 174 autosuspend_enable();
michael@0 175 mPowerModule->setInteractive(mPowerModule, false);
michael@0 176 }
michael@0 177 }
michael@0 178
michael@0 179 void
michael@0 180 GonkDisplayJB::OnEnabled(OnEnabledCallbackType callback)
michael@0 181 {
michael@0 182 mEnabledCallback = callback;
michael@0 183 }
michael@0 184
michael@0 185 void*
michael@0 186 GonkDisplayJB::GetHWCDevice()
michael@0 187 {
michael@0 188 return mHwc;
michael@0 189 }
michael@0 190
michael@0 191 void*
michael@0 192 GonkDisplayJB::GetFBSurface()
michael@0 193 {
michael@0 194 return mFBSurface.get();
michael@0 195 }
michael@0 196
michael@0 197 bool
michael@0 198 GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
michael@0 199 {
michael@0 200 StopBootAnimation();
michael@0 201 mBootAnimBuffer = nullptr;
michael@0 202
michael@0 203 // Should be called when composition rendering is complete for a frame.
michael@0 204 // Only HWC v1.0 needs this call.
michael@0 205 // HWC > v1.0 case, do not call compositionComplete().
michael@0 206 // mFBDevice is present only when HWC is v1.0.
michael@0 207 if (mFBDevice && mFBDevice->compositionComplete) {
michael@0 208 mFBDevice->compositionComplete(mFBDevice);
michael@0 209 }
michael@0 210
michael@0 211 #if ANDROID_VERSION == 17
michael@0 212 mList->dpy = dpy;
michael@0 213 mList->sur = sur;
michael@0 214 #else
michael@0 215 mList->outbuf = nullptr;
michael@0 216 mList->outbufAcquireFenceFd = -1;
michael@0 217 #endif
michael@0 218 eglSwapBuffers(dpy, sur);
michael@0 219 return Post(mFBSurface->lastHandle, mFBSurface->GetPrevFBAcquireFd());
michael@0 220 }
michael@0 221
michael@0 222 bool
michael@0 223 GonkDisplayJB::Post(buffer_handle_t buf, int fence)
michael@0 224 {
michael@0 225 if (!mHwc) {
michael@0 226 if (fence >= 0)
michael@0 227 close(fence);
michael@0 228 return !mFBDevice->post(mFBDevice, buf);
michael@0 229 }
michael@0 230
michael@0 231 hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = {NULL};
michael@0 232 const hwc_rect_t r = { 0, 0, mWidth, mHeight };
michael@0 233 displays[HWC_DISPLAY_PRIMARY] = mList;
michael@0 234 mList->retireFenceFd = -1;
michael@0 235 mList->numHwLayers = 2;
michael@0 236 mList->flags = HWC_GEOMETRY_CHANGED;
michael@0 237 mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER;
michael@0 238 mList->hwLayers[0].hints = 0;
michael@0 239 /* Skip this layer so the hwc module doesn't complain about null handles */
michael@0 240 mList->hwLayers[0].flags = HWC_SKIP_LAYER;
michael@0 241 mList->hwLayers[0].backgroundColor = {0};
michael@0 242 mList->hwLayers[0].acquireFenceFd = -1;
michael@0 243 mList->hwLayers[0].releaseFenceFd = -1;
michael@0 244 /* hwc module checks displayFrame even though it shouldn't */
michael@0 245 mList->hwLayers[0].displayFrame = r;
michael@0 246 mList->hwLayers[1].compositionType = HWC_FRAMEBUFFER_TARGET;
michael@0 247 mList->hwLayers[1].hints = 0;
michael@0 248 mList->hwLayers[1].flags = 0;
michael@0 249 mList->hwLayers[1].handle = buf;
michael@0 250 mList->hwLayers[1].transform = 0;
michael@0 251 mList->hwLayers[1].blending = HWC_BLENDING_PREMULT;
michael@0 252 #if ANDROID_VERSION >= 19
michael@0 253 if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_3) {
michael@0 254 mList->hwLayers[1].sourceCropf.left = 0;
michael@0 255 mList->hwLayers[1].sourceCropf.top = 0;
michael@0 256 mList->hwLayers[1].sourceCropf.right = mWidth;
michael@0 257 mList->hwLayers[1].sourceCropf.bottom = mHeight;
michael@0 258 } else {
michael@0 259 mList->hwLayers[1].sourceCrop = r;
michael@0 260 }
michael@0 261 #else
michael@0 262 mList->hwLayers[1].sourceCrop = r;
michael@0 263 #endif
michael@0 264 mList->hwLayers[1].displayFrame = r;
michael@0 265 mList->hwLayers[1].visibleRegionScreen.numRects = 1;
michael@0 266 mList->hwLayers[1].visibleRegionScreen.rects = &mList->hwLayers[1].displayFrame;
michael@0 267 mList->hwLayers[1].acquireFenceFd = fence;
michael@0 268 mList->hwLayers[1].releaseFenceFd = -1;
michael@0 269 #if ANDROID_VERSION == 18
michael@0 270 mList->hwLayers[1].planeAlpha = 0xFF;
michael@0 271 #endif
michael@0 272 mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
michael@0 273 int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
michael@0 274 mFBSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd);
michael@0 275 if (mList->retireFenceFd >= 0)
michael@0 276 close(mList->retireFenceFd);
michael@0 277 return !err;
michael@0 278 }
michael@0 279
michael@0 280 ANativeWindowBuffer*
michael@0 281 GonkDisplayJB::DequeueBuffer()
michael@0 282 {
michael@0 283 return static_cast<ANativeWindowBuffer*>(mBootAnimBuffer.get());
michael@0 284 }
michael@0 285
michael@0 286 bool
michael@0 287 GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf)
michael@0 288 {
michael@0 289 bool success = Post(buf->handle, -1);
michael@0 290 return success;
michael@0 291 }
michael@0 292
michael@0 293 void
michael@0 294 GonkDisplayJB::UpdateFBSurface(EGLDisplay dpy, EGLSurface sur)
michael@0 295 {
michael@0 296 StopBootAnimation();
michael@0 297 mBootAnimBuffer = nullptr;
michael@0 298 eglSwapBuffers(dpy, sur);
michael@0 299 }
michael@0 300
michael@0 301 void
michael@0 302 GonkDisplayJB::SetFBReleaseFd(int fd)
michael@0 303 {
michael@0 304 mFBSurface->setReleaseFenceFd(fd);
michael@0 305 }
michael@0 306
michael@0 307 int
michael@0 308 GonkDisplayJB::GetPrevFBAcquireFd()
michael@0 309 {
michael@0 310 return mFBSurface->GetPrevFBAcquireFd();
michael@0 311 }
michael@0 312
michael@0 313 __attribute__ ((visibility ("default")))
michael@0 314 GonkDisplay*
michael@0 315 GetGonkDisplay()
michael@0 316 {
michael@0 317 if (!sGonkDisplay)
michael@0 318 sGonkDisplay = new GonkDisplayJB();
michael@0 319 return sGonkDisplay;
michael@0 320 }
michael@0 321
michael@0 322 } // namespace mozilla

mercurial