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