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