summaryrefslogtreecommitdiff
path: root/widget/gonk/HwcUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gonk/HwcUtils.cpp')
-rw-r--r--widget/gonk/HwcUtils.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/widget/gonk/HwcUtils.cpp b/widget/gonk/HwcUtils.cpp
new file mode 100644
index 0000000000..a8f030f3c0
--- /dev/null
+++ b/widget/gonk/HwcUtils.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/log.h>
+#include "HwcUtils.h"
+#include "gfxUtils.h"
+#include "gfx2DGlue.h"
+
+#define LOG_TAG "HwcUtils"
+
+#if (LOG_NDEBUG == 0)
+#define LOGD(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ## args)
+#else
+#define LOGD(args...) ((void)0)
+#endif
+
+#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, ## args)
+
+
+namespace mozilla {
+
+/* Utility functions for HwcComposer */
+
+
+
+/* static */ bool
+HwcUtils::PrepareLayerRects(nsIntRect aVisible,
+ const gfx::Matrix& aLayerTransform,
+ const gfx::Matrix& aLayerBufferTransform,
+ nsIntRect aClip, nsIntRect aBufferRect,
+ bool aYFlipped,
+ hwc_rect_t* aSourceCrop, hwc_rect_t* aVisibleRegionScreen) {
+
+ gfxMatrix aTransform = gfx::ThebesMatrix(aLayerTransform);
+ gfxRect visibleRect(ThebesRect(aVisible));
+ gfxRect clip(ThebesRect(aClip));
+ gfxRect visibleRectScreen = aTransform.TransformBounds(visibleRect);
+ // |clip| is guaranteed to be integer
+ visibleRectScreen.IntersectRect(visibleRectScreen, clip);
+
+ if (visibleRectScreen.IsEmpty()) {
+ return false;
+ }
+
+ gfxMatrix inverse = gfx::ThebesMatrix(aLayerBufferTransform);
+ inverse.Invert();
+ gfxRect crop = inverse.TransformBounds(visibleRectScreen);
+
+ //clip to buffer size
+ crop.IntersectRect(crop, ThebesRect(aBufferRect));
+ crop.Round();
+
+ if (crop.IsEmpty()) {
+ return false;
+ }
+
+ //propagate buffer clipping back to visible rect
+ gfxMatrix layerBufferTransform = gfx::ThebesMatrix(aLayerBufferTransform);
+ visibleRectScreen = layerBufferTransform.TransformBounds(crop);
+ visibleRectScreen.Round();
+
+ // Map from layer space to buffer space
+ crop -= aBufferRect.TopLeft();
+ if (aYFlipped) {
+ crop.y = aBufferRect.height - (crop.y + crop.height);
+ }
+
+ aSourceCrop->left = crop.x;
+ aSourceCrop->top = crop.y;
+ aSourceCrop->right = crop.x + crop.width;
+ aSourceCrop->bottom = crop.y + crop.height;
+
+ aVisibleRegionScreen->left = visibleRectScreen.x;
+ aVisibleRegionScreen->top = visibleRectScreen.y;
+ aVisibleRegionScreen->right = visibleRectScreen.x + visibleRectScreen.width;
+ aVisibleRegionScreen->bottom = visibleRectScreen.y + visibleRectScreen.height;
+
+ return true;
+}
+
+/* static */ bool
+HwcUtils::PrepareVisibleRegion(const nsIntRegion& aVisible,
+ const gfx::Matrix& aLayerTransform,
+ const gfx::Matrix& aLayerBufferTransform,
+ nsIntRect aClip, nsIntRect aBufferRect,
+ RectVector* aVisibleRegionScreen,
+ bool& aIsVisible) {
+ const float MIN_SRC_WIDTH = 2.f;
+ const float MIN_SRC_HEIGHT = 2.f;
+
+ gfxMatrix layerTransform = gfx::ThebesMatrix(aLayerTransform);
+ gfxMatrix layerBufferTransform = gfx::ThebesMatrix(aLayerBufferTransform);
+ gfxRect bufferRect =
+ layerBufferTransform.TransformBounds(ThebesRect(aBufferRect));
+ gfxMatrix inverse = gfx::ThebesMatrix(aLayerBufferTransform);
+ inverse.Invert();
+ aIsVisible = false;
+
+ for (auto iter = aVisible.RectIter(); !iter.Done(); iter.Next()) {
+ gfxRect screenRect =
+ layerTransform.TransformBounds(ThebesRect(iter.Get()));
+ screenRect.IntersectRect(screenRect, bufferRect);
+ screenRect.IntersectRect(screenRect, ThebesRect(aClip));
+ screenRect.Round();
+ if (screenRect.IsEmpty()) {
+ continue;
+ }
+
+ hwc_rect_t visibleRectScreen;
+ visibleRectScreen.left = screenRect.x;
+ visibleRectScreen.top = screenRect.y;
+ visibleRectScreen.right = screenRect.XMost();
+ visibleRectScreen.bottom = screenRect.YMost();
+
+ gfxRect srcCrop = inverse.TransformBounds(screenRect);
+ // When src crop is very small, HWC could not render correctly in some cases.
+ // See Bug 1169093
+ if(srcCrop.Width() < MIN_SRC_WIDTH || srcCrop.Height() < MIN_SRC_HEIGHT) {
+ return false;
+ }
+
+ aVisibleRegionScreen->push_back(visibleRectScreen);
+ aIsVisible = true;
+ }
+
+ return true;
+}
+
+/* static */ bool
+HwcUtils::CalculateClipRect(const gfx::Matrix& transform,
+ const nsIntRect* aLayerClip,
+ nsIntRect aParentClip, nsIntRect* aRenderClip) {
+
+ gfxMatrix aTransform = gfx::ThebesMatrix(transform);
+ *aRenderClip = aParentClip;
+
+ if (!aLayerClip) {
+ return true;
+ }
+
+ if (aLayerClip->IsEmpty()) {
+ return false;
+ }
+
+ nsIntRect clip = *aLayerClip;
+
+ gfxRect r = ThebesRect(clip);
+ gfxRect trClip = aTransform.TransformBounds(r);
+ trClip.Round();
+ gfxUtils::GfxRectToIntRect(trClip, &clip);
+
+ aRenderClip->IntersectRect(*aRenderClip, clip);
+ return true;
+}
+
+} // namespace mozilla