1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/HwcComposer2D.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,798 @@ 1.4 +/* 1.5 + * Copyright (c) 2012, 2013 The Linux Foundation. All rights reserved. 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#include <android/log.h> 1.21 +#include <string.h> 1.22 + 1.23 +#include "libdisplay/GonkDisplay.h" 1.24 +#include "Framebuffer.h" 1.25 +#include "GLContext.h" // for GLContext 1.26 +#include "HwcUtils.h" 1.27 +#include "HwcComposer2D.h" 1.28 +#include "mozilla/layers/LayerManagerComposite.h" 1.29 +#include "mozilla/layers/PLayerTransaction.h" 1.30 +#include "mozilla/layers/ShadowLayerUtilsGralloc.h" 1.31 +#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL 1.32 +#include "mozilla/StaticPtr.h" 1.33 +#include "cutils/properties.h" 1.34 +#include "gfx2DGlue.h" 1.35 + 1.36 +#if ANDROID_VERSION >= 17 1.37 +#include "libdisplay/FramebufferSurface.h" 1.38 +#ifndef HWC_BLIT 1.39 +#define HWC_BLIT (HWC_FRAMEBUFFER_TARGET + 1) 1.40 +#endif 1.41 +#endif 1.42 + 1.43 +#ifdef LOG_TAG 1.44 +#undef LOG_TAG 1.45 +#endif 1.46 +#define LOG_TAG "HWComposer" 1.47 + 1.48 +/* 1.49 + * By default the debug message of hwcomposer (LOG_DEBUG level) are undefined, 1.50 + * but can be enabled by uncommenting HWC_DEBUG below. 1.51 + */ 1.52 +//#define HWC_DEBUG 1.53 + 1.54 +#ifdef HWC_DEBUG 1.55 +#define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ## args) 1.56 +#else 1.57 +#define LOGD(args...) ((void)0) 1.58 +#endif 1.59 + 1.60 +#define LOGI(args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, ## args) 1.61 +#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args) 1.62 + 1.63 +#define LAYER_COUNT_INCREMENTS 5 1.64 + 1.65 +using namespace android; 1.66 +using namespace mozilla::layers; 1.67 + 1.68 +namespace mozilla { 1.69 + 1.70 +static StaticRefPtr<HwcComposer2D> sInstance; 1.71 + 1.72 +HwcComposer2D::HwcComposer2D() 1.73 + : mHwc(nullptr) 1.74 + , mList(nullptr) 1.75 + , mMaxLayerCount(0) 1.76 + , mColorFill(false) 1.77 + , mRBSwapSupport(false) 1.78 +#if ANDROID_VERSION >= 17 1.79 + , mPrevRetireFence(Fence::NO_FENCE) 1.80 + , mPrevDisplayFence(Fence::NO_FENCE) 1.81 +#endif 1.82 + , mPrepared(false) 1.83 +{ 1.84 +} 1.85 + 1.86 +HwcComposer2D::~HwcComposer2D() { 1.87 + free(mList); 1.88 +} 1.89 + 1.90 +int 1.91 +HwcComposer2D::Init(hwc_display_t dpy, hwc_surface_t sur) 1.92 +{ 1.93 + MOZ_ASSERT(!Initialized()); 1.94 + 1.95 + mHwc = (HwcDevice*)GetGonkDisplay()->GetHWCDevice(); 1.96 + if (!mHwc) { 1.97 + LOGE("Failed to initialize hwc"); 1.98 + return -1; 1.99 + } 1.100 + 1.101 + nsIntSize screenSize; 1.102 + 1.103 + mozilla::Framebuffer::GetSize(&screenSize); 1.104 + mScreenRect = nsIntRect(nsIntPoint(0, 0), screenSize); 1.105 + 1.106 +#if ANDROID_VERSION >= 17 1.107 + int supported = 0; 1.108 + 1.109 + if (mHwc->query) { 1.110 + if (mHwc->query(mHwc, HwcUtils::HWC_COLOR_FILL, &supported) == NO_ERROR) { 1.111 + mColorFill = !!supported; 1.112 + } 1.113 + if (mHwc->query(mHwc, HwcUtils::HWC_FORMAT_RB_SWAP, &supported) == NO_ERROR) { 1.114 + mRBSwapSupport = !!supported; 1.115 + } 1.116 + } else { 1.117 + mColorFill = false; 1.118 + mRBSwapSupport = false; 1.119 + } 1.120 +#else 1.121 + char propValue[PROPERTY_VALUE_MAX]; 1.122 + property_get("ro.display.colorfill", propValue, "0"); 1.123 + mColorFill = (atoi(propValue) == 1) ? true : false; 1.124 + mRBSwapSupport = true; 1.125 +#endif 1.126 + 1.127 + mDpy = dpy; 1.128 + mSur = sur; 1.129 + 1.130 + return 0; 1.131 +} 1.132 + 1.133 +HwcComposer2D* 1.134 +HwcComposer2D::GetInstance() 1.135 +{ 1.136 + if (!sInstance) { 1.137 + LOGI("Creating new instance"); 1.138 + sInstance = new HwcComposer2D(); 1.139 + } 1.140 + return sInstance; 1.141 +} 1.142 + 1.143 +bool 1.144 +HwcComposer2D::ReallocLayerList() 1.145 +{ 1.146 + int size = sizeof(HwcList) + 1.147 + ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer)); 1.148 + 1.149 + HwcList* listrealloc = (HwcList*)realloc(mList, size); 1.150 + 1.151 + if (!listrealloc) { 1.152 + return false; 1.153 + } 1.154 + 1.155 + if (!mList) { 1.156 + //first alloc, initialize 1.157 + listrealloc->numHwLayers = 0; 1.158 + listrealloc->flags = 0; 1.159 + } 1.160 + 1.161 + mList = listrealloc; 1.162 + mMaxLayerCount += LAYER_COUNT_INCREMENTS; 1.163 + return true; 1.164 +} 1.165 + 1.166 +void 1.167 +HwcComposer2D::setCrop(HwcLayer* layer, hwc_rect_t srcCrop) 1.168 +{ 1.169 +#if ANDROID_VERSION >= 19 1.170 + if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_3) { 1.171 + layer->sourceCropf.left = srcCrop.left; 1.172 + layer->sourceCropf.top = srcCrop.top; 1.173 + layer->sourceCropf.right = srcCrop.right; 1.174 + layer->sourceCropf.bottom = srcCrop.bottom; 1.175 + } else { 1.176 + layer->sourceCrop = srcCrop; 1.177 + } 1.178 +#else 1.179 + layer->sourceCrop = srcCrop; 1.180 +#endif 1.181 +} 1.182 + 1.183 +void 1.184 +HwcComposer2D::setHwcGeometry(bool aGeometryChanged) 1.185 +{ 1.186 +#if ANDROID_VERSION >= 19 1.187 + mList->flags = aGeometryChanged ? HWC_GEOMETRY_CHANGED : 0; 1.188 +#else 1.189 + mList->flags = HWC_GEOMETRY_CHANGED; 1.190 +#endif 1.191 +} 1.192 + 1.193 +bool 1.194 +HwcComposer2D::PrepareLayerList(Layer* aLayer, 1.195 + const nsIntRect& aClip, 1.196 + const gfxMatrix& aParentTransform, 1.197 + const gfxMatrix& aGLWorldTransform) 1.198 +{ 1.199 + // NB: we fall off this path whenever there are container layers 1.200 + // that require intermediate surfaces. That means all the 1.201 + // GetEffective*() coordinates are relative to the framebuffer. 1.202 + 1.203 + bool fillColor = false; 1.204 + 1.205 + const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion(); 1.206 + if (visibleRegion.IsEmpty()) { 1.207 + return true; 1.208 + } 1.209 + 1.210 + uint8_t opacity = std::min(0xFF, (int)(aLayer->GetEffectiveOpacity() * 256.0)); 1.211 +#if ANDROID_VERSION < 18 1.212 + if (opacity < 0xFF) { 1.213 + LOGD("%s Layer has planar semitransparency which is unsupported", aLayer->Name()); 1.214 + return false; 1.215 + } 1.216 +#endif 1.217 + 1.218 + nsIntRect clip; 1.219 + if (!HwcUtils::CalculateClipRect(aParentTransform * aGLWorldTransform, 1.220 + aLayer->GetEffectiveClipRect(), 1.221 + aClip, 1.222 + &clip)) 1.223 + { 1.224 + LOGD("%s Clip rect is empty. Skip layer", aLayer->Name()); 1.225 + return true; 1.226 + } 1.227 + 1.228 + // HWC supports only the following 2D transformations: 1.229 + // 1.230 + // Scaling via the sourceCrop and displayFrame in HwcLayer 1.231 + // Translation via the sourceCrop and displayFrame in HwcLayer 1.232 + // Rotation (in square angles only) via the HWC_TRANSFORM_ROT_* flags 1.233 + // Reflection (horizontal and vertical) via the HWC_TRANSFORM_FLIP_* flags 1.234 + // 1.235 + // A 2D transform with PreservesAxisAlignedRectangles() has all the attributes 1.236 + // above 1.237 + gfxMatrix transform; 1.238 + gfx3DMatrix transform3D; 1.239 + gfx::To3DMatrix(aLayer->GetEffectiveTransform(), transform3D); 1.240 + 1.241 + if (!transform3D.Is2D(&transform) || !transform.PreservesAxisAlignedRectangles()) { 1.242 + LOGD("Layer has a 3D transform or a non-square angle rotation"); 1.243 + return false; 1.244 + } 1.245 + 1.246 + 1.247 + if (ContainerLayer* container = aLayer->AsContainerLayer()) { 1.248 + nsAutoTArray<Layer*, 12> children; 1.249 + container->SortChildrenBy3DZOrder(children); 1.250 + 1.251 + for (uint32_t i = 0; i < children.Length(); i++) { 1.252 + if (!PrepareLayerList(children[i], clip, transform, aGLWorldTransform)) { 1.253 + return false; 1.254 + } 1.255 + } 1.256 + return true; 1.257 + } 1.258 + 1.259 + LayerRenderState state = aLayer->GetRenderState(); 1.260 + nsIntSize surfaceSize; 1.261 + 1.262 + if (state.mSurface.get()) { 1.263 + surfaceSize = state.mSize; 1.264 + } else { 1.265 + if (aLayer->AsColorLayer() && mColorFill) { 1.266 + fillColor = true; 1.267 + } else { 1.268 + LOGD("%s Layer doesn't have a gralloc buffer", aLayer->Name()); 1.269 + return false; 1.270 + } 1.271 + } 1.272 + // Buffer rotation is not to be confused with the angled rotation done by a transform matrix 1.273 + // It's a fancy ThebesLayer feature used for scrolling 1.274 + if (state.BufferRotated()) { 1.275 + LOGD("%s Layer has a rotated buffer", aLayer->Name()); 1.276 + return false; 1.277 + } 1.278 + 1.279 + nsIntRect visibleRect = visibleRegion.GetBounds(); 1.280 + 1.281 + nsIntRect bufferRect; 1.282 + if (fillColor) { 1.283 + bufferRect = nsIntRect(visibleRect); 1.284 + } else { 1.285 + if(state.mHasOwnOffset) { 1.286 + bufferRect = nsIntRect(state.mOffset.x, state.mOffset.y, 1.287 + state.mSize.width, state.mSize.height); 1.288 + } else { 1.289 + //Since the buffer doesn't have its own offset, assign the whole 1.290 + //surface size as its buffer bounds 1.291 + bufferRect = nsIntRect(0, 0, state.mSize.width, state.mSize.height); 1.292 + } 1.293 + } 1.294 + 1.295 + hwc_rect_t sourceCrop, displayFrame; 1.296 + if(!HwcUtils::PrepareLayerRects(visibleRect, 1.297 + transform * aGLWorldTransform, 1.298 + clip, 1.299 + bufferRect, 1.300 + state.YFlipped(), 1.301 + &(sourceCrop), 1.302 + &(displayFrame))) 1.303 + { 1.304 + return true; 1.305 + } 1.306 + 1.307 + // OK! We can compose this layer with hwc. 1.308 + int current = mList ? mList->numHwLayers : 0; 1.309 + 1.310 + // Do not compose any layer below full-screen Opaque layer 1.311 + // Note: It can be generalized to non-fullscreen Opaque layers. 1.312 + bool isOpaque = (opacity == 0xFF) && (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE); 1.313 + if (current && isOpaque) { 1.314 + nsIntRect displayRect = nsIntRect(displayFrame.left, displayFrame.top, 1.315 + displayFrame.right - displayFrame.left, displayFrame.bottom - displayFrame.top); 1.316 + if (displayRect.Contains(mScreenRect)) { 1.317 + // In z-order, all previous layers are below 1.318 + // the current layer. We can ignore them now. 1.319 + mList->numHwLayers = current = 0; 1.320 + mHwcLayerMap.Clear(); 1.321 + } 1.322 + } 1.323 + 1.324 + if (!mList || current >= mMaxLayerCount) { 1.325 + if (!ReallocLayerList() || current >= mMaxLayerCount) { 1.326 + LOGE("PrepareLayerList failed! Could not increase the maximum layer count"); 1.327 + return false; 1.328 + } 1.329 + } 1.330 + 1.331 + HwcLayer& hwcLayer = mList->hwLayers[current]; 1.332 + hwcLayer.flags = 0; 1.333 + 1.334 + if (ContainerLayer* parent = aLayer->GetParent()) { 1.335 + if (parent->UseIntermediateSurface()) { 1.336 + LOGD("Parent container needs intermediate surface"); 1.337 + hwcLayer.flags = HWC_SKIP_LAYER; 1.338 +#if ANDROID_VERSION < 18 1.339 + // No partial HWC Composition on older versions 1.340 + return false; 1.341 +#endif 1.342 + } 1.343 + } 1.344 + 1.345 + hwcLayer.displayFrame = displayFrame; 1.346 + setCrop(&hwcLayer, sourceCrop); 1.347 + buffer_handle_t handle = fillColor ? nullptr : state.mSurface->getNativeBuffer()->handle; 1.348 + hwcLayer.handle = handle; 1.349 + 1.350 + hwcLayer.hints = 0; 1.351 + hwcLayer.blending = isOpaque ? HWC_BLENDING_NONE : HWC_BLENDING_PREMULT; 1.352 +#if ANDROID_VERSION >= 17 1.353 + hwcLayer.compositionType = HWC_FRAMEBUFFER; 1.354 + 1.355 + hwcLayer.acquireFenceFd = -1; 1.356 + hwcLayer.releaseFenceFd = -1; 1.357 +#if ANDROID_VERSION >= 18 1.358 + hwcLayer.planeAlpha = opacity; 1.359 +#endif 1.360 +#else 1.361 + hwcLayer.compositionType = HwcUtils::HWC_USE_COPYBIT; 1.362 +#endif 1.363 + 1.364 + if (!fillColor) { 1.365 + if (state.FormatRBSwapped()) { 1.366 + if (!mRBSwapSupport) { 1.367 + LOGD("No R/B swap support in H/W Composer"); 1.368 + return false; 1.369 + } 1.370 + hwcLayer.flags |= HwcUtils::HWC_FORMAT_RB_SWAP; 1.371 + } 1.372 + 1.373 + // Translation and scaling have been addressed in PrepareLayerRects(). 1.374 + // Given the above and that we checked for PreservesAxisAlignedRectangles() 1.375 + // the only possible transformations left to address are 1.376 + // square angle rotation and horizontal/vertical reflection. 1.377 + // 1.378 + // The rotation and reflection permutations total 16 but can be 1.379 + // reduced to 8 transformations after eliminating redundancies. 1.380 + // 1.381 + // All matrices represented here are in the form 1.382 + // 1.383 + // | xx xy | 1.384 + // | yx yy | 1.385 + // 1.386 + // And ignore scaling. 1.387 + // 1.388 + // Reflection is applied before rotation 1.389 + gfxMatrix rotation = transform * aGLWorldTransform; 1.390 + // Compute fuzzy zero like PreservesAxisAlignedRectangles() 1.391 + if (fabs(rotation.xx) < 1e-6) { 1.392 + if (rotation.xy < 0) { 1.393 + if (rotation.yx > 0) { 1.394 + // 90 degree rotation 1.395 + // 1.396 + // | 0 -1 | 1.397 + // | 1 0 | 1.398 + // 1.399 + hwcLayer.transform = HWC_TRANSFORM_ROT_90; 1.400 + LOGD("Layer rotated 90 degrees"); 1.401 + } 1.402 + else { 1.403 + // Horizontal reflection then 90 degree rotation 1.404 + // 1.405 + // | 0 -1 | | -1 0 | = | 0 -1 | 1.406 + // | 1 0 | | 0 1 | | -1 0 | 1.407 + // 1.408 + // same as vertical reflection then 270 degree rotation 1.409 + // 1.410 + // | 0 1 | | 1 0 | = | 0 -1 | 1.411 + // | -1 0 | | 0 -1 | | -1 0 | 1.412 + // 1.413 + hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_H; 1.414 + LOGD("Layer vertically reflected then rotated 270 degrees"); 1.415 + } 1.416 + } else { 1.417 + if (rotation.yx < 0) { 1.418 + // 270 degree rotation 1.419 + // 1.420 + // | 0 1 | 1.421 + // | -1 0 | 1.422 + // 1.423 + hwcLayer.transform = HWC_TRANSFORM_ROT_270; 1.424 + LOGD("Layer rotated 270 degrees"); 1.425 + } 1.426 + else { 1.427 + // Vertical reflection then 90 degree rotation 1.428 + // 1.429 + // | 0 1 | | -1 0 | = | 0 1 | 1.430 + // | -1 0 | | 0 1 | | 1 0 | 1.431 + // 1.432 + // Same as horizontal reflection then 270 degree rotation 1.433 + // 1.434 + // | 0 -1 | | 1 0 | = | 0 1 | 1.435 + // | 1 0 | | 0 -1 | | 1 0 | 1.436 + // 1.437 + hwcLayer.transform = HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_FLIP_V; 1.438 + LOGD("Layer horizontally reflected then rotated 270 degrees"); 1.439 + } 1.440 + } 1.441 + } else if (rotation.xx < 0) { 1.442 + if (rotation.yy > 0) { 1.443 + // Horizontal reflection 1.444 + // 1.445 + // | -1 0 | 1.446 + // | 0 1 | 1.447 + // 1.448 + hwcLayer.transform = HWC_TRANSFORM_FLIP_H; 1.449 + LOGD("Layer rotated 180 degrees"); 1.450 + } 1.451 + else { 1.452 + // 180 degree rotation 1.453 + // 1.454 + // | -1 0 | 1.455 + // | 0 -1 | 1.456 + // 1.457 + // Same as horizontal and vertical reflection 1.458 + // 1.459 + // | -1 0 | | 1 0 | = | -1 0 | 1.460 + // | 0 1 | | 0 -1 | | 0 -1 | 1.461 + // 1.462 + hwcLayer.transform = HWC_TRANSFORM_ROT_180; 1.463 + LOGD("Layer rotated 180 degrees"); 1.464 + } 1.465 + } else { 1.466 + if (rotation.yy < 0) { 1.467 + // Vertical reflection 1.468 + // 1.469 + // | 1 0 | 1.470 + // | 0 -1 | 1.471 + // 1.472 + hwcLayer.transform = HWC_TRANSFORM_FLIP_V; 1.473 + LOGD("Layer rotated 180 degrees"); 1.474 + } 1.475 + else { 1.476 + // No rotation or reflection 1.477 + // 1.478 + // | 1 0 | 1.479 + // | 0 1 | 1.480 + // 1.481 + hwcLayer.transform = 0; 1.482 + } 1.483 + } 1.484 + 1.485 + if (state.YFlipped()) { 1.486 + // Invert vertical reflection flag if it was already set 1.487 + hwcLayer.transform ^= HWC_TRANSFORM_FLIP_V; 1.488 + } 1.489 + hwc_region_t region; 1.490 + if (visibleRegion.GetNumRects() > 1) { 1.491 + mVisibleRegions.push_back(HwcUtils::RectVector()); 1.492 + HwcUtils::RectVector* visibleRects = &(mVisibleRegions.back()); 1.493 + if(!HwcUtils::PrepareVisibleRegion(visibleRegion, 1.494 + transform * aGLWorldTransform, 1.495 + clip, 1.496 + bufferRect, 1.497 + visibleRects)) { 1.498 + return true; 1.499 + } 1.500 + region.numRects = visibleRects->size(); 1.501 + region.rects = &((*visibleRects)[0]); 1.502 + } else { 1.503 + region.numRects = 1; 1.504 + region.rects = &(hwcLayer.displayFrame); 1.505 + } 1.506 + hwcLayer.visibleRegionScreen = region; 1.507 + } else { 1.508 + hwcLayer.flags |= HwcUtils::HWC_COLOR_FILL; 1.509 + ColorLayer* colorLayer = aLayer->AsColorLayer(); 1.510 + if (colorLayer->GetColor().a < 1.0) { 1.511 + LOGD("Color layer has semitransparency which is unsupported"); 1.512 + return false; 1.513 + } 1.514 + hwcLayer.transform = colorLayer->GetColor().Packed(); 1.515 + } 1.516 + 1.517 + mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData())); 1.518 + mList->numHwLayers++; 1.519 + return true; 1.520 +} 1.521 + 1.522 + 1.523 +#if ANDROID_VERSION >= 17 1.524 +bool 1.525 +HwcComposer2D::TryHwComposition() 1.526 +{ 1.527 + FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface()); 1.528 + 1.529 + if (!(fbsurface && fbsurface->lastHandle)) { 1.530 + LOGD("H/W Composition failed. FBSurface not initialized."); 1.531 + return false; 1.532 + } 1.533 + 1.534 + // Add FB layer 1.535 + int idx = mList->numHwLayers++; 1.536 + if (idx >= mMaxLayerCount) { 1.537 + if (!ReallocLayerList() || idx >= mMaxLayerCount) { 1.538 + LOGE("TryHwComposition failed! Could not add FB layer"); 1.539 + return false; 1.540 + } 1.541 + } 1.542 + 1.543 + Prepare(fbsurface->lastHandle, -1); 1.544 + 1.545 + /* Possible composition paths, after hwc prepare: 1.546 + 1. GPU Composition 1.547 + 2. BLIT Composition 1.548 + 3. Full OVERLAY Composition 1.549 + 4. Partial OVERLAY Composition (GPU + OVERLAY) */ 1.550 + 1.551 + bool gpuComposite = false; 1.552 + bool blitComposite = false; 1.553 + bool overlayComposite = true; 1.554 + 1.555 + for (int j=0; j < idx; j++) { 1.556 + if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER || 1.557 + mList->hwLayers[j].compositionType == HWC_BLIT) { 1.558 + // Full OVERLAY composition is not possible on this frame 1.559 + // It is either GPU / BLIT / partial OVERLAY composition. 1.560 + overlayComposite = false; 1.561 + break; 1.562 + } 1.563 + } 1.564 + 1.565 + if (!overlayComposite) { 1.566 + for (int k=0; k < idx; k++) { 1.567 + switch (mList->hwLayers[k].compositionType) { 1.568 + case HWC_FRAMEBUFFER: 1.569 + gpuComposite = true; 1.570 + break; 1.571 + case HWC_BLIT: 1.572 + blitComposite = true; 1.573 + break; 1.574 + case HWC_OVERLAY: 1.575 + // HWC will compose HWC_OVERLAY layers in partial 1.576 + // Overlay Composition, set layer composition flag 1.577 + // on mapped LayerComposite to skip GPU composition 1.578 + mHwcLayerMap[k]->SetLayerComposited(true); 1.579 + if ((mList->hwLayers[k].hints & HWC_HINT_CLEAR_FB) && 1.580 + (mList->hwLayers[k].blending == HWC_BLENDING_NONE)) { 1.581 + // Clear visible rect on FB with transparent pixels. 1.582 + hwc_rect_t r = mList->hwLayers[k].displayFrame; 1.583 + mHwcLayerMap[k]->SetClearRect(nsIntRect(r.left, r.top, 1.584 + r.right - r.left, 1.585 + r.bottom - r.top)); 1.586 + } 1.587 + break; 1.588 + default: 1.589 + break; 1.590 + } 1.591 + } 1.592 + 1.593 + if (gpuComposite) { 1.594 + // GPU or partial OVERLAY Composition 1.595 + return false; 1.596 + } else if (blitComposite) { 1.597 + // BLIT Composition, flip FB target 1.598 + GetGonkDisplay()->UpdateFBSurface(mDpy, mSur); 1.599 + FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface()); 1.600 + if (!fbsurface) { 1.601 + LOGE("H/W Composition failed. NULL FBSurface."); 1.602 + return false; 1.603 + } 1.604 + mList->hwLayers[idx].handle = fbsurface->lastHandle; 1.605 + mList->hwLayers[idx].acquireFenceFd = fbsurface->GetPrevFBAcquireFd(); 1.606 + } 1.607 + } 1.608 + 1.609 + // BLIT or full OVERLAY Composition 1.610 + Commit(); 1.611 + 1.612 + GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[idx].releaseFenceFd); 1.613 + return true; 1.614 +} 1.615 + 1.616 +bool 1.617 +HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur) 1.618 +{ 1.619 + if (!mList) { 1.620 + // After boot, HWC list hasn't been created yet 1.621 + return GetGonkDisplay()->SwapBuffers(dpy, sur); 1.622 + } 1.623 + 1.624 + GetGonkDisplay()->UpdateFBSurface(dpy, sur); 1.625 + 1.626 + FramebufferSurface* fbsurface = (FramebufferSurface*)(GetGonkDisplay()->GetFBSurface()); 1.627 + if (!fbsurface) { 1.628 + LOGE("H/W Composition failed. FBSurface not initialized."); 1.629 + return false; 1.630 + } 1.631 + 1.632 + if (mPrepared) { 1.633 + // No mHwc prepare, if already prepared in current draw cycle 1.634 + mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle; 1.635 + mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->GetPrevFBAcquireFd(); 1.636 + } else { 1.637 + mList->flags = HWC_GEOMETRY_CHANGED; 1.638 + mList->numHwLayers = 2; 1.639 + mList->hwLayers[0].hints = 0; 1.640 + mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER; 1.641 + mList->hwLayers[0].flags = HWC_SKIP_LAYER; 1.642 + mList->hwLayers[0].backgroundColor = {0}; 1.643 + mList->hwLayers[0].acquireFenceFd = -1; 1.644 + mList->hwLayers[0].releaseFenceFd = -1; 1.645 + mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height}; 1.646 + Prepare(fbsurface->lastHandle, fbsurface->GetPrevFBAcquireFd()); 1.647 + } 1.648 + 1.649 + // GPU or partial HWC Composition 1.650 + Commit(); 1.651 + 1.652 + GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd); 1.653 + return true; 1.654 +} 1.655 + 1.656 +void 1.657 +HwcComposer2D::Prepare(buffer_handle_t fbHandle, int fence) 1.658 +{ 1.659 + int idx = mList->numHwLayers - 1; 1.660 + const hwc_rect_t r = {0, 0, mScreenRect.width, mScreenRect.height}; 1.661 + hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr }; 1.662 + 1.663 + displays[HWC_DISPLAY_PRIMARY] = mList; 1.664 + mList->outbufAcquireFenceFd = -1; 1.665 + mList->outbuf = nullptr; 1.666 + mList->retireFenceFd = -1; 1.667 + 1.668 + mList->hwLayers[idx].hints = 0; 1.669 + mList->hwLayers[idx].flags = 0; 1.670 + mList->hwLayers[idx].transform = 0; 1.671 + mList->hwLayers[idx].handle = fbHandle; 1.672 + mList->hwLayers[idx].blending = HWC_BLENDING_PREMULT; 1.673 + mList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET; 1.674 + setCrop(&mList->hwLayers[idx], r); 1.675 + mList->hwLayers[idx].displayFrame = r; 1.676 + mList->hwLayers[idx].visibleRegionScreen.numRects = 1; 1.677 + mList->hwLayers[idx].visibleRegionScreen.rects = &mList->hwLayers[idx].displayFrame; 1.678 + mList->hwLayers[idx].acquireFenceFd = fence; 1.679 + mList->hwLayers[idx].releaseFenceFd = -1; 1.680 +#if ANDROID_VERSION >= 18 1.681 + mList->hwLayers[idx].planeAlpha = 0xFF; 1.682 +#endif 1.683 + if (mPrepared) { 1.684 + LOGE("Multiple hwc prepare calls!"); 1.685 + } 1.686 + mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays); 1.687 + mPrepared = true; 1.688 +} 1.689 + 1.690 +bool 1.691 +HwcComposer2D::Commit() 1.692 +{ 1.693 + hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr }; 1.694 + displays[HWC_DISPLAY_PRIMARY] = mList; 1.695 + 1.696 + int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays); 1.697 + 1.698 + mPrevDisplayFence = mPrevRetireFence; 1.699 + mPrevRetireFence = Fence::NO_FENCE; 1.700 + 1.701 + for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) { 1.702 + if (mList->hwLayers[j].releaseFenceFd >= 0) { 1.703 + int fd = mList->hwLayers[j].releaseFenceFd; 1.704 + mList->hwLayers[j].releaseFenceFd = -1; 1.705 + sp<Fence> fence = new Fence(fd); 1.706 + 1.707 + LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState(); 1.708 + if (!state.mTexture) { 1.709 + continue; 1.710 + } 1.711 + TextureHostOGL* texture = state.mTexture->AsHostOGL(); 1.712 + if (!texture) { 1.713 + continue; 1.714 + } 1.715 + texture->SetReleaseFence(fence); 1.716 + } 1.717 + } 1.718 + 1.719 + if (mList->retireFenceFd >= 0) { 1.720 + mPrevRetireFence = new Fence(mList->retireFenceFd); 1.721 + } 1.722 + 1.723 + mPrepared = false; 1.724 + return !err; 1.725 +} 1.726 + 1.727 +void 1.728 +HwcComposer2D::Reset() 1.729 +{ 1.730 + LOGD("hwcomposer is already prepared, reset with null set"); 1.731 + hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr }; 1.732 + displays[HWC_DISPLAY_PRIMARY] = nullptr; 1.733 + mHwc->set(mHwc, HWC_DISPLAY_PRIMARY, displays); 1.734 + mPrepared = false; 1.735 +} 1.736 +#else 1.737 +bool 1.738 +HwcComposer2D::TryHwComposition() 1.739 +{ 1.740 + return !mHwc->set(mHwc, mDpy, mSur, mList); 1.741 +} 1.742 + 1.743 +bool 1.744 +HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur) 1.745 +{ 1.746 + return GetGonkDisplay()->SwapBuffers(dpy, sur); 1.747 +} 1.748 + 1.749 +void 1.750 +HwcComposer2D::Reset() 1.751 +{ 1.752 + mPrepared = false; 1.753 +} 1.754 +#endif 1.755 + 1.756 +bool 1.757 +HwcComposer2D::TryRender(Layer* aRoot, 1.758 + const gfx::Matrix& GLWorldTransform, 1.759 + bool aGeometryChanged) 1.760 +{ 1.761 + gfxMatrix aGLWorldTransform = ThebesMatrix(GLWorldTransform); 1.762 + if (!aGLWorldTransform.PreservesAxisAlignedRectangles()) { 1.763 + LOGD("Render aborted. World transform has non-square angle rotation"); 1.764 + return false; 1.765 + } 1.766 + 1.767 + MOZ_ASSERT(Initialized()); 1.768 + if (mList) { 1.769 + setHwcGeometry(aGeometryChanged); 1.770 + mList->numHwLayers = 0; 1.771 + mHwcLayerMap.Clear(); 1.772 + } 1.773 + 1.774 + if (mPrepared) { 1.775 + Reset(); 1.776 + } 1.777 + 1.778 + // XXX: The clear() below means all rect vectors will be have to be 1.779 + // reallocated. We may want to avoid this if possible 1.780 + mVisibleRegions.clear(); 1.781 + 1.782 + MOZ_ASSERT(mHwcLayerMap.IsEmpty()); 1.783 + if (!PrepareLayerList(aRoot, 1.784 + mScreenRect, 1.785 + gfxMatrix(), 1.786 + aGLWorldTransform)) 1.787 + { 1.788 + LOGD("Render aborted. Nothing was drawn to the screen"); 1.789 + return false; 1.790 + } 1.791 + 1.792 + if (!TryHwComposition()) { 1.793 + LOGD("H/W Composition failed"); 1.794 + return false; 1.795 + } 1.796 + 1.797 + LOGD("Frame rendered"); 1.798 + return true; 1.799 +} 1.800 + 1.801 +} // namespace mozilla