Bug 810334: Honor layer clip rects in HwcComposer2D. r=vlad a=cjones

This commit is contained in:
Diego Wilson 2013-01-17 13:34:01 -08:00
Родитель a1377a76d9
Коммит a0d13480f7
2 изменённых файлов: 78 добавлений и 76 удалений

Просмотреть файл

@ -15,8 +15,6 @@
*/
#include <android/log.h>
#include <EGL/egl.h>
#include <hardware/hardware.h>
#include "Framebuffer.h"
#include "HwcComposer2D.h"
@ -24,10 +22,8 @@
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
#include "mozilla/StaticPtr.h"
#include "nsIScreenManager.h"
#include "nsMathUtils.h"
#include "nsServiceManagerUtils.h"
#include "cutils/properties.h"
#include "gfxUtils.h"
#define LOG_TAG "HWComposer"
@ -85,8 +81,7 @@ HwcComposer2D::Init(hwc_display_t dpy, hwc_surface_t sur)
nsIntSize screenSize;
mozilla::Framebuffer::GetSize(&screenSize);
mScreenWidth = screenSize.width;
mScreenHeight = screenSize.height;
mScreenRect = nsIntRect(nsIntPoint(0, 0), screenSize);
char propValue[PROPERTY_VALUE_MAX];
property_get("ro.display.colorfill", propValue, "0");
@ -131,45 +126,6 @@ HwcComposer2D::ReallocLayerList()
return true;
}
int
HwcComposer2D::GetRotation()
{
int halrotation = 0;
uint32_t screenrotation;
if (!mScreen) {
nsCOMPtr<nsIScreenManager> screenMgr =
do_GetService("@mozilla.org/gfx/screenmanager;1");
if (screenMgr) {
screenMgr->GetPrimaryScreen(getter_AddRefs(mScreen));
}
}
if (mScreen) {
if (NS_SUCCEEDED(mScreen->GetRotation(&screenrotation))) {
switch (screenrotation) {
case nsIScreen::ROTATION_0_DEG:
halrotation = 0;
break;
case nsIScreen::ROTATION_90_DEG:
halrotation = HWC_TRANSFORM_ROT_90;
break;
case nsIScreen::ROTATION_180_DEG:
halrotation = HWC_TRANSFORM_ROT_180;
break;
case nsIScreen::ROTATION_270_DEG:
halrotation = HWC_TRANSFORM_ROT_270;
break;
}
}
}
return halrotation;
}
/**
* Sets hwc layer rectangles required for hwc composition
*
@ -237,9 +193,51 @@ PrepareLayerRects(nsIntRect aVisible, const gfxMatrix& aTransform,
return true;
}
/**
* Calculates the layer's clipping rectangle
*
* @param aTransform Input. A transformation matrix
* It transforms the clip rect to screen space
* @param aLayerClip Input. The layer's internal clipping rectangle.
* This may be NULL which means the layer has no internal clipping
* The origin is the top-left corner of the layer
* @param aParentClip Input. The parent layer's rendering clipping rectangle
* The origin is the top-left corner of the screen
* @param aRenderClip Output. The layer's rendering clipping rectangle
* The origin is the top-left corner of the screen
* @return true if the layer should be rendered.
* false if the layer can be skipped
*/
static bool
CalculateClipRect(const gfxMatrix& aTransform, const nsIntRect* aLayerClip,
nsIntRect aParentClip, nsIntRect* aRenderClip) {
*aRenderClip = aParentClip;
if (!aLayerClip) {
return true;
}
if (aLayerClip->IsEmpty()) {
return false;
}
nsIntRect clip = *aLayerClip;
gfxRect r(clip);
gfxRect trClip = aTransform.TransformBounds(r);
trClip.Round();
gfxUtils::GfxRectToIntRect(trClip, &clip);
aRenderClip->IntersectRect(*aRenderClip, clip);
return true;
}
bool
HwcComposer2D::PrepareLayerList(Layer* aLayer,
const nsIntRect& aClip)
const nsIntRect& aClip,
const gfxMatrix& aParentTransform,
const gfxMatrix& aGLWorldTransform)
{
// NB: we fall off this path whenever there are container layers
// that require intermediate surfaces. That means all the
@ -268,6 +266,23 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
return false;
}
nsIntRect clip;
if (!CalculateClipRect(aParentTransform * aGLWorldTransform,
aLayer->GetEffectiveClipRect(),
aClip,
&clip))
{
LOGD("Clip rect is empty. Skip layer");
return true;
}
gfxMatrix transform;
const gfx3DMatrix& transform3D = aLayer->GetEffectiveTransform();
if (!transform3D.Is2D(&transform) || !transform.PreservesAxisAlignedRectangles()) {
LOGD("Layer has a 3D transform or a non-square angle rotation");
return false;
}
if (ContainerLayer* container = aLayer->AsContainerLayer()) {
if (container->UseIntermediateSurface()) {
@ -277,9 +292,8 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
nsAutoTArray<Layer*, 12> children;
container->SortChildrenBy3DZOrder(children);
//FIXME/bug 810334
for (uint32_t i = 0; i < children.Length(); i++) {
if (!PrepareLayerList(children[i], aClip)) {
if (!PrepareLayerList(children[i], clip, transform, aGLWorldTransform)) {
return false;
}
}
@ -303,12 +317,6 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
return false;
}
gfxMatrix transform;
const gfx3DMatrix& transform3D = aLayer->GetEffectiveTransform();
if (!transform3D.Is2D(&transform) || !transform.PreservesAxisAlignedRectangles()) {
LOGD("Layer has a 3D transform or a non-square angle rotation");
return false;
}
// OK! We can compose this layer with hwc.
@ -339,9 +347,13 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
hwc_layer_t& hwcLayer = mList->hwLayers[current];
//FIXME/bug 810334
if(!PrepareLayerRects(visibleRect, transform, aClip, bufferRect,
&(hwcLayer.sourceCrop), &(hwcLayer.displayFrame))) {
if(!PrepareLayerRects(visibleRect,
transform * aGLWorldTransform,
clip,
bufferRect,
&(hwcLayer.sourceCrop),
&(hwcLayer.displayFrame)))
{
return true;
}
@ -392,20 +404,12 @@ HwcComposer2D::TryRender(Layer* aRoot,
if (mList) {
mList->numHwLayers = 0;
}
// XXX use GL world transform instead of GetRotation()
int rotation = GetRotation();
int fbHeight, fbWidth;
if (rotation == 0 || rotation == HWC_TRANSFORM_ROT_180) {
fbWidth = mScreenWidth;
fbHeight = mScreenHeight;
} else {
fbWidth = mScreenHeight;
fbHeight = mScreenWidth;
}
if (!PrepareLayerList(aRoot, nsIntRect(0, 0, fbWidth, fbHeight))) {
if (!PrepareLayerList(aRoot,
mScreenRect,
gfxMatrix(),
aGLWorldTransform))
{
LOGD("Render aborted. Nothing was drawn to the screen");
return false;
}

Просмотреть файл

@ -20,7 +20,6 @@
#include "Composer2D.h"
#include "HWComposer.h"
#include "Layers.h"
#include "nsIScreen.h"
namespace mozilla {
@ -48,12 +47,11 @@ public:
private:
bool ReallocLayerList();
bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip);
int GetRotation();
bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
const gfxMatrix& aParentTransform, const gfxMatrix& aGLWorldTransform);
hwc_layer_list_t* mList;
nsCOMPtr<nsIScreen> mScreen;
int mScreenWidth, mScreenHeight;
nsIntRect mScreenRect;
int mMaxLayerCount;
bool mColorFill;
};