|
1 /* |
|
2 * Copyright (c) 2012, 2013 The Linux Foundation. All rights reserved. |
|
3 * |
|
4 * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 * you may not use this file except in compliance with the License. |
|
6 * You may obtain a copy of the License at |
|
7 * |
|
8 * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 * |
|
10 * Unless required by applicable law or agreed to in writing, software |
|
11 * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 * See the License for the specific language governing permissions and |
|
14 * limitations under the License. |
|
15 */ |
|
16 |
|
17 #include <android/log.h> |
|
18 #include <string.h> |
|
19 |
|
20 #include "libdisplay/GonkDisplay.h" |
|
21 #include "Framebuffer.h" |
|
22 #include "GLContext.h" // for GLContext |
|
23 #include "HwcUtils.h" |
|
24 #include "HwcComposer2D.h" |
|
25 #include "mozilla/layers/LayerManagerComposite.h" |
|
26 #include "mozilla/layers/PLayerTransaction.h" |
|
27 #include "mozilla/layers/ShadowLayerUtilsGralloc.h" |
|
28 #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL |
|
29 #include "mozilla/StaticPtr.h" |
|
30 #include "cutils/properties.h" |
|
31 #include "gfx2DGlue.h" |
|
32 |
|
33 #if ANDROID_VERSION >= 17 |
|
34 #include "libdisplay/FramebufferSurface.h" |
|
35 #ifndef HWC_BLIT |
|
36 #define HWC_BLIT (HWC_FRAMEBUFFER_TARGET + 1) |
|
37 #endif |
|
38 #endif |
|
39 |
|
40 #ifdef LOG_TAG |
|
41 #undef LOG_TAG |
|
42 #endif |
|
43 #define LOG_TAG "HWComposer" |
|
44 |
|
45 /* |
|
46 * By default the debug message of hwcomposer (LOG_DEBUG level) are undefined, |
|
47 * but can be enabled by uncommenting HWC_DEBUG below. |
|
48 */ |
|
49 //#define HWC_DEBUG |
|
50 |
|
51 #ifdef HWC_DEBUG |
|
52 #define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ## args) |
|
53 #else |
|
54 #define LOGD(args...) ((void)0) |
|
55 #endif |
|
56 |
|
57 #define LOGI(args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, ## args) |
|
58 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args) |
|
59 |
|
60 #define LAYER_COUNT_INCREMENTS 5 |
|
61 |
|
62 using namespace android; |
|
63 using namespace mozilla::layers; |
|
64 |
|
65 namespace mozilla { |
|
66 |
|
67 static StaticRefPtr<HwcComposer2D> sInstance; |
|
68 |
|
69 HwcComposer2D::HwcComposer2D() |
|
70 : mHwc(nullptr) |
|
71 , mList(nullptr) |
|
72 , mMaxLayerCount(0) |
|
73 , mColorFill(false) |
|
74 , mRBSwapSupport(false) |
|
75 #if ANDROID_VERSION >= 17 |
|
76 , mPrevRetireFence(Fence::NO_FENCE) |
|
77 , mPrevDisplayFence(Fence::NO_FENCE) |
|
78 #endif |
|
79 , mPrepared(false) |
|
80 { |
|
81 } |
|
82 |
|
83 HwcComposer2D::~HwcComposer2D() { |
|
84 free(mList); |
|
85 } |
|
86 |
|
87 int |
|
88 HwcComposer2D::Init(hwc_display_t dpy, hwc_surface_t sur) |
|
89 { |
|
90 MOZ_ASSERT(!Initialized()); |
|
91 |
|
92 mHwc = (HwcDevice*)GetGonkDisplay()->GetHWCDevice(); |
|
93 if (!mHwc) { |
|
94 LOGE("Failed to initialize hwc"); |
|
95 return -1; |
|
96 } |
|
97 |
|
98 nsIntSize screenSize; |
|
99 |
|
100 mozilla::Framebuffer::GetSize(&screenSize); |
|
101 mScreenRect = nsIntRect(nsIntPoint(0, 0), screenSize); |
|
102 |
|
103 #if ANDROID_VERSION >= 17 |
|
104 int supported = 0; |
|
105 |
|
106 if (mHwc->query) { |
|
107 if (mHwc->query(mHwc, HwcUtils::HWC_COLOR_FILL, &supported) == NO_ERROR) { |
|
108 mColorFill = !!supported; |
|
109 } |
|
110 if (mHwc->query(mHwc, HwcUtils::HWC_FORMAT_RB_SWAP, &supported) == NO_ERROR) { |
|
111 mRBSwapSupport = !!supported; |
|
112 } |
|
113 } else { |
|
114 mColorFill = false; |
|
115 mRBSwapSupport = false; |
|
116 } |
|
117 #else |
|
118 char propValue[PROPERTY_VALUE_MAX]; |
|
119 property_get("ro.display.colorfill", propValue, "0"); |
|
120 mColorFill = (atoi(propValue) == 1) ? true : false; |
|
121 mRBSwapSupport = true; |
|
122 #endif |
|
123 |
|
124 mDpy = dpy; |
|
125 mSur = sur; |
|
126 |
|
127 return 0; |
|
128 } |
|
129 |
|
130 HwcComposer2D* |
|
131 HwcComposer2D::GetInstance() |
|
132 { |
|
133 if (!sInstance) { |
|
134 LOGI("Creating new instance"); |
|
135 sInstance = new HwcComposer2D(); |
|
136 } |
|
137 return sInstance; |
|
138 } |
|
139 |
|
140 bool |
|
141 HwcComposer2D::ReallocLayerList() |
|
142 { |
|
143 int size = sizeof(HwcList) + |
|
144 ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer)); |
|
145 |
|
146 HwcList* listrealloc = (HwcList*)realloc(mList, size); |
|
147 |
|
148 if (!listrealloc) { |
|
149 return false; |
|
150 } |
|
151 |
|
152 if (!mList) { |
|
153 //first alloc, initialize |
|
154 listrealloc->numHwLayers = 0; |
|
155 listrealloc->flags = 0; |
|
156 } |
|
157 |
|
158 mList = listrealloc; |
|
159 mMaxLayerCount += LAYER_COUNT_INCREMENTS; |
|
160 return true; |
|
161 } |
|
162 |
|
163 void |
|
164 HwcComposer2D::setCrop(HwcLayer* layer, hwc_rect_t srcCrop) |
|
165 { |
|
166 #if ANDROID_VERSION >= 19 |
|
167 if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_3) { |
|
168 layer->sourceCropf.left = srcCrop.left; |
|
169 layer->sourceCropf.top = srcCrop.top; |
|
170 layer->sourceCropf.right = srcCrop.right; |
|
171 layer->sourceCropf.bottom = srcCrop.bottom; |
|
172 } else { |
|
173 layer->sourceCrop = srcCrop; |
|
174 } |
|
175 #else |
|
176 layer->sourceCrop = srcCrop; |
|
177 #endif |
|
178 } |
|
179 |
|
180 void |
|
181 HwcComposer2D::setHwcGeometry(bool aGeometryChanged) |
|
182 { |
|
183 #if ANDROID_VERSION >= 19 |
|
184 mList->flags = aGeometryChanged ? HWC_GEOMETRY_CHANGED : 0; |
|
185 #else |
|
186 mList->flags = HWC_GEOMETRY_CHANGED; |
|
187 #endif |
|
188 } |
|
189 |
|
190 bool |
|
191 HwcComposer2D::PrepareLayerList(Layer* aLayer, |
|
192 const nsIntRect& aClip, |
|
193 const gfxMatrix& aParentTransform, |
|
194 const gfxMatrix& aGLWorldTransform) |
|
195 { |
|
196 // NB: we fall off this path whenever there are container layers |
|
197 // that require intermediate surfaces. That means all the |
|
198 // GetEffective*() coordinates are relative to the framebuffer. |
|
199 |
|
200 bool fillColor = false; |
|
201 |
|
202 const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion(); |
|
203 if (visibleRegion.IsEmpty()) { |
|
204 return true; |
|
205 } |
|
206 |
|
207 uint8_t opacity = std::min(0xFF, (int)(aLayer->GetEffectiveOpacity() * 256.0)); |
|
208 #if ANDROID_VERSION < 18 |
|
209 if (opacity < 0xFF) { |
|
210 LOGD("%s Layer has planar semitransparency which is unsupported", aLayer->Name()); |
|
211 return false; |
|
212 } |
|
213 #endif |
|
214 |
|
215 nsIntRect clip; |
|
216 if (!HwcUtils::CalculateClipRect(aParentTransform * aGLWorldTransform, |
|
217 aLayer->GetEffectiveClipRect(), |
|
218 aClip, |
|
219 &clip)) |
|
220 { |
|
221 LOGD("%s Clip rect is empty. Skip layer", aLayer->Name()); |
|
222 return true; |
|
223 } |
|
224 |
|
225 // HWC supports only the following 2D transformations: |
|
226 // |
|
227 // Scaling via the sourceCrop and displayFrame in HwcLayer |
|
228 // Translation via the sourceCrop and displayFrame in HwcLayer |
|
229 // Rotation (in square angles only) via the HWC_TRANSFORM_ROT_* flags |
|
230 // Reflection (horizontal and vertical) via the HWC_TRANSFORM_FLIP_* flags |
|
231 // |
|
232 // A 2D transform with PreservesAxisAlignedRectangles() has all the attributes |
|
233 // above |
|
234 gfxMatrix transform; |
|
235 gfx3DMatrix transform3D; |
|
236 gfx::To3DMatrix(aLayer->GetEffectiveTransform(), transform3D); |
|
237 |
|
238 if (!transform3D.Is2D(&transform) || !transform.PreservesAxisAlignedRectangles()) { |
|
239 LOGD("Layer has a 3D transform or a non-square angle rotation"); |
|
240 return false; |
|
241 } |
|
242 |
|
243 |
|
244 if (ContainerLayer* container = aLayer->AsContainerLayer()) { |
|
245 nsAutoTArray<Layer*, 12> children; |
|
246 container->SortChildrenBy3DZOrder(children); |
|
247 |
|
248 for (uint32_t i = 0; i < children.Length(); i++) { |
|
249 if (!PrepareLayerList(children[i], clip, transform, aGLWorldTransform)) { |
|
250 return false; |
|
251 } |
|
252 } |
|
253 return true; |
|
254 } |
|
255 |
|
256 LayerRenderState state = aLayer->GetRenderState(); |
|
257 nsIntSize surfaceSize; |
|
258 |
|
259 if (state.mSurface.get()) { |
|
260 surfaceSize = state.mSize; |
|
261 } else { |
|
262 if (aLayer->AsColorLayer() && mColorFill) { |
|
263 fillColor = true; |
|
264 } else { |
|
265 LOGD("%s Layer doesn't have a gralloc buffer", aLayer->Name()); |
|
266 return false; |
|
267 } |
|
268 } |
|
269 // Buffer rotation is not to be confused with the angled rotation done by a transform matrix |
|
270 // It's a fancy ThebesLayer feature used for scrolling |
|
271 if (state.BufferRotated()) { |
|
272 LOGD("%s Layer has a rotated buffer", aLayer->Name()); |
|
273 return false; |
|
274 } |
|
275 |
|
276 nsIntRect visibleRect = visibleRegion.GetBounds(); |
|
277 |
|
278 nsIntRect bufferRect; |
|
279 if (fillColor) { |
|
280 bufferRect = nsIntRect(visibleRect); |
|
281 } else { |
|
282 if(state.mHasOwnOffset) { |
|
283 bufferRect = nsIntRect(state.mOffset.x, state.mOffset.y, |
|
284 state.mSize.width, state.mSize.height); |
|
285 } else { |
|
286 //Since the buffer doesn't have its own offset, assign the whole |
|
287 //surface size as its buffer bounds |
|
288 bufferRect = nsIntRect(0, 0, state.mSize.width, state.mSize.height); |
|
289 } |
|
290 } |
|
291 |
|
292 hwc_rect_t sourceCrop, displayFrame; |
|
293 if(!HwcUtils::PrepareLayerRects(visibleRect, |
|
294 transform * aGLWorldTransform, |
|
295 clip, |
|
296 bufferRect, |
|
297 state.YFlipped(), |
|
298 &(sourceCrop), |
|
299 &(displayFrame))) |
|
300 { |
|
301 return true; |
|
302 } |
|
303 |
|
304 // OK! We can compose this layer with hwc. |
|
305 int current = mList ? mList->numHwLayers : 0; |
|
306 |
|
307 // Do not compose any layer below full-screen Opaque layer |
|
308 // Note: It can be generalized to non-fullscreen Opaque layers. |
|
309 bool isOpaque = (opacity == 0xFF) && (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE); |
|
310 if (current && isOpaque) { |
|
311 nsIntRect displayRect = nsIntRect(displayFrame.left, displayFrame.top, |
|
312 displayFrame.right - displayFrame.left, displayFrame.bottom - displayFrame.top); |
|
313 if (displayRect.Contains(mScreenRect)) { |
|
314 // In z-order, all previous layers are below |
|
315 // the current layer. We can ignore them now. |
|
316 mList->numHwLayers = current = 0; |
|
317 mHwcLayerMap.Clear(); |
|
318 } |
|
319 } |
|
320 |
|
321 if (!mList || current >= mMaxLayerCount) { |
|
322 if (!ReallocLayerList() || current >= mMaxLayerCount) { |
|
323 LOGE("PrepareLayerList failed! Could not increase the maximum layer count"); |
|
324 return false; |
|
325 } |
|
326 } |
|
327 |
|
328 HwcLayer& hwcLayer = mList->hwLayers[current]; |
|
329 hwcLayer.flags = 0; |
|
330 |
|
331 if (ContainerLayer* parent = aLayer->GetParent()) { |
|
332 if (parent->UseIntermediateSurface()) { |
|
333 LOGD("Parent container needs intermediate surface"); |
|
334 hwcLayer.flags = HWC_SKIP_LAYER; |
|
335 #if ANDROID_VERSION < 18 |
|
336 // No partial HWC Composition on older versions |
|
337 return false; |
|
338 #endif |
|
339 } |
|
340 } |
|
341 |
|
342 hwcLayer.displayFrame = displayFrame; |
|
343 setCrop(&hwcLayer, sourceCrop); |
|
344 buffer_handle_t handle = fillColor ? nullptr : state.mSurface->getNativeBuffer()->handle; |
|
345 hwcLayer.handle = handle; |
|
346 |
|
347 hwcLayer.hints = 0; |
|
348 hwcLayer.blending = isOpaque ? HWC_BLENDING_NONE : HWC_BLENDING_PREMULT; |
|
349 #if ANDROID_VERSION >= 17 |
|
350 hwcLayer.compositionType = HWC_FRAMEBUFFER; |
|
351 |
|
352 hwcLayer.acquireFenceFd = -1; |
|
353 hwcLayer.releaseFenceFd = -1; |
|
354 #if ANDROID_VERSION >= 18 |
|
355 hwcLayer.planeAlpha = opacity; |
|
356 #endif |
|
357 #else |
|
358 hwcLayer.compositionType = HwcUtils::HWC_USE_COPYBIT; |
|
359 #endif |
|
360 |
|
361 if (!fillColor) { |
|
362 if (state.FormatRBSwapped()) { |
|
363 if (!mRBSwapSupport) { |
|
364 LOGD("No R/B swap support in H/W Composer"); |
|
365 return false; |
|
366 } |
|
367 hwcLayer.flags |= HwcUtils::HWC_FORMAT_RB_SWAP; |
|
368 } |
|
369 |
|
370 // Translation and scaling have been addressed in PrepareLayerRects(). |
|
371 // Given the above and that we checked for PreservesAxisAlignedRectangles() |
|
372 // the only possible transformations left to address are |
|
373 // square angle rotation and horizontal/vertical reflection. |
|
374 // |
|
375 // The rotation and reflection permutations total 16 but can be |
|
376 // reduced to 8 transformations after eliminating redundancies. |
|
377 // |
|
378 // All matrices represented here are in the form |
|
379 // |
|
380 // | xx xy | |
|
381 // | yx yy | |
|
382 // |
|
383 // And ignore scaling. |
|
384 // |
|
385 // Reflection is applied before rotation |
|
386 gfxMatrix rotation = transform * aGLWorldTransform; |
|
387 // Compute fuzzy zero like PreservesAxisAlignedRectangles() |
|
388 if (fabs(rotation.xx) < 1e-6) { |
|
389 if (rotation.xy < 0) { |
|
390 if (rotation.yx > 0) { |
|
391 // 90 degree rotation |
|
392 // |
|
393 // | 0 -1 | |
|
394 // | 1 0 | |
|
395 // |
|
396 hwcLayer.transform = HWC_TRANSFORM_ROT_90; |
|
397 LOGD("Layer rotated 90 degrees"); |
|
398 } |
|
399 else { |
|
400 // Horizontal reflection then 90 degree rotation |
|
401 // |
|
402 // | 0 -1 | | -1 0 | = | 0 -1 | |
|
403 // | 1 0 | | 0 1 | | -1 0 | |
|
404 // |
|
405 // same as vertical reflection then 270 degree rotation |
|
406 // |
|
407 // | 0 1 | | 1 0 | = | 0 -1 | |
|
408 // | -1 0 | | 0 -1 | | -1 0 | |
|
409 // |
|
410 hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_H; |
|
411 LOGD("Layer vertically reflected then rotated 270 degrees"); |
|
412 } |
|
413 } else { |
|
414 if (rotation.yx < 0) { |
|
415 // 270 degree rotation |
|
416 // |
|
417 // | 0 1 | |
|
418 // | -1 0 | |
|
419 // |
|
420 hwcLayer.transform = HWC_TRANSFORM_ROT_270; |
|
421 LOGD("Layer rotated 270 degrees"); |
|
422 } |
|
423 else { |
|
424 // Vertical reflection then 90 degree rotation |
|
425 // |
|
426 // | 0 1 | | -1 0 | = | 0 1 | |
|
427 // | -1 0 | | 0 1 | | 1 0 | |
|
428 // |
|
429 // Same as horizontal reflection then 270 degree rotation |
|
430 // |
|
431 // | 0 -1 | | 1 0 | = | 0 1 | |
|
432 // | 1 0 | | 0 -1 | | 1 0 | |
|
433 // |
|
434 hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_V; |
|
435 LOGD("Layer horizontally reflected then rotated 270 degrees"); |
|
436 } |
|
437 } |
|
438 } else if (rotation.xx < 0) { |
|
439 if (rotation.yy > 0) { |
|
440 // Horizontal reflection |
|
441 // |
|
442 // | -1 0 | |
|
443 // | 0 1 | |
|
444 // |
|
445 hwcLayer.transform = HWC_TRANSFORM_FLIP_H; |
|
446 LOGD("Layer rotated 180 degrees"); |
|
447 } |
|
448 else { |
|
449 // 180 degree rotation |
|
450 // |
|
451 // | -1 0 | |
|
452 // | 0 -1 | |
|
453 // |
|
454 // Same as horizontal and vertical reflection |
|
455 // |
|
456 // | -1 0 | | 1 0 | = | -1 0 | |
|
457 // | 0 1 | | 0 -1 | | 0 -1 | |
|
458 // |
|
459 hwcLayer.transform = HWC_TRANSFORM_ROT_180; |
|
460 LOGD("Layer rotated 180 degrees"); |
|
461 } |
|
462 } else { |
|
463 if (rotation.yy < 0) { |
|
464 // Vertical reflection |
|
465 // |
|
466 // | 1 0 | |
|
467 // | 0 -1 | |
|
468 // |
|
469 hwcLayer.transform = HWC_TRANSFORM_FLIP_V; |
|
470 LOGD("Layer rotated 180 degrees"); |
|
471 } |
|
472 else { |
|
473 // No rotation or reflection |
|
474 // |
|
475 // | 1 0 | |
|
476 // | 0 1 | |
|
477 // |
|
478 hwcLayer.transform = 0; |
|
479 } |
|
480 } |
|
481 |
|
482 if (state.YFlipped()) { |
|
483 // Invert vertical reflection flag if it was already set |
|
484 hwcLayer.transform ^= HWC_TRANSFORM_FLIP_V; |
|
485 } |
|
486 hwc_region_t region; |
|
487 if (visibleRegion.GetNumRects() > 1) { |
|
488 mVisibleRegions.push_back(HwcUtils::RectVector()); |
|
489 HwcUtils::RectVector* visibleRects = &(mVisibleRegions.back()); |
|
490 if(!HwcUtils::PrepareVisibleRegion(visibleRegion, |
|
491 transform * aGLWorldTransform, |
|
492 clip, |
|
493 bufferRect, |
|
494 visibleRects)) { |
|
495 return true; |
|
496 } |
|
497 region.numRects = visibleRects->size(); |
|
498 region.rects = &((*visibleRects)[0]); |
|
499 } else { |
|
500 region.numRects = 1; |
|
501 region.rects = &(hwcLayer.displayFrame); |
|
502 } |
|
503 hwcLayer.visibleRegionScreen = region; |
|
504 } else { |
|
505 hwcLayer.flags |= HwcUtils::HWC_COLOR_FILL; |
|
506 ColorLayer* colorLayer = aLayer->AsColorLayer(); |
|
507 if (colorLayer->GetColor().a < 1.0) { |
|
508 LOGD("Color layer has semitransparency which is unsupported"); |
|
509 return false; |
|
510 } |
|
511 hwcLayer.transform = colorLayer->GetColor().Packed(); |
|
512 } |
|
513 |
|
514 mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData())); |
|
515 mList->numHwLayers++; |
|
516 return true; |
|
517 } |
|
518 |
|
519 |
|
520 #if ANDROID_VERSION >= 17 |
|
521 bool |
|
522 HwcComposer2D::TryHwComposition() |
|
523 { |
|
524 FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface()); |
|
525 |
|
526 if (!(fbsurface && fbsurface->lastHandle)) { |
|
527 LOGD("H/W Composition failed. FBSurface not initialized."); |
|
528 return false; |
|
529 } |
|
530 |
|
531 // Add FB layer |
|
532 int idx = mList->numHwLayers++; |
|
533 if (idx >= mMaxLayerCount) { |
|
534 if (!ReallocLayerList() || idx >= mMaxLayerCount) { |
|
535 LOGE("TryHwComposition failed! Could not add FB layer"); |
|
536 return false; |
|
537 } |
|
538 } |
|
539 |
|
540 Prepare(fbsurface->lastHandle, -1); |
|
541 |
|
542 /* Possible composition paths, after hwc prepare: |
|
543 1. GPU Composition |
|
544 2. BLIT Composition |
|
545 3. Full OVERLAY Composition |
|
546 4. Partial OVERLAY Composition (GPU + OVERLAY) */ |
|
547 |
|
548 bool gpuComposite = false; |
|
549 bool blitComposite = false; |
|
550 bool overlayComposite = true; |
|
551 |
|
552 for (int j=0; j < idx; j++) { |
|
553 if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER || |
|
554 mList->hwLayers[j].compositionType == HWC_BLIT) { |
|
555 // Full OVERLAY composition is not possible on this frame |
|
556 // It is either GPU / BLIT / partial OVERLAY composition. |
|
557 overlayComposite = false; |
|
558 break; |
|
559 } |
|
560 } |
|
561 |
|
562 if (!overlayComposite) { |
|
563 for (int k=0; k < idx; k++) { |
|
564 switch (mList->hwLayers[k].compositionType) { |
|
565 case HWC_FRAMEBUFFER: |
|
566 gpuComposite = true; |
|
567 break; |
|
568 case HWC_BLIT: |
|
569 blitComposite = true; |
|
570 break; |
|
571 case HWC_OVERLAY: |
|
572 // HWC will compose HWC_OVERLAY layers in partial |
|
573 // Overlay Composition, set layer composition flag |
|
574 // on mapped LayerComposite to skip GPU composition |
|
575 mHwcLayerMap[k]->SetLayerComposited(true); |
|
576 if ((mList->hwLayers[k].hints & HWC_HINT_CLEAR_FB) && |
|
577 (mList->hwLayers[k].blending == HWC_BLENDING_NONE)) { |
|
578 // Clear visible rect on FB with transparent pixels. |
|
579 hwc_rect_t r = mList->hwLayers[k].displayFrame; |
|
580 mHwcLayerMap[k]->SetClearRect(nsIntRect(r.left, r.top, |
|
581 r.right - r.left, |
|
582 r.bottom - r.top)); |
|
583 } |
|
584 break; |
|
585 default: |
|
586 break; |
|
587 } |
|
588 } |
|
589 |
|
590 if (gpuComposite) { |
|
591 // GPU or partial OVERLAY Composition |
|
592 return false; |
|
593 } else if (blitComposite) { |
|
594 // BLIT Composition, flip FB target |
|
595 GetGonkDisplay()->UpdateFBSurface(mDpy, mSur); |
|
596 FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface()); |
|
597 if (!fbsurface) { |
|
598 LOGE("H/W Composition failed. NULL FBSurface."); |
|
599 return false; |
|
600 } |
|
601 mList->hwLayers[idx].handle = fbsurface->lastHandle; |
|
602 mList->hwLayers[idx].acquireFenceFd = fbsurface->GetPrevFBAcquireFd(); |
|
603 } |
|
604 } |
|
605 |
|
606 // BLIT or full OVERLAY Composition |
|
607 Commit(); |
|
608 |
|
609 GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[idx].releaseFenceFd); |
|
610 return true; |
|
611 } |
|
612 |
|
613 bool |
|
614 HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur) |
|
615 { |
|
616 if (!mList) { |
|
617 // After boot, HWC list hasn't been created yet |
|
618 return GetGonkDisplay()->SwapBuffers(dpy, sur); |
|
619 } |
|
620 |
|
621 GetGonkDisplay()->UpdateFBSurface(dpy, sur); |
|
622 |
|
623 FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface()); |
|
624 if (!fbsurface) { |
|
625 LOGE("H/W Composition failed. FBSurface not initialized."); |
|
626 return false; |
|
627 } |
|
628 |
|
629 if (mPrepared) { |
|
630 // No mHwc prepare, if already prepared in current draw cycle |
|
631 mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle; |
|
632 mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->GetPrevFBAcquireFd(); |
|
633 } else { |
|
634 mList->flags = HWC_GEOMETRY_CHANGED; |
|
635 mList->numHwLayers = 2; |
|
636 mList->hwLayers[0].hints = 0; |
|
637 mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER; |
|
638 mList->hwLayers[0].flags = HWC_SKIP_LAYER; |
|
639 mList->hwLayers[0].backgroundColor = {0}; |
|
640 mList->hwLayers[0].acquireFenceFd = -1; |
|
641 mList->hwLayers[0].releaseFenceFd = -1; |
|
642 mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height}; |
|
643 Prepare(fbsurface->lastHandle, fbsurface->GetPrevFBAcquireFd()); |
|
644 } |
|
645 |
|
646 // GPU or partial HWC Composition |
|
647 Commit(); |
|
648 |
|
649 GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd); |
|
650 return true; |
|
651 } |
|
652 |
|
653 void |
|
654 HwcComposer2D::Prepare(buffer_handle_t fbHandle, int fence) |
|
655 { |
|
656 int idx = mList->numHwLayers - 1; |
|
657 const hwc_rect_t r = {0, 0, mScreenRect.width, mScreenRect.height}; |
|
658 hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr }; |
|
659 |
|
660 displays[HWC_DISPLAY_PRIMARY] = mList; |
|
661 mList->outbufAcquireFenceFd = -1; |
|
662 mList->outbuf = nullptr; |
|
663 mList->retireFenceFd = -1; |
|
664 |
|
665 mList->hwLayers[idx].hints = 0; |
|
666 mList->hwLayers[idx].flags = 0; |
|
667 mList->hwLayers[idx].transform = 0; |
|
668 mList->hwLayers[idx].handle = fbHandle; |
|
669 mList->hwLayers[idx].blending = HWC_BLENDING_PREMULT; |
|
670 mList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET; |
|
671 setCrop(&mList->hwLayers[idx], r); |
|
672 mList->hwLayers[idx].displayFrame = r; |
|
673 mList->hwLayers[idx].visibleRegionScreen.numRects = 1; |
|
674 mList->hwLayers[idx].visibleRegionScreen.rects = &mList->hwLayers[idx].displayFrame; |
|
675 mList->hwLayers[idx].acquireFenceFd = fence; |
|
676 mList->hwLayers[idx].releaseFenceFd = -1; |
|
677 #if ANDROID_VERSION >= 18 |
|
678 mList->hwLayers[idx].planeAlpha = 0xFF; |
|
679 #endif |
|
680 if (mPrepared) { |
|
681 LOGE("Multiple hwc prepare calls!"); |
|
682 } |
|
683 mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays); |
|
684 mPrepared = true; |
|
685 } |
|
686 |
|
687 bool |
|
688 HwcComposer2D::Commit() |
|
689 { |
|
690 hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr }; |
|
691 displays[HWC_DISPLAY_PRIMARY] = mList; |
|
692 |
|
693 int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays); |
|
694 |
|
695 mPrevDisplayFence = mPrevRetireFence; |
|
696 mPrevRetireFence = Fence::NO_FENCE; |
|
697 |
|
698 for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) { |
|
699 if (mList->hwLayers[j].releaseFenceFd >= 0) { |
|
700 int fd = mList->hwLayers[j].releaseFenceFd; |
|
701 mList->hwLayers[j].releaseFenceFd = -1; |
|
702 sp<Fence> fence = new Fence(fd); |
|
703 |
|
704 LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState(); |
|
705 if (!state.mTexture) { |
|
706 continue; |
|
707 } |
|
708 TextureHostOGL* texture = state.mTexture->AsHostOGL(); |
|
709 if (!texture) { |
|
710 continue; |
|
711 } |
|
712 texture->SetReleaseFence(fence); |
|
713 } |
|
714 } |
|
715 |
|
716 if (mList->retireFenceFd >= 0) { |
|
717 mPrevRetireFence = new Fence(mList->retireFenceFd); |
|
718 } |
|
719 |
|
720 mPrepared = false; |
|
721 return !err; |
|
722 } |
|
723 |
|
724 void |
|
725 HwcComposer2D::Reset() |
|
726 { |
|
727 LOGD("hwcomposer is already prepared, reset with null set"); |
|
728 hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr }; |
|
729 displays[HWC_DISPLAY_PRIMARY] = nullptr; |
|
730 mHwc->set(mHwc, HWC_DISPLAY_PRIMARY, displays); |
|
731 mPrepared = false; |
|
732 } |
|
733 #else |
|
734 bool |
|
735 HwcComposer2D::TryHwComposition() |
|
736 { |
|
737 return !mHwc->set(mHwc, mDpy, mSur, mList); |
|
738 } |
|
739 |
|
740 bool |
|
741 HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur) |
|
742 { |
|
743 return GetGonkDisplay()->SwapBuffers(dpy, sur); |
|
744 } |
|
745 |
|
746 void |
|
747 HwcComposer2D::Reset() |
|
748 { |
|
749 mPrepared = false; |
|
750 } |
|
751 #endif |
|
752 |
|
753 bool |
|
754 HwcComposer2D::TryRender(Layer* aRoot, |
|
755 const gfx::Matrix& GLWorldTransform, |
|
756 bool aGeometryChanged) |
|
757 { |
|
758 gfxMatrix aGLWorldTransform = ThebesMatrix(GLWorldTransform); |
|
759 if (!aGLWorldTransform.PreservesAxisAlignedRectangles()) { |
|
760 LOGD("Render aborted. World transform has non-square angle rotation"); |
|
761 return false; |
|
762 } |
|
763 |
|
764 MOZ_ASSERT(Initialized()); |
|
765 if (mList) { |
|
766 setHwcGeometry(aGeometryChanged); |
|
767 mList->numHwLayers = 0; |
|
768 mHwcLayerMap.Clear(); |
|
769 } |
|
770 |
|
771 if (mPrepared) { |
|
772 Reset(); |
|
773 } |
|
774 |
|
775 // XXX: The clear() below means all rect vectors will be have to be |
|
776 // reallocated. We may want to avoid this if possible |
|
777 mVisibleRegions.clear(); |
|
778 |
|
779 MOZ_ASSERT(mHwcLayerMap.IsEmpty()); |
|
780 if (!PrepareLayerList(aRoot, |
|
781 mScreenRect, |
|
782 gfxMatrix(), |
|
783 aGLWorldTransform)) |
|
784 { |
|
785 LOGD("Render aborted. Nothing was drawn to the screen"); |
|
786 return false; |
|
787 } |
|
788 |
|
789 if (!TryHwComposition()) { |
|
790 LOGD("H/W Composition failed"); |
|
791 return false; |
|
792 } |
|
793 |
|
794 LOGD("Frame rendered"); |
|
795 return true; |
|
796 } |
|
797 |
|
798 } // namespace mozilla |