一. 上层调用SurfaceFlinger.cpp 中的函数,进行旋转操作,从这个函数开始分析。
路径:frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
//初始化
void SurfaceFlinger::init() {
//设定初始条件
initializeDisplays();
}
void SurfaceFlinger::initializeDisplays() {
flinger->onInitializeDisplays();
}
void SurfaceFlinger::onInitializeDisplays() {
//关键的函数
setTransactionState(state, displays, 0);
}
void SurfaceFlinger::setTransactionState() {
//设定旋转的标志位 通知函数SurfaceFlinger::onMessageReceived 来进行处理
}
1.SurfaceFlinger::onMessageReceived 来进行处理接收到的旋转信息。
主要包括: handleMessageTransaction();
handleMessageInvalidate();
handleMessageRefresh();
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
bool frameMissed = !mHadClientComposition &&
mPreviousPresentFence != Fence::NO_FENCE &&
mPreviousPresentFence->getSignalTime() == INT64_MAX;
ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
if (mPropagateBackpressure && frameMissed) {
signalLayerUpdate();
break;
}
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
if (refreshNeeded) {
// Signal a refresh if a transaction modified the window state,
// a new buffer was latched, or if HWC has requested a full
// repaint
signalRefresh();
}
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
1.1 SurfaceFlinger::handleMessageTransaction() 主要是设定旋转的标志位,遍历所有图层,对需要作出旋转的事务进行处理。
bool SurfaceFlinger::handleMessageTransaction() {
//这里使用到函数setTransactionState 设定的旋转标志位 进行处理
handleTransaction(transactionFlags);
}
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
//通过事务锁来提交事务
handleTransactionLocked(transactionFlags);
}
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
//遍历所有图层,对需要作出旋转的事务进行处理。
hw->setProjection(state.orientation,state.viewport, state.frame);
}
1.1.1 旋转核心函数void DisplayDevice::setProjection(int orientation,const Rect& newViewport, const Rect& newFrame):获取0度 90度 180度 270度 方向标志位,生成全局变换矩阵mGlobalTransform。
路径:frameworks\native\services\surfaceflinger\DisplayDevice.cpp
void DisplayDevice::setProjection(int orientation,
const Rect& newViewport, const Rect& newFrame) {
Rect viewport(newViewport);
Rect frame(newFrame);
#if RK_FORCE_SCALE_FULLSCREEN
ALOGV("name =%s",getDisplayName().string());
ALOGV(" viewport [%d %d] mViewport [%d %d]",viewport.getWidth(),viewport.getHeight(),mViewport.getWidth(),mViewport.getHeight());
ALOGV(" frame [%d %d]", frame.getWidth(),frame.getHeight());
ALOGV(" hw [%d %d]", getWidth(),getHeight());
bool isVirtualScreen = mType == DisplayDevice::DISPLAY_VIRTUAL;
if ((isVirtualScreen && frame.getWidth() > frame.getHeight()) ||
(viewport.getWidth()== getWidth() && viewport.getHeight() == getHeight()
&& (getWidth() != frame.getWidth() || getHeight() != frame.getHeight()))
) {
//If change the resolution,force scale to full screen.
frame = Rect(0,0,getWidth(),getHeight());
ALOGV("update frame [%d,%d]",frame.getWidth(),frame.getHeight());
}
#endif
#if !RK_VR & RK_HW_ROTATION
bool isHdmiScreen = mType == DisplayDevice::DISPLAY_EXTERNAL;
if (isHdmiScreen) {
int eInitOrientation = 0;
bool isSfHwrotated = false;
bool isSupportRotation = false;
bool isPrimaryExternalSameOrientation = false;
Rect newFrame = Rect(0,0,getWidth(),getHeight());
Rect newFrameRotated = Rect(0,0,getHeight(),getWidth());
float frameRatio = (float)frame.getWidth() / frame.getHeight();
char value[PROPERTY_VALUE_MAX];
property_get("ro.sf.hwrotation", value, "0");
isSfHwrotated = atoi(value) != 0;
property_get("ro.same.orientation", value, "false");
isPrimaryExternalSameOrientation = !strcmp(value,"true");
if(!isSfHwrotated) {
property_get("ro.orientation.einit", value, "0");
eInitOrientation = atoi(value) / 90;
property_get("ro.rotation.external", value, "false");
isSupportRotation = !strcmp(value,"true");
}
if (isSupportRotation && !isPrimaryExternalSameOrientation) {
mClientOrientation = orientation;
if (eInitOrientation % 2 == 1) {
frame = frameRatio > 1.0 ? frame : newFrameRotated;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else if (isSupportRotation) {
mClientOrientation = orientation;
if (eInitOrientation % 2 == 1) {
//frame = frameRatio > 1.0 ? frame : frame;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? newFrame : newFrameRotated;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else if (eInitOrientation % 2 != 0) {
if (isPrimaryExternalSameOrientation) {
//frame = frameRatio > 1.0 ? frame : frame;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? frame : newFrameRotated;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else if (eInitOrientation % 2 == 0) {
if (isPrimaryExternalSameOrientation) {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGI("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
property_get("persist.orientation.vhshow", value, "false");
if(!strcmp(value,"true")) {
property_get("persist.orientation.vhinit", value, "0");
eInitOrientation = atoi(value);
if(eInitOrientation == 0) {
int width,height;
width = getWidth()>getHeight() ? getWidth():getHeight();
height = width == getHeight() ? getWidth():getHeight();
frame = Rect(0,0,width, height);
} else if(eInitOrientation == 1) {
int width,height;
width = getWidth()<getHeight() ? getWidth():getHeight();
height = width == getHeight() ? getWidth():getHeight();
frame = Rect(0,0,width, height);
}
}
ALOGV("update frame [%d,%d]",frame.getWidth(),frame.getHeight());
}
if (mType == DisplayDevice::DISPLAY_PRIMARY) {
mClientOrientation = orientation;
orientation = (mHardwareOrientation + orientation) % 4;
}
#endif
const int w = mDisplayWidth;
const int h = mDisplayHeight;
Transform R;
DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
if (!frame.isValid()) {
// the destination frame can be invalid if it has never been set,
// in that case we assume the whole display frame.
frame = Rect(w, h);
}
if (viewport.isEmpty()) {
// viewport can be invalid if it has never been set, in that case
// we assume the whole display size.
// it's also invalid to have an empty viewport, so we handle that
// case in the same way.
viewport = Rect(w, h);
if (R.getOrientation() & Transform::ROT_90) {
// viewport is always specified in the logical orientation
// of the display (ie: post-rotation).
swap(viewport.right, viewport.bottom);
}
}
dirtyRegion.set(getBounds());
Transform TL, TP, S;
float src_width = viewport.width();
float src_height = viewport.height();
float dst_width = frame.width();
float dst_height = frame.height();
if (src_width != dst_width || src_height != dst_height) {
float sx = dst_width / src_width;
float sy = dst_height / src_height;
S.set(sx, 0, 0, sy);
}
float src_x = viewport.left;
float src_y = viewport.top;
float dst_x = frame.left;
float dst_y = frame.top;
TL.set(-src_x, -src_y);
TP.set(dst_x, dst_y);
// The viewport and frame are both in the logical orientation.
// Apply the logical translation, scale to physical size, apply the
// physical translation and finally rotate to the physical orientation.
mGlobalTransform = R * TP * S * TL;
#if RK_HW_ROTATION
Transform realR;
if (DisplayDevice::orientationToTransfrom(
mClientOrientation, w, h, &realR) == NO_ERROR) {
mRealGlobalTransform = realR * TP * S * TL;
}
#endif
const uint8_t type = mGlobalTransform.getType();
mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
(type >= Transform::SCALE));
mScissor = mGlobalTransform.transform(viewport);
if (mScissor.isEmpty()) {
mScissor = getBounds();
}
mOrientation = orientation;
if (mType == DisplayType::DISPLAY_PRIMARY) {
uint32_t transform = 0;
switch (mOrientation) {
case DisplayState::eOrientationDefault:
transform = Transform::ROT_0;
break;
case DisplayState::eOrientation90:
transform = Transform::ROT_90;
break;
case DisplayState::eOrientation180:
transform = Transform::ROT_180;
break;
case DisplayState::eOrientation270:
transform = Transform::ROT_270;
break;
}
sPrimaryDisplayOrientation = transform;
}
mViewport = viewport;
mFrame = frame;
}
******** 1 void DisplayDevice::setProjection(int orientation,const Rect& newViewport, const Rect& newFrame)函数生成全局变换矩阵,通过调用Transform.cpp 中的函数进行相应的矩阵变换。接下来分析在Transform.cpp 中是如何进行矩阵变换的。
路径:frameworks\native\services\surfaceflinger\Transform.cpp
(1) 可以在Transform::reset() 中对0度时的UI 进行rotation 操作,只需要改变3x3 matrix 即可。
void Transform::reset() {
// mType = IDENTITY;
// for(int i=0 ; i<3 ; i++) {
// vec3& v(mMatrix[i]);
// for (int j=0 ; j<3 ; j++)
// v[j] = ((i==j) ? 1.0f : 0.0f);
// }
mType = IDENTITY;
//mType |= SCALE;
for(int i=0 ; i<3 ; i++) {
vec3& v(mMatrix[i]);
if(i == 0) {
v[0] = 0.4f;
v[1] = 0.2f;
v[2] = 0.0f;
}
if(i == 1) {
v[0] = 0.0f;
v[1] = 0.4f;
v[2] = 0.0f;
}
if(i == 2) {
v[0] = 0.0f;
v[1] = 0.0f;
v[2] = 1.0f;
}
}
}
(2)可以在Transform::set() 模板中对0度时的UI 进行rotation scale translate操作,只需要改变3x3 matrix 即可。
void Transform::set(float tx, float ty)
{
mMatrix[2][0] = tx;
mMatrix[2][1] = ty;
mMatrix[2][2] = 1.0f;
if (isZero(tx) && isZero(ty)) {
mType &= ~TRANSLATE;
} else {
mType |= TRANSLATE;
}
}
void Transform::set(float a, float b, float c, float d)
{
mat33& M(mMatrix);
M[0][0] = a; M[1][0] = b;
M[0][1] = c; M[1][1] = d;
M[0][2] = 0; M[1][2] = 0;
mType = UNKNOWN_TYPE;
}
status_t Transform::set(uint32_t flags, float w, float h)
{
if (flags & ROT_INVALID) {
// that's not allowed!
reset();
//R.mType = ROTATE;
//R.mType |= SCALE;
//R.mType |= TRANSLATE;
/* mat33& M(R.mMatrix);
M[0][0] = 0.8f; M[1][0] = 0; M[2][0] = 0;
M[0][1] = 0; M[1][1] = 0.8f; M[2][1] = 0;
M[0][2] = 0; M[1][2] = 0; M[2][2] = 1; */
return BAD_VALUE;
}
Transform H, V, R;
if (flags & ROT_90) {
// w & h are inverted when rotating by 90 degrees
swap(w, h);
}
if (flags & FLIP_H) {
H.mType = (FLIP_H << 8) | SCALE;
H.mType |= isZero(w) ? IDENTITY : TRANSLATE;
mat33& M(H.mMatrix);
M[0][0] = -1;
M[2][0] = w;
}
if (flags & FLIP_V) {
V.mType = (FLIP_V << 8) | SCALE;
V.mType |= isZero(h) ? IDENTITY : TRANSLATE;
mat33& M(V.mMatrix);
M[1][1] = -1;
M[2][1] = h;
}
if (flags & ROT_90) {
const float original_w = h;
R.mType = (ROT_90 << 8) | ROTATE;
R.mType |= isZero(original_w) ? IDENTITY : TRANSLATE;
mat33& M(R.mMatrix);
M[0][0] = 0; M[1][0] =-1; M[2][0] = original_w;
M[0][1] = 1; M[1][1] = 0;
}
*this = (R*(H*V));
return NO_ERROR;
}
Transform类中还有许多函数,例如求逆矩阵,就不一一详述。
以上通过设定opengl matrix 进行对UI 进行相应的操作,本人只成功进行过ratation 操作,scale 以及translate 并未成功,可能是相应设定没设定对。
******** 2 在hwcomposer.cpp 同样可以对系统UI 界面进行scale 以及translate 操作。接下来分析如果通过hwcomposer设定UI 的缩放和平移。
路径:hardware\rockchip\hwcomposer\hwcomposer.cpp
(1) 平移(offset)
int xoffset = 300;(向右偏移300像素点)
int yoffset = 200;(向下偏移200像素点)
将 : hd->w_scale * sf_layer->displayFrame.left, hd->h_scale * sf_layer->displayFrame.top,
hd->w_scale * sf_layer->displayFrame.right, hd->h_scale * sf_layer->displayFrame.bottom);
修改为:
hd->w_scale * sf_layer->displayFrame.left + xoffset, hd->h_scale * sf_layer->displayFrame.top + yoffset,
hd->w_scale * sf_layer->displayFrame.right + xoffset, hd->h_scale * sf_layer->displayFrame.bottom + yoffset);
int DrmHwcLayer::InitFromHwcLayer(struct hwc_context_t *ctx, int display, hwc_layer_1_t *sf_layer, Importer *importer,
const gralloc_module_t *gralloc, bool bClone) {
if(bClone) {
//int panle_height = hd->rel_yres + hd->v_total;
//int y_offset = (panle_height - panle_height * 3 / 147) / 2 + panle_height * 3 / 147;
int y_offset = hd->v_total;
display_frame = DrmHwcRect<int>(
hd->w_scale * sf_layer->displayFrame.left, hd->h_scale * sf_layer- >displayFrame.top + y_offset,
hd->w_scale * sf_layer->displayFrame.right, hd->h_scale * sf_layer->displayFrame.bottom + y_offset);
}else {
if(stereo == FPS_3D)
{
int y_offset = hd->v_total;
display_frame = DrmHwcRect<int>(
hd->w_scale * sf_layer->displayFrame.left, hd->h_scale * sf_layer->displayFrame.top,
hd->w_scale * sf_layer->displayFrame.right, hd->h_scale * sf_layer->displayFrame.bottom + y_offset);
}else {
//设定平移的参数,以图像左上角为原点,向右向下为正
int xoffset = 300;
int yoffset = 200;
display_frame = DrmHwcRect<int>(
//hd->w_scale * sf_layer->displayFrame.left, hd->h_scale * sf_layer->displayFrame.top,
//hd->w_scale * sf_layer->displayFrame.right, hd->h_scale * sf_layer->displayFrame.bottom);
hd->w_scale * sf_layer->displayFrame.left + xoffset, hd->h_scale * sf_layer->displayFrame.top + yoffset,
hd->w_scale * sf_layer->displayFrame.right + xoffset, hd->h_scale * sf_layer->displayFrame.bottom + yoffset);
}
}
}
(2) 缩放(scale)
将 : hd->w_scale = (float)mode.h_display() / hd->framebuffer_width;
hd->h_scale = (float)mode.v_display() / hd->framebuffer_height;
修改为:
hd->w_scale = 1.0;(如果缩小一半,就设定为0.5)
hd->h_scale = 1.0;(如果缩小一半,就设定为0.5)
static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
hwc_display_contents_1_t **display_contents) {
update_hdmi_output_format(ctx, connector, i, hd);
update_display_bestmode(hd, i, connector);
DrmMode mode = connector->best_mode();
connector->set_current_mode(mode);
hd->rel_xres = mode.h_display();
hd->rel_yres = mode.v_display();
hd->v_total = mode.v_total();
//hd->w_scale = (float)mode.h_display() / hd->framebuffer_width;
//hd->h_scale = (float)mode.v_display() / hd->framebuffer_height;
hd->w_scale = 1.0;
hd->h_scale = 1.0;
int fbSize = hd->framebuffer_width * hd->framebuffer_height;
//get plane size for display
std::vector<PlaneGroup *>& plane_groups = ctx->drm.GetPlaneGroups();
hd->iPlaneSize = 0;
hd->is_interlaced = (mode.interlaced()>0) ? true:false;
for (std::vector<PlaneGroup *> ::const_iterator iter = plane_groups.begin();
iter != plane_groups.end(); ++iter)
}
1.2 SurfaceFlinger::handleMessageInvalidate() 主要是更新layer 对象,等待vsync到来,调用
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doComposition();
postComposition(refreshStartTime);
将图像合成并显示。
bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL();
//对多个图层进行处理
return handlePageFlip();
}
bool SurfaceFlinger::handlePageFlip()
{
//对需要更新对象更新对应区域
const Region dirty(layer->latchBuffer(visibleRegions));
}
1.3 SF 收到vsync 信号调用void SurfaceFlinger::handleMessageRefresh() 函数。
void SurfaceFlinger::handleMessageRefresh() {
//遍历所有的图层,检测是否有图层发生变化,如果发生变化,SF最终还是会调用
//SurfaceFlinger::onMessageReceived()函数
preComposition();
//1.重建所有显示设备得图层,组成新的列表
//2.计算每个图层在设备上的可见区域
//3.计算设备需要更新的区域
rebuildLayerStacks();
//调用hardware\rockchip\hwcomposer\hwcomposer.cpp HWComposer对象中图层对象列表以及图层属性
//将每种HWComposer中的所有图层的类型都设置为HWC_FRAMEBUFFER
setUpHWComposer();
doDebugFlashRegions();
//合成所有图层,生成 OpenGL 纹理图像
//如果不支持HWC ,则用GPU 合成,eglSwapBuffers 来显示
doComposition();
//将图像传递给物理屏幕
postComposition(refreshStartTime);
}
1.3.1 SurfaceFlinger::rebuildLayerStacks() 函数根据旋转标志位,计算图层可见区域。
void SurfaceFlinger::rebuildLayerStacks() {
if (displayDevice->isDisplayOn()) {
SurfaceFlinger::computeVisibleRegions(layers,
displayDevice->getLayerStack(), dirtyRegion,
opaqueRegion);
}
void SurfaceFlinger::computeVisibleRegions(
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
// compute the opaque region
const int32_t layerOrientation = s.active.transform.getOrientation();
if (s.alpha == 1.0f && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
// the opaque region is the layer's footprint
opaqueRegion = visibleRegion;
}
}
1.3.2 SurfaceFlinger::doComposition() 函数 主要用来合成图层,使用hwc 以及不使用hwc 如何进行处理。最终都会循环调用layer 的draw() 进行绘制图形。
void SurfaceFlinger::doComposition() {
// repaint the framebuffer (if needed)
doDisplayComposition(hw, dirtyRegion);
}
void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
const Region& inDirtyRegion)
{
if (!doComposeSurfaces(hw, dirtyRegion)) return;
}
bool SurfaceFlinger::doComposeSurfaces(
const sp<const DisplayDevice>& displayDevice, const Region& dirty)
{
//调用opengl 生成纹理
layer->draw(displayDevice, clip);
}
二. SurfaceFlinger.cpp 中的函数最终都会调用Layer.cpp中的函数进行绘制图像。接下来分析Layer.cpp 中是如何对图像进行渲染的。
路径:frameworks\native\services\surfaceflinger\Layer.cpp
1.void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) 函数为0度 90度 180度 270度设置相应的纹理坐标,然后调用调用opengl 进行渲染。
void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
onDraw(hw, clip, false);
}
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
bool useIdentityTransform) const
{
//opengl 利用纹理坐标与顶点坐标得到layer 的显示内容以及区域
drawWithOpenGL(hw, clip, useIdentityTransform);
}
void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
const Region& /* clip */, bool useIdentityTransform) const {
computeGeometry(hw, mMesh, useIdentityTransform);
}
void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
bool useIdentityTransform) const
{
const Layer::State& s(getDrawingState());
#if RK_HW_ROTATION
Transform tr(hw->getTransform());
const Transform identity;
#else
const Transform tr(hw->getTransform());
#endif
const uint32_t hw_h = hw->getHeight();
Rect win(s.active.w, s.active.h);
D("mDrawingScreenshot : %d, useIdentityTransform : %d.", mDrawingScreenshot, useIdentityTransform);
#if RK_HW_ROTATION
if (mDrawingScreenshot) {
computeHWGeometry(tr, identity, hw);
}
#endif
if (!s.crop.isEmpty()) {
win.intersect(s.crop, &win);
}
// subtract the transparent region and snap to the bounds
win = reduce(win, s.activeTransparentRegion);
vec2 lt = vec2(win.left, win.top);
vec2 lb = vec2(win.left, win.bottom);
vec2 rb = vec2(win.right, win.bottom);
vec2 rt = vec2(win.right, win.top);
if (!useIdentityTransform) {
lt = s.active.transform.transform(lt);
lb = s.active.transform.transform(lb);
rb = s.active.transform.transform(rb);
rt = s.active.transform.transform(rt);
}
if (!s.finalCrop.isEmpty()) {
boundPoint(<, s.finalCrop);
boundPoint(&lb, s.finalCrop);
boundPoint(&rb, s.finalCrop);
boundPoint(&rt, s.finalCrop);
}
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
position[0] = tr.transform(lt);
position[1] = tr.transform(lb);
position[2] = tr.transform(rb);
position[3] = tr.transform(rt);
for (size_t i=0 ; i<4 ; i++) {
position[i].y = hw_h - position[i].y;
}
//position[2].y = 200;
}