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<DisplayDevice::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<IBinder> token = mBuiltinDisplays[i];
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer,
- new GraphicBufferAlloc());
- sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
- consumer);
- int32_t hwcId = allocateHwcDisplayId(type);
- sp<DisplayDevice> 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);
- ...
- }
2.DisplayDevice中会调用显示的旋转函数setProjection()
- DisplayDevice::DisplayDevice(
- const sp<SurfaceFlinger>& flinger,
- DisplayType type,
- int32_t hwcId,
- int format,
- bool isSecure,
- const wp<IBinder>& displayToken,
- const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
- EGLConfig config)(
- <span style="font-family: Arial, Helvetica, sans-serif;">...
- </span><pre code_snippet_id="1939821" snippet_file_name="blog_20161020_4_9852155" name="code" class="cpp">#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()方法设置矩阵,有兴趣可以深入分析
转自:https://blog.csdn.net/zqh2007/article/details/52873903