android屏幕旋转显示流程,android屏幕旋转显示流程

PAD默认屏幕显示方向是竖着显示,改成默认横屏显示需要将屏幕的默认显示方向顺时针旋转90度.

android显示系统的核心是surfaceflinger,它为所有的应用程序提供显示服务,它能够将各种应用程序的2D,3D surface进行组合,合并最终得到的一个main surface数据送入framebuffer,显示的翻转和旋转也是由surfaceflinger完成的,我们大致分析下surfaceflinger的旋转流程:

1.surfaceflinger启动后首先进行初始化操作,设置surfaceflinger的相关属性并创建了DisplayDevice对象

void SurfaceFlinger::init() {

...

#ifdef MTK_AOSP_ENHANCEMENT

// make sure 3D init success

if (mEGLContext == EGL_NO_CONTEXT)

{

ALOGE("FATAL: couldn't create EGLContext");

delete mHwc;

eglTerminate(mEGLDisplay);

exit(0);

}

// init properties setting first

setMTKProperties(); //设置MTK相关属性

#else

LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,

"couldn't create EGLContext");

#endif

...

// initialize our non-virtual displays

for (size_t i=0 ; i<:num_builtin_display_types i>

DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);

// set-up the displays that are already connected

if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {

// All non-virtual displays are currently considered secure.

bool isSecure = true;

createBuiltinDisplayLocked(type);

wp token = mBuiltinDisplays[i];

sp producer;

sp consumer;

BufferQueue::createBufferQueue(&producer, &consumer,

new GraphicBufferAlloc());

sp fbs = new FramebufferSurface(*mHwc, i,

consumer);

int32_t hwcId = allocateHwcDisplayId(type);

sp hw = new DisplayDevice(this, //初始化各个DisplayDevice对象

type, hwcId, mHwc->getFormat(hwcId), isSecure, token,

fbs, producer,

mRenderEngine->getEGLConfig());

if (i > DisplayDevice::DISPLAY_PRIMARY) {

// FIXME: currently we don't get blank/unblank requests

// for displays other than the main display, so we always

// assume a connected display is unblanked.

ALOGD("marking display %zu as acquired/unblanked", i);

hw->setPowerMode(HWC_POWER_MODE_NORMAL);

}

mDisplays.add(token, hw);

}

}

}

setMTKProperties()中会设置surfaceflinger的相关属性:

void SurfaceFlinger::setMTKProperties(String8 &result) {

...

// get info for panel physical rotation

property_get("ro.sf.hwrotation", value, "0");

sPropertiesState.mHwRotation = atoi(value);

snprintf(buffer, sizeof(buffer), " ro.sf.hwrotation (mHwRotation): %d\n", sPropertiesState.mHwRotation);

result.append(buffer);

...

}此处会读取

ro.sf.hwrotation系统属性,这个系统属性决定了显示屏的初始旋转方向,并保存到全局变量sPropertiesState.mHwRotation中

2.DisplayDevice中会调用显示的旋转函数setProjection()

DisplayDevice::DisplayDevice(

const sp& flinger,

DisplayType type,

int32_t hwcId,

int format,

bool isSecure,

const wp& displayToken,

const sp& displaySurface,

const sp& producer,

EGLConfig config)(

...

#ifdef MTK_AOSP_ENHANCEMENT

mHwOrientation = DisplayState::eOrientationDefault; //读取默认的显示屏方向

// Name the display. The name will be replaced shortly if the display

// was created with createDisplay().

switch (mType) {

case DISPLAY_PRIMARY:

mDisplayName = "Built-in Screen";

#ifdef MTK_AOSP_ENHANCEMENT

switch (mFlinger->sPropertiesState.mHwRotation) { //读取显示屏初始旋转方向

case 90:

mHwOrientation = DisplayState::eOrientation90;

break;

case 180:

mHwOrientation = DisplayState::eOrientation180;

break;

case 270:

mHwOrientation = DisplayState::eOrientation270;

break;

}

#endif

break;

case DISPLAY_EXTERNAL:

mDisplayName = "HDMI Screen";

break;

default:

mDisplayName = "Virtual Screen"; // e.g. Overlay #n

break;

}

// initialize the display orientation transform.

setProjection(DisplayState::eOrientationDefault, mViewport, mFrame); //设置显示屏初始旋转方向

}

void DisplayDevice::setProjection(int orientation,

const Rect& newViewport, const Rect& newFrame) {

Rect viewport(newViewport);

Rect frame(newFrame);

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());

#ifdef MTK_AOSP_ENHANCEMENT

// for boot animation black screen issue

if ((false == mFlinger->getBootFinished()) && (DISPLAY_PRIMARY == mType)) {

ALOGI("[%s] clear DisplayDevice(type:%d) dirty region while booting",

__FUNCTION__, mType);

dirtyRegion.clear();

}

#endif

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);

#ifdef MTK_AOSP_ENHANCEMENT

// need to take care of HW rotation for mGlobalTransform

// for case if the panel is not installed align with device orientation

if (DisplayState::eOrientationDefault != mHwOrientation) {

DisplayDevice::orientationToTransfrom(

(orientation + mHwOrientation) % (DisplayState::eOrientation270 + 1),

w, h, &R);

}

#endif

// 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;

const uint8_t type = mGlobalTransform.getType();

mNeedsFiltering = (!mGlobalTransform.preserveRects() ||

(type >= Transform::SCALE));

mScissor = mGlobalTransform.transform(viewport);

if (mScissor.isEmpty()) {

mScissor = getBounds();

}

mOrientation = orientation;

mViewport = viewport;

mFrame = frame;

}

接着调用DisplayDevice类的orientationToTransfrom()方法构造成一个变换矩阵R,然后得到mGlobalTransform这个全局变换矩阵,最后通过mGlobalTransform.transform()这个方法进行显示的旋转

status_t DisplayDevice::orientationToTransfrom(

int orientation, int w, int h, Transform* tr)

{

uint32_t flags = 0;

switch (orientation) {

case DisplayState::eOrientationDefault:

flags = Transform::ROT_0;

break;

case DisplayState::eOrientation90:

flags = Transform::ROT_90;

break;

case DisplayState::eOrientation180:

flags = Transform::ROT_180;

break;

case DisplayState::eOrientation270:

flags = Transform::ROT_270;

break;

default:

return BAD_VALUE;

}

tr->set(flags, w, h);

return NO_ERROR;

}

这里调用Transform::set()方法设置矩阵,有兴趣可以深入分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值