环境:
OS: Android4.1
Chipset:MSM8X25Q
mdp:3.03
背景:
屏幕反着打,需要显示旋转180°。
旋转方案:
1. 通过lcd driver ic直接让屏幕旋转。
2. 通过mdp旋转。
3. Framework旋转。
调试过程:
方案1:
由于玻璃是单扫描方向,如果直接将driver IC反着扫,也就是说从IC
的memory里反着取数据,而玻璃还是正着扫描的话,结果就会产生
Tearing。此方案理论上直接行不通。
方案2:
在mdp_ppp.c传参数flip_v+flip_h给mdp register,告诉ppp模块
在使用mdp composition旋转180°。
考虑到GPU的composition会绕过mdp的ppp模块,因此将debug.composition.type
改成mdp,也就是想让系统全部用mdp去做composition.
事实上,有些特殊情况,mdp是无法处理的,像alpha不是完全透明的,
旋转太复杂的等。这也可以从framework中的代码里的注释看到:
voidLayer::setGeometry(hwc_layer_t* hwcl)
{
~~snip
//we can't do alpha-fade with the hwc HAL
const State& s(drawingState());
if (s.alpha < 0xFF) {
hwcl->flags = HWC_SKIP_LAYER; //表示用GPU做composition
}
~~snip
//we can only handle simple transformation
if (finalTransform &Transform::ROT_INVALID) {
hwcl->flags = HWC_SKIP_LAYER;
} else {
hwcl->transform = finalTransform;
}
~~snip
}
因此,走GPU的时候又恢复成0°画面了,此方案也行不通了。
方案3:
SF中提供了一个property来设置orientation,如90°,270°,
设置了180°之后,竖屏画面ok,不幸的是当进入横屏或者退出横屏的
时候,会瞬间显示成0°的画面。就是这个问题,花了我一周工作日时间才
搞定。下面是调试过程,中间省略N步…
a) 在进入或者退出横屏前过滤掉N帧。测试发现有时候进入横屏游戏卡的时候
这种方法是行不通的。
b) 设置debug.composition.type为GPU,无效。设置成mdp,然后将HWC_SKIP_LAYER
类型的都改成用mdp来处理,发现瞬间的画面虽然还是有,但是已经不是0°了,说明
跟这个flag有关啊!
c) 另外发现HWC_SKIP_LAYER和transform(坐标矩阵变换),也就是orientation有关联,
接着只能要细看SF的处理流程了,中间就是看一段觉得可疑就修改下加log,看和改参数之类的,无效。
d) 再者在composeSurfaces()中发现旋转的时候,要处理的layer其中总有一个的orientation和
另外的值不一样,比较了和不旋转180°的log,似乎也这样,就没太怀疑。
e) 从b)的过程能看出和GPU的处理有关,另外,网上有篇blog提到当旋转的时候,系统会先将屏幕
恢复成0°,然后再作旋转。可是它的codebase是GB,我使用的JB中并没有这部分,没办法,
继续往opengl中追。一直看到送给/dev/graphics/fb0也没发现有处理transform的地方。所以应该不是这个问题了。
f) 从log中发现LayerBase::setGeometry有不被Layer::setGeometry调用的状况,看来还有其他类型的layer创建了呀!
g) 跟踪发现,在旋转的时候居然创建了layerscrenshot这种Layer,而这种layer的纹理处理和一般的layer是不一样的,终于找到问题了!
改动如下:
LayerScreenshot.cpp
void LayerScreenshot::initTexture(GLfloat u, GLfloat v) {
ALOGE("LayerScreenshot::initTexture");
glBindTexture(GL_TEXTURE_2D, mTextureName);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef SF_ROTATION_180
mTexCoords[0] = 0; mTexCoords[1] = v;
mTexCoords[2] = 0; mTexCoords[3] = 0;
mTexCoords[4] = u; mTexCoords[5] = 0;
mTexCoords[6] = u; mTexCoords[7] = v;
#else
mTexCoords[0] = u; mTexCoords[1] = 0;
mTexCoords[2] = u; mTexCoords[3] = v;
mTexCoords[4] = 0; mTexCoords[5] = v;
mTexCoords[6] = 0; mTexCoords[7] = 0;
#endif
}