1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set ts=4 sw=4 sts=4 et: */
3 /*
4 * Copyright (c) 2012, 2013 The Linux Foundation. All rights reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <android/log.h>
20 #include <string.h>
21
22 #include "gfxPrefs.h"
23 #include "ImageLayers.h"
24 #include "libdisplay/GonkDisplay.h"
25 #include "HwcComposer2D.h"
26 #include "LayerScope.h"
27 #include "Units.h"
28 #include "mozilla/ClearOnShutdown.h"
29 #include "mozilla/layers/CompositorBridgeParent.h"
30 #include "mozilla/layers/LayerManagerComposite.h"
31 #include "mozilla/layers/PLayerTransaction.h"
32 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
33 #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
34 #include "mozilla/StaticPtr.h"
35 #include "nsThreadUtils.h"
36 #include "cutils/properties.h"
37 #include "gfx2DGlue.h"
38 #include "gfxPlatform.h"
39 #include "VsyncSource.h"
40 #include "nsScreenManagerGonk.h"
41 #include "nsWindow.h"
42
43 #if ANDROID_VERSION >= 17
44 #include "libdisplay/DisplaySurface.h"
45 #endif
46
47 #ifdef LOG_TAG
48 #undef LOG_TAG
49 #endif
50 #define LOG_TAG "HWComposer"
51
52 /*
53 * By default the debug message of hwcomposer (LOG_DEBUG level) are undefined,
54 * but can be enabled by uncommenting HWC_DEBUG below.
55 */
56 //#define HWC_DEBUG
57
58 #ifdef HWC_DEBUG
59 #define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ## args)
60 #else
61 #define LOGD(args...) ((void)0)
62 #endif
63
64 #define LOGI(args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, ## args)
65 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args)
66
67 #define LAYER_COUNT_INCREMENTS 5
68
69 using namespace android;
70 using namespace mozilla::gfx;
71 using namespace mozilla::layers;
72
73 namespace mozilla {
74
75 static void
HookInvalidate(const struct hwc_procs * aProcs)76 HookInvalidate(const struct hwc_procs* aProcs)
77 {
78 HwcComposer2D::GetInstance()->Invalidate();
79 }
80
81 static void
HookVsync(const struct hwc_procs * aProcs,int aDisplay,int64_t aTimestamp)82 HookVsync(const struct hwc_procs* aProcs, int aDisplay,
83 int64_t aTimestamp)
84 {
85 HwcComposer2D::GetInstance()->Vsync(aDisplay, aTimestamp);
86 }
87
88 static void
HookHotplug(const struct hwc_procs * aProcs,int aDisplay,int aConnected)89 HookHotplug(const struct hwc_procs* aProcs, int aDisplay,
90 int aConnected)
91 {
92 HwcComposer2D::GetInstance()->Hotplug(aDisplay, aConnected);
93 }
94
95 static StaticRefPtr<HwcComposer2D> sInstance;
96
HwcComposer2D()97 HwcComposer2D::HwcComposer2D()
98 : mList(nullptr)
99 , mMaxLayerCount(0)
100 , mColorFill(false)
101 , mRBSwapSupport(false)
102 , mPrepared(false)
103 , mHasHWVsync(false)
104 , mLock("mozilla.HwcComposer2D.mLock")
105 {
106 mHal = HwcHALBase::CreateHwcHAL();
107 if (!mHal->HasHwc()) {
108 LOGD("no hwc support");
109 return;
110 }
111
112 RegisterHwcEventCallback();
113
114 nsIntSize screenSize;
115
116 GonkDisplay::NativeData data = GetGonkDisplay()->GetNativeData(GonkDisplay::DISPLAY_PRIMARY);
117 ANativeWindow *win = data.mNativeWindow.get();
118 win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width);
119 win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height);
120 mScreenRect = gfx::IntRect(gfx::IntPoint(0, 0), screenSize);
121
122 mColorFill = mHal->Query(HwcHALBase::QueryType::COLOR_FILL);
123 mRBSwapSupport = mHal->Query(HwcHALBase::QueryType::RB_SWAP);
124 }
125
~HwcComposer2D()126 HwcComposer2D::~HwcComposer2D()
127 {
128 free(mList);
129 }
130
131 HwcComposer2D*
GetInstance()132 HwcComposer2D::GetInstance()
133 {
134 if (!sInstance) {
135 #ifdef HWC_DEBUG
136 // Make sure only create once
137 static int timesCreated = 0;
138 ++timesCreated;
139 MOZ_ASSERT(timesCreated == 1);
140 #endif
141 LOGI("Creating new instance");
142 sInstance = new HwcComposer2D();
143
144 // If anyone uses the compositor thread to create HwcComposer2D,
145 // we just skip this function.
146 // If ClearOnShutdown() can handle objects in other threads
147 // in the future, we can remove this check.
148 if (NS_IsMainThread()) {
149 // If we create HwcComposer2D by the main thread, we can use
150 // ClearOnShutdown() to make sure it will be nullified properly.
151 ClearOnShutdown(&sInstance);
152 }
153 }
154 return sInstance;
155 }
156
157 bool
EnableVsync(bool aEnable)158 HwcComposer2D::EnableVsync(bool aEnable)
159 {
160 MOZ_ASSERT(NS_IsMainThread());
161 if (!mHasHWVsync) {
162 return false;
163 }
164 return mHal->EnableVsync(aEnable) && aEnable;
165 }
166
167 bool
RegisterHwcEventCallback()168 HwcComposer2D::RegisterHwcEventCallback()
169 {
170 const HwcHALProcs_t cHWCProcs = {
171 &HookInvalidate, // 1st: void (*invalidate)(...)
172 &HookVsync, // 2nd: void (*vsync)(...)
173 &HookHotplug // 3rd: void (*hotplug)(...)
174 };
175 mHasHWVsync = mHal->RegisterHwcEventCallback(cHWCProcs);
176 return mHasHWVsync;
177 }
178
179 void
Vsync(int aDisplay,nsecs_t aVsyncTimestamp)180 HwcComposer2D::Vsync(int aDisplay, nsecs_t aVsyncTimestamp)
181 {
182 // Only support hardware vsync on kitkat, L and up due to inaccurate timings
183 // with JellyBean.
184 #if (ANDROID_VERSION == 19 || ANDROID_VERSION >= 21)
185 TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(aVsyncTimestamp);
186 gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().NotifyVsync(vsyncTime);
187 #else
188 // If this device doesn't support vsync, this function should not be used.
189 MOZ_ASSERT(false);
190 #endif
191 }
192
193 // Called on the "invalidator" thread (run from HAL).
194 void
Invalidate()195 HwcComposer2D::Invalidate()
196 {
197 if (!mHal->HasHwc()) {
198 LOGE("HwcComposer2D::Invalidate failed!");
199 return;
200 }
201
202 MutexAutoLock lock(mLock);
203 if (mCompositorBridgeParent) {
204 mCompositorBridgeParent->ScheduleRenderOnCompositorThread();
205 }
206 }
207
208 namespace {
209 class HotplugEvent : public Runnable {
210 public:
HotplugEvent(GonkDisplay::DisplayType aType,bool aConnected)211 HotplugEvent(GonkDisplay::DisplayType aType, bool aConnected)
212 : mType(aType)
213 , mConnected(aConnected)
214 {
215 }
216
Run()217 NS_IMETHOD Run() override
218 {
219 RefPtr<nsScreenManagerGonk> screenManager =
220 nsScreenManagerGonk::GetInstance();
221 if (mConnected) {
222 screenManager->AddScreen(mType);
223 } else {
224 screenManager->RemoveScreen(mType);
225 }
226 return NS_OK;
227 }
228 private:
229 GonkDisplay::DisplayType mType;
230 bool mConnected;
231 };
232 } // namespace
233
234 void
Hotplug(int aDisplay,int aConnected)235 HwcComposer2D::Hotplug(int aDisplay, int aConnected)
236 {
237 NS_DispatchToMainThread(new HotplugEvent(GonkDisplay::DISPLAY_EXTERNAL,
238 aConnected));
239 }
240
241 void
SetCompositorBridgeParent(CompositorBridgeParent * aCompositorBridgeParent)242 HwcComposer2D::SetCompositorBridgeParent(CompositorBridgeParent* aCompositorBridgeParent)
243 {
244 MutexAutoLock lock(mLock);
245 mCompositorBridgeParent = aCompositorBridgeParent;
246 }
247
248 bool
ReallocLayerList()249 HwcComposer2D::ReallocLayerList()
250 {
251 int size = sizeof(HwcList) +
252 ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer));
253
254 HwcList* listrealloc = (HwcList*)realloc(mList, size);
255
256 if (!listrealloc) {
257 return false;
258 }
259
260 if (!mList) {
261 //first alloc, initialize
262 listrealloc->numHwLayers = 0;
263 listrealloc->flags = 0;
264 }
265
266 mList = listrealloc;
267 mMaxLayerCount += LAYER_COUNT_INCREMENTS;
268 return true;
269 }
270
271 bool
PrepareLayerList(Layer * aLayer,const nsIntRect & aClip,const Matrix & aParentTransform,bool aFindSidebandStreams)272 HwcComposer2D::PrepareLayerList(Layer* aLayer,
273 const nsIntRect& aClip,
274 const Matrix& aParentTransform,
275 bool aFindSidebandStreams)
276 {
277 // NB: we fall off this path whenever there are container layers
278 // that require intermediate surfaces. That means all the
279 // GetEffective*() coordinates are relative to the framebuffer.
280
281 bool fillColor = false;
282
283 const nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
284 if (visibleRegion.IsEmpty()) {
285 return true;
286 }
287
288 uint8_t opacity = std::min(0xFF, (int)(aLayer->GetEffectiveOpacity() * 256.0));
289 if (opacity == 0) {
290 LOGD("%s Layer has zero opacity; skipping", aLayer->Name());
291 return true;
292 }
293
294 if (!mHal->SupportTransparency() && opacity < 0xFF && !aFindSidebandStreams) {
295 LOGD("%s Layer has planar semitransparency which is unsupported by hwcomposer", aLayer->Name());
296 return false;
297 }
298
299 if (aLayer->GetMaskLayer() && !aFindSidebandStreams) {
300 LOGD("%s Layer has MaskLayer which is unsupported by hwcomposer", aLayer->Name());
301 return false;
302 }
303
304 nsIntRect clip;
305 nsIntRect layerClip = aLayer->GetLocalClipRect().valueOr(ParentLayerIntRect()).ToUnknownRect();
306 nsIntRect* layerClipPtr = aLayer->GetLocalClipRect() ? &layerClip : nullptr;
307 if (!HwcUtils::CalculateClipRect(aParentTransform,
308 layerClipPtr,
309 aClip,
310 &clip))
311 {
312 LOGD("%s Clip rect is empty. Skip layer", aLayer->Name());
313 return true;
314 }
315
316 // HWC supports only the following 2D transformations:
317 //
318 // Scaling via the sourceCrop and displayFrame in HwcLayer
319 // Translation via the sourceCrop and displayFrame in HwcLayer
320 // Rotation (in square angles only) via the HWC_TRANSFORM_ROT_* flags
321 // Reflection (horizontal and vertical) via the HWC_TRANSFORM_FLIP_* flags
322 //
323 // A 2D transform with PreservesAxisAlignedRectangles() has all the attributes
324 // above
325 Matrix layerTransform;
326 if (!aLayer->GetEffectiveTransform().Is2D(&layerTransform) ||
327 !layerTransform.PreservesAxisAlignedRectangles()) {
328 LOGD("Layer EffectiveTransform has a 3D transform or a non-square angle rotation");
329 return false;
330 }
331
332 Matrix layerBufferTransform;
333 if (!aLayer->GetEffectiveTransformForBuffer().Is2D(&layerBufferTransform) ||
334 !layerBufferTransform.PreservesAxisAlignedRectangles()) {
335 LOGD("Layer EffectiveTransformForBuffer has a 3D transform or a non-square angle rotation");
336 return false;
337 }
338
339 if (ContainerLayer* container = aLayer->AsContainerLayer()) {
340 if (container->UseIntermediateSurface() && !aFindSidebandStreams) {
341 LOGD("Container layer needs intermediate surface");
342 return false;
343 }
344 AutoTArray<Layer*, 12> children;
345 container->SortChildrenBy3DZOrder(children);
346
347 for (uint32_t i = 0; i < children.Length(); i++) {
348 if (!PrepareLayerList(children[i], clip, layerTransform, aFindSidebandStreams) &&
349 !aFindSidebandStreams) {
350 return false;
351 }
352 }
353 return true;
354 }
355
356 LayerRenderState state = aLayer->GetRenderState();
357
358 #if ANDROID_VERSION >= 21
359 if (!state.GetGrallocBuffer() && !state.GetSidebandStream().IsValid()) {
360 #else
361 if (!state.GetGrallocBuffer()) {
362 #endif
363 if (aLayer->AsColorLayer() && mColorFill) {
364 fillColor = true;
365 } else {
366 LOGD("%s Layer doesn't have a gralloc buffer", aLayer->Name());
367 return false;
368 }
369 }
370
371 nsIntRect visibleRect = visibleRegion.GetBounds();
372
373 nsIntRect bufferRect;
374 if (fillColor) {
375 bufferRect = nsIntRect(visibleRect);
376 } else {
377 nsIntRect layerRect;
378 if (state.mHasOwnOffset) {
379 bufferRect = nsIntRect(state.mOffset.x, state.mOffset.y,
380 state.mSize.width, state.mSize.height);
381 layerRect = bufferRect;
382 } else {
383 //Since the buffer doesn't have its own offset, assign the whole
384 //surface size as its buffer bounds
385 bufferRect = nsIntRect(0, 0, state.mSize.width, state.mSize.height);
386 layerRect = bufferRect;
387 if (aLayer->GetType() == Layer::TYPE_IMAGE) {
388 ImageLayer* imageLayer = static_cast<ImageLayer*>(aLayer);
389 if(imageLayer->GetScaleMode() != ScaleMode::SCALE_NONE) {
390 layerRect = nsIntRect(0, 0, imageLayer->GetScaleToSize().width, imageLayer->GetScaleToSize().height);
391 }
392 }
393 }
394 // In some cases the visible rect assigned to the layer can be larger
395 // than the layer's surface, e.g., an ImageLayer with a small Image
396 // in it.
397 visibleRect.IntersectRect(visibleRect, layerRect);
398 }
399
400 // Buffer rotation is not to be confused with the angled rotation done by a transform matrix
401 // It's a fancy PaintedLayer feature used for scrolling
402 if (state.BufferRotated()) {
403 LOGD("%s Layer has a rotated buffer", aLayer->Name());
404 return false;
405 }
406
407 const bool needsYFlip = state.OriginBottomLeft() ? true
408 : false;
409
410 hwc_rect_t sourceCrop, displayFrame;
411 if(!HwcUtils::PrepareLayerRects(visibleRect,
412 layerTransform,
413 layerBufferTransform,
414 clip,
415 bufferRect,
416 needsYFlip,
417 &(sourceCrop),
418 &(displayFrame)))
419 {
420 return true;
421 }
422
423 // OK! We can compose this layer with hwc.
424 int current = mList ? mList->numHwLayers : 0;
425
426 // Do not compose any layer below full-screen Opaque layer
427 // Note: It can be generalized to non-fullscreen Opaque layers.
428 bool isOpaque = opacity == 0xFF &&
429 (state.mFlags & LayerRenderStateFlags::OPAQUE);
430 // Currently we perform opacity calculation using the *bounds* of the layer.
431 // We can only make this assumption if we're not dealing with a complex visible region.
432 bool isSimpleVisibleRegion = visibleRegion.Contains(visibleRect);
433 if (current && isOpaque && isSimpleVisibleRegion) {
434 nsIntRect displayRect = nsIntRect(displayFrame.left, displayFrame.top,
435 displayFrame.right - displayFrame.left, displayFrame.bottom - displayFrame.top);
436 if (displayRect.Contains(mScreenRect)) {
437 // In z-order, all previous layers are below
438 // the current layer. We can ignore them now.
439 mList->numHwLayers = current = 0;
440 mHwcLayerMap.Clear();
441 }
442 }
443
444 if (!mList || current >= mMaxLayerCount) {
445 if (!ReallocLayerList() || current >= mMaxLayerCount) {
446 LOGE("PrepareLayerList failed! Could not increase the maximum layer count");
447 return false;
448 }
449 }
450
451 HwcLayer& hwcLayer = mList->hwLayers[current];
452 hwcLayer.displayFrame = displayFrame;
453 mHal->SetCrop(hwcLayer, sourceCrop);
454 buffer_handle_t handle = nullptr;
455 #if ANDROID_VERSION >= 21
456 if (state.GetSidebandStream().IsValid()) {
457 handle = state.GetSidebandStream().GetRawNativeHandle();
458 } else if (state.GetGrallocBuffer()) {
459 handle = state.GetGrallocBuffer()->getNativeBuffer()->handle;
460 }
461 #else
462 if (state.GetGrallocBuffer()) {
463 handle = state.GetGrallocBuffer()->getNativeBuffer()->handle;
464 }
465 #endif
466 hwcLayer.handle = handle;
467
468 hwcLayer.flags = 0;
469 hwcLayer.hints = 0;
470 hwcLayer.blending = isOpaque ? HWC_BLENDING_NONE : HWC_BLENDING_PREMULT;
471 #if ANDROID_VERSION >= 17
472 hwcLayer.compositionType = HWC_FRAMEBUFFER;
473 #if ANDROID_VERSION >= 21
474 if (state.GetSidebandStream().IsValid()) {
475 hwcLayer.compositionType = HWC_SIDEBAND;
476 }
477 #endif
478 hwcLayer.acquireFenceFd = -1;
479 hwcLayer.releaseFenceFd = -1;
480 #if ANDROID_VERSION >= 18
481 hwcLayer.planeAlpha = opacity;
482 #endif
483 #else
484 hwcLayer.compositionType = HwcUtils::HWC_USE_COPYBIT;
485 #endif
486
487 if (!fillColor) {
488 if (state.FormatRBSwapped()) {
489 if (!mRBSwapSupport) {
490 LOGD("No R/B swap support in H/W Composer");
491 return false;
492 }
493 hwcLayer.flags |= HwcUtils::HWC_FORMAT_RB_SWAP;
494 }
495
496 // Translation and scaling have been addressed in PrepareLayerRects().
497 // Given the above and that we checked for PreservesAxisAlignedRectangles()
498 // the only possible transformations left to address are
499 // square angle rotation and horizontal/vertical reflection.
500 //
501 // The rotation and reflection permutations total 16 but can be
502 // reduced to 8 transformations after eliminating redundancies.
503 //
504 // All matrices represented here are in the form
505 //
506 // | xx xy |
507 // | yx yy |
508 //
509 // And ignore scaling.
510 //
511 // Reflection is applied before rotation
512 gfx::Matrix rotation = layerTransform;
513 // Compute fuzzy zero like PreservesAxisAlignedRectangles()
514 if (fabs(rotation._11) < 1e-6) {
515 if (rotation._21 < 0) {
516 if (rotation._12 > 0) {
517 // 90 degree rotation
518 //
519 // | 0 -1 |
520 // | 1 0 |
521 //
522 hwcLayer.transform = HWC_TRANSFORM_ROT_90;
523 LOGD("Layer rotated 90 degrees");
524 }
525 else {
526 // Horizontal reflection then 90 degree rotation
527 //
528 // | 0 -1 | | -1 0 | = | 0 -1 |
529 // | 1 0 | | 0 1 | | -1 0 |
530 //
531 // same as vertical reflection then 270 degree rotation
532 //
533 // | 0 1 | | 1 0 | = | 0 -1 |
534 // | -1 0 | | 0 -1 | | -1 0 |
535 //
536 hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_H;
537 LOGD("Layer vertically reflected then rotated 270 degrees");
538 }
539 } else {
540 if (rotation._12 < 0) {
541 // 270 degree rotation
542 //
543 // | 0 1 |
544 // | -1 0 |
545 //
546 hwcLayer.transform = HWC_TRANSFORM_ROT_270;
547 LOGD("Layer rotated 270 degrees");
548 }
549 else {
550 // Vertical reflection then 90 degree rotation
551 //
552 // | 0 1 | | -1 0 | = | 0 1 |
553 // | -1 0 | | 0 1 | | 1 0 |
554 //
555 // Same as horizontal reflection then 270 degree rotation
556 //
557 // | 0 -1 | | 1 0 | = | 0 1 |
558 // | 1 0 | | 0 -1 | | 1 0 |
559 //
560 hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_V;
561 LOGD("Layer horizontally reflected then rotated 270 degrees");
562 }
563 }
564 } else if (rotation._11 < 0) {
565 if (rotation._22 > 0) {
566 // Horizontal reflection
567 //
568 // | -1 0 |
569 // | 0 1 |
570 //
571 hwcLayer.transform = HWC_TRANSFORM_FLIP_H;
572 LOGD("Layer rotated 180 degrees");
573 }
574 else {
575 // 180 degree rotation
576 //
577 // | -1 0 |
578 // | 0 -1 |
579 //
580 // Same as horizontal and vertical reflection
581 //
582 // | -1 0 | | 1 0 | = | -1 0 |
583 // | 0 1 | | 0 -1 | | 0 -1 |
584 //
585 hwcLayer.transform = HWC_TRANSFORM_ROT_180;
586 LOGD("Layer rotated 180 degrees");
587 }
588 } else {
589 if (rotation._22 < 0) {
590 // Vertical reflection
591 //
592 // | 1 0 |
593 // | 0 -1 |
594 //
595 hwcLayer.transform = HWC_TRANSFORM_FLIP_V;
596 LOGD("Layer rotated 180 degrees");
597 }
598 else {
599 // No rotation or reflection
600 //
601 // | 1 0 |
602 // | 0 1 |
603 //
604 hwcLayer.transform = 0;
605 }
606 }
607
608 const bool needsYFlip = state.OriginBottomLeft() ? true
609 : false;
610
611 if (needsYFlip) {
612 // Invert vertical reflection flag if it was already set
613 hwcLayer.transform ^= HWC_TRANSFORM_FLIP_V;
614 }
615 hwc_region_t region;
616 if (visibleRegion.GetNumRects() > 1) {
617 mVisibleRegions.push_back(HwcUtils::RectVector());
618 HwcUtils::RectVector* visibleRects = &(mVisibleRegions.back());
619 bool isVisible = false;
620 if(!HwcUtils::PrepareVisibleRegion(visibleRegion,
621 layerTransform,
622 layerBufferTransform,
623 clip,
624 bufferRect,
625 visibleRects,
626 isVisible)) {
627 LOGD("A region of layer is too small to be rendered by HWC");
628 return false;
629 }
630 if (!isVisible) {
631 // Layer is not visible, no need to render it
632 return true;
633 }
634 region.numRects = visibleRects->size();
635 region.rects = &((*visibleRects)[0]);
636 } else {
637 region.numRects = 1;
638 region.rects = &(hwcLayer.displayFrame);
639 }
640 hwcLayer.visibleRegionScreen = region;
641 } else {
642 hwcLayer.flags |= HwcUtils::HWC_COLOR_FILL;
643 ColorLayer* colorLayer = aLayer->AsColorLayer();
644 if (colorLayer->GetColor().a < 1.0) {
645 LOGD("Color layer has semitransparency which is unsupported");
646 return false;
647 }
648 hwcLayer.transform = colorLayer->GetColor().ToABGR();
649 }
650
651 #if ANDROID_VERSION >= 21
652 if (aFindSidebandStreams && hwcLayer.compositionType == HWC_SIDEBAND) {
653 mCachedSidebandLayers.AppendElement(hwcLayer);
654 }
655 #endif
656
657 mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData()));
658 mList->numHwLayers++;
659 return true;
660 }
661
662
663 #if ANDROID_VERSION >= 17
664 bool
665 HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
666 {
667 DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
668
669 if (!(dispSurface && dispSurface->lastHandle)) {
670 LOGD("H/W Composition failed. DispSurface not initialized.");
671 return false;
672 }
673
674 // Add FB layer
675 int idx = mList->numHwLayers++;
676 if (idx >= mMaxLayerCount) {
677 if (!ReallocLayerList() || idx >= mMaxLayerCount) {
678 LOGE("TryHwComposition failed! Could not add FB layer");
679 return false;
680 }
681 }
682
683 Prepare(dispSurface->lastHandle, -1, aScreen);
684
685 /* Possible composition paths, after hwc prepare:
686 1. GPU Composition
687 2. BLIT Composition
688 3. Full OVERLAY Composition
689 4. Partial OVERLAY Composition (GPU + OVERLAY) */
690
691 bool gpuComposite = false;
692 bool blitComposite = false;
693 bool overlayComposite = true;
694
695 for (int j=0; j < idx; j++) {
696 if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER ||
697 mList->hwLayers[j].compositionType == HWC_BLIT) {
698 // Full OVERLAY composition is not possible on this frame
699 // It is either GPU / BLIT / partial OVERLAY composition.
700 overlayComposite = false;
701 break;
702 }
703 }
704
705 if (!overlayComposite) {
706 for (int k=0; k < idx; k++) {
707 switch (mList->hwLayers[k].compositionType) {
708 case HWC_FRAMEBUFFER:
709 gpuComposite = true;
710 break;
711 case HWC_BLIT:
712 blitComposite = true;
713 break;
714 #if ANDROID_VERSION >= 21
715 case HWC_SIDEBAND:
716 #endif
717 case HWC_OVERLAY: {
718 // HWC will compose HWC_OVERLAY layers in partial
719 // Overlay Composition, set layer composition flag
720 // on mapped LayerComposite to skip GPU composition
721 mHwcLayerMap[k]->SetLayerComposited(true);
722
723 uint8_t opacity = std::min(0xFF, (int)(mHwcLayerMap[k]->GetLayer()->GetEffectiveOpacity() * 256.0));
724 if ((mList->hwLayers[k].hints & HWC_HINT_CLEAR_FB) &&
725 (opacity == 0xFF)) {
726 // Clear visible rect on FB with transparent pixels.
727 hwc_rect_t r = mList->hwLayers[k].displayFrame;
728 mHwcLayerMap[k]->SetClearRect(nsIntRect(r.left, r.top,
729 r.right - r.left,
730 r.bottom - r.top));
731 }
732 break;
733 }
734 default:
735 break;
736 }
737 }
738
739 if (gpuComposite) {
740 // GPU or partial OVERLAY Composition
741 return false;
742 } else if (blitComposite) {
743 // BLIT Composition, flip DispSurface target
744 GetGonkDisplay()->UpdateDispSurface(aScreen->GetEGLDisplay(), aScreen->GetEGLSurface());
745 DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
746 if (!dispSurface) {
747 LOGE("H/W Composition failed. NULL DispSurface.");
748 return false;
749 }
750 mList->hwLayers[idx].handle = dispSurface->lastHandle;
751 mList->hwLayers[idx].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
752 }
753 }
754
755 // BLIT or full OVERLAY Composition
756 return Commit(aScreen);
757 }
758
759 bool
760 HwcComposer2D::Render(nsIWidget* aWidget)
761 {
762 nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
763
764 // HWC module does not exist or mList is not created yet.
765 if (!mHal->HasHwc() || !mList) {
766 return GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface());
767 } else if (!mList && !ReallocLayerList()) {
768 LOGE("Cannot realloc layer list");
769 return false;
770 }
771
772 DisplaySurface* dispSurface = screen->GetDisplaySurface();
773 if (!dispSurface) {
774 LOGE("H/W Composition failed. DispSurface not initialized.");
775 return false;
776 }
777
778 if (mPrepared) {
779 // No mHwc prepare, if already prepared in current draw cycle
780 mList->hwLayers[mList->numHwLayers - 1].handle = dispSurface->lastHandle;
781 mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
782 } else {
783 // Update screen rect to handle a case that TryRenderWithHwc() is not called.
784 mScreenRect = screen->GetNaturalBounds().ToUnknownRect();
785
786 mList->flags = HWC_GEOMETRY_CHANGED;
787 mList->numHwLayers = 2;
788 mList->hwLayers[0].hints = 0;
789 mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER;
790 mList->hwLayers[0].flags = HWC_SKIP_LAYER;
791 mList->hwLayers[0].backgroundColor = {0};
792 mList->hwLayers[0].acquireFenceFd = -1;
793 mList->hwLayers[0].releaseFenceFd = -1;
794 mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height};
795
796 #if ANDROID_VERSION >= 21
797 // Prepare layers for sideband streams
798 const uint32_t len = mCachedSidebandLayers.Length();
799 for (uint32_t i = 0; i < len; ++i) {
800 ++mList->numHwLayers;
801 mList->hwLayers[i+1] = mCachedSidebandLayers[i];
802 }
803 #endif
804 Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd(), screen);
805 }
806
807 // GPU or partial HWC Composition
808 return Commit(screen);
809 }
810
811 void
812 HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen)
813 {
814 if (mPrepared) {
815 LOGE("Multiple hwc prepare calls!");
816 }
817 hwc_rect_t dispRect = {0, 0, mScreenRect.width, mScreenRect.height};
818 mHal->Prepare(mList, screen->GetDisplayType(), dispRect, dispHandle, fence);
819 mPrepared = true;
820 }
821
822 bool
823 HwcComposer2D::Commit(nsScreenGonk* aScreen)
824 {
825 for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
826 mList->hwLayers[j].acquireFenceFd = -1;
827 if (mHwcLayerMap.IsEmpty() ||
828 (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER)) {
829 continue;
830 }
831 LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
832 if (!state.mTexture) {
833 continue;
834 }
835 FenceHandle fence = state.mTexture->GetAndResetAcquireFenceHandle();
836 if (fence.IsValid()) {
837 RefPtr<FenceHandle::FdObj> fdObj = fence.GetAndResetFdObj();
838 mList->hwLayers[j].acquireFenceFd = fdObj->GetAndResetFd();
839 }
840 }
841
842 int err = mHal->Set(mList, aScreen->GetDisplayType());
843
844 mPrevRetireFence.TransferToAnotherFenceHandle(mPrevDisplayFence);
845
846 for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
847 if (mList->hwLayers[j].releaseFenceFd >= 0) {
848 int fd = mList->hwLayers[j].releaseFenceFd;
849 mList->hwLayers[j].releaseFenceFd = -1;
850 RefPtr<FenceHandle::FdObj> fdObj = new FenceHandle::FdObj(fd);
851 FenceHandle fence(fdObj);
852
853 LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
854 if (!state.mTexture) {
855 continue;
856 }
857 state.mTexture->SetReleaseFenceHandle(fence);
858 }
859 }
860
861 if (mList->retireFenceFd >= 0) {
862 mPrevRetireFence = FenceHandle(new FenceHandle::FdObj(mList->retireFenceFd));
863 }
864
865 // Set DisplaySurface layer fence
866 DisplaySurface* displaySurface = aScreen->GetDisplaySurface();
867 displaySurface->setReleaseFenceFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
868 mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd = -1;
869
870 mPrepared = false;
871 return !err;
872 }
873 #else
874 bool
875 HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
876 {
877 mHal->SetEGLInfo(aScreen->GetEGLDisplay(), aScreen->GetEGLSurface());
878 return !mHal->Set(mList, aScreen->GetDisplayType());
879 }
880
881 bool
882 HwcComposer2D::Render(nsIWidget* aWidget)
883 {
884 nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
885 return GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface());
886 }
887 #endif
888
889 bool
890 HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
891 nsIWidget* aWidget,
892 bool aGeometryChanged,
893 bool aHasImageHostOverlays)
894 {
895 if (!mHal->HasHwc()) {
896 return false;
897 }
898
899 nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
900
901 if (mList) {
902 mList->flags = mHal->GetGeometryChangedFlag(aGeometryChanged);
903 mList->numHwLayers = 0;
904 mHwcLayerMap.Clear();
905 }
906
907 if (mPrepared) {
908 mHal->ResetHwc();
909 mPrepared = false;
910 }
911
912 // XXX: The clear() below means all rect vectors will be have to be
913 // reallocated. We may want to avoid this if possible
914 mVisibleRegions.clear();
915
916 mScreenRect = screen->GetNaturalBounds().ToUnknownRect();
917 MOZ_ASSERT(mHwcLayerMap.IsEmpty());
918 mCachedSidebandLayers.Clear();
919 if (!PrepareLayerList(aRoot,
920 mScreenRect,
921 gfx::Matrix(),
922 /* aFindSidebandStreams */ false))
923 {
924 mHwcLayerMap.Clear();
925 LOGD("Render aborted. Fallback to GPU Composition");
926 if (aHasImageHostOverlays) {
927 LOGD("Prepare layers of SidebandStreams");
928 // Failed to create a layer list for hwc. But we need the list
929 // only for handling sideband streams. Traverse layer tree without
930 // some early returns to make sure we can find all the layers.
931 // It is the best wrong thing that we can do.
932 PrepareLayerList(aRoot,
933 mScreenRect,
934 gfx::Matrix(),
935 /* aFindSidebandStreams */ true);
936 // Reset mPrepared to false, since we already fell back to
937 // gpu composition.
938 mPrepared = false;
939 }
940 return false;
941 }
942
943 // Send data to LayerScope for debugging
944 SendtoLayerScope();
945
946 if (!TryHwComposition(screen)) {
947 LOGD("Full HWC Composition failed. Fallback to GPU Composition or partial OVERLAY Composition");
948 LayerScope::CleanLayer();
949 return false;
950 }
951
952 LOGD("Frame rendered");
953 return true;
954 }
955
956 void
957 HwcComposer2D::SendtoLayerScope()
958 {
959 if (!LayerScope::CheckSendable()) {
960 return;
961 }
962
963 const int len = mList->numHwLayers;
964 for (int i = 0; i < len; ++i) {
965 LayerComposite* layer = mHwcLayerMap[i];
966 const hwc_rect_t r = mList->hwLayers[i].displayFrame;
967 LayerScope::SendLayer(layer, r.right - r.left, r.bottom - r.top);
968 }
969 }
970
971 } // namespace mozilla
972