精华内容
下载资源
问答
  • android双屏显示demo

    2015-11-24 09:52:54
    android双屏显示demo 基于HDML+LCD
  • Android 双屏显示分析

    2019-10-29 15:09:35
    双屏异显 系统提供了Presentation类,可以实现在两块屏幕上同时显示不同的内容;Presentation是一个特殊的dialog,它的目的是显示内容到第二屏幕。 image.png 基本原理 image.png 1 获得显示设备信息: ...

    双屏异显

    系统提供了Presentation类,可以实现在两块屏幕上同时显示不同的内容;Presentation是一个特殊的dialog,它的目的是显示内容到第二屏幕。

    image.png

    基本原理

    image.png

    1 获得显示设备信息:
    DisplayManagerService 启动后从SurfaceFlinger当中获取到系统默认的Display 与HDMI display的信息。

    2 应用程序端指定其应用ContextImpl的Display。

    3 应用程序获得Surface和配置Surface,这个surface对应于SurfaceFlinger中的Layer;

    WindowManagerService作为一个系统服务,主要管理系统中所有的应用的Window。在WMS中,每个Window都有一个对应的WindowState对象。

    3.1 addWindow,该函数在WindowManagerService当中,由WindowManagerImpl中的addView函数调用到,并且将Window所在的Display作为参数带到WMS当中。

    3.2在addWindow函数,WMS首先找到窗口所在的Display,创建WindowState,然后将窗口加到Display中的Windowlist当中。win.mToken.addWindow(win);

    3.3 WindowState,获取对应Display的layerstack将其放置在WindowStateAnimator当中,并且将值设置到SurfaceFlinger当中与之对应的Layer中,告知SurfaceFlinger自己所在Display。mSurfaceControl.setLayerStack(mLayerStack);

    4 绘制Surface
    SurfaceFlinger作为Android在native层比较重要的一个系统服务,主要作用是compose所有的layer,将其绘制输出到显示设备当中,也就是物理Display当中。
    SurfaceFlinger根据Layer当中的layerStack成员,获知需要将该Layer绘制到具体哪一个Display当中。

     

    image.png

    SurfaceFlinger需要利用HWC, Compose 属于每个Display的layer,并且将其输出到具体的DisplayDivice当中。

     

    image.png

    源码分析

    1 新设备加入流程

    DisplayManagerService

     

    image.png

    LocalDisplayAdapter

     

    image.png

    当驱动层发现设备加入时会发出事件,framework检测到这个事件会调用onHotplug;如果是connected,那么调用tryConnectDisplayLocked,创建LocalDisplayDevice并保存到mDevices,发送DISPLAY_DEVICE_ENVENT_CHANGED;

    image.png

    image.png

    最终会调用DisplayManagerService中的handleDisplayDeviceAddedLocked;

     

    image.png

     

    handleDisplayDeviceAddedLocked函数中添加逻辑设备;并且分配默认的displayId和Layerstack

    2 异显示流程

    2.1 在Presentation创建的时候关联一个目标设备,确定Presentation要显示在那个设备上。根据这个设备的信息来配置Presentation的context和resources信息,每一个display拥有自己的管理对象以及context对象,这样双屏的操作互相独立;对于上层而言,其即意味着一个屏幕。

     

    image.png

     

    2.2 调用show函数显示view;实际调用WindowManagerImpl的addview函数;

     

    image.png


    WindowManagerImpl的addview 函数创建ViewRootImp,并调用ViewRootImpl的setView函数;ViewRootImpl类中创建了WindowSession和IWindow对象负责和Windowmanagerservice之间跨进程通信;

    image.png

    ViewRootImpl setview函数,调用了requestLayout 和WindowSession addToDisplay;

    ViewRootImpl中requestLayout函数调用mWindowSession.relayout,最终调用WindowManagerservice 的relayoutWindow,这个函数会配置Display信息; WindowStateAnimator创建Surfacecontrol,通过SurfaceControl,设置Layerstack;

     

    image.png

    SurfaceControl 事务

    SurfaceControl开始事务,设置参数,结束事务

    image.png

    WindowManagerservice addWindow函数

    1 通过displayId 获取显示设备

    final DisplayContent displayContent = mRoot.getDisplayContentOrCreate(displayId);

    2 创建WindowState, WindowState函数中创建了WindowStateAnimator对象负责窗口的管理

    final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid,
    session.mCanAddInternalSystemWindow);

    SurfaceControl 调用本地层方法android_view_SurfaceControl 设置surfaceflinger

     

    image.png

     

    image.png

     

    SurfaceComposerClient对象负责和surfaceflinger通信;配置好参数,结束事务,跨进程调用surfaceflinger setTransactionState

     

    image.png

     

    image.png


    Surfaceflinger 对display设备和layer层操作,设置layerstack, layer和第二块屏绑定setDisplayStateLocked

    image.png

     

    image.png

    Surfaceflinger输出过程:

    1 handleTransaction handPageFlip用户进程更新Surface图像时会调用,来更新Layer对象

    handleTransaction函数的作用的就是处理系统在两次刷新期间的各种变化。

    包括:

    处理Layer的事务,检测是否需要更新;

    处理显示设备的变化:

    1.显示设备减少了,需要把显示设备对应的DisplayDevice移除

    2.显示设备发生了变化,例如用户设置了Surface、重新设置了layerStack、旋转了屏幕等,这就需要重新设置显示对象的属性

    3.显示设备增加了,创建新的DisplayDevice加入系统中。

    设置设置和显示设备关联在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack)的TransformHint(主要指设备的显示方向orientation)

    image.png

    处理Layer增加情况

    设置mDrawingState

    2 VSync信号定时的调用handleMessageRefresh进行屏幕数据的刷新,输出到屏幕;

    image.png

    preComposition函数,遍历所有的Layer对象,调用其onPreComposition函数来检测Layer层中的图像是否有变化。

    rebuildLayerStacks函数的作用是重建每个显示设备的可见layer对象列表。通过判断layerstack 和display设备的layerstack是否相同,来决定该layer是否在那个display设备显示;

     

    image.png

    setUpHWComposer函数的作用是更新HWComposer对象中图层对象列表以及图层属性。

    doComposition函数是合成所有层的图像

    postFramebuffer先判断系统是否支持composer,如果不支持,我们知道图像已经在doComposition函数时调用hw->swapBuffers输出了,就返回了。如果支持硬件composer,postFramebuffer函数将调用HWComposer的commit函数继续执行。



    作者:NiceDream
    链接:https://www.jianshu.com/p/c3349146b38d
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • 关于Android双屏显示

    千次阅读 2012-09-18 11:53:33
    双屏显示的一款产品的介绍: http://www.kyocera.com.cn/prdct/telecom/consumer/ksp8000/ksp8000.html SDK和开发文档: ...
    展开全文
  • android 双屏显示机制

    2015-08-13 09:47:00
    public class Presentation extendsDialog java.lang.Object ...android.app.Dialog ↳ android.app.Presentation Class Overview Base class for presentations. A pr...
    public class

    Presentation

    extends Dialog
    java.lang.Object
       ↳ android.app.Dialog
         ↳ android.app.Presentation

    Class Overview


    Base class for presentations.

    A presentation is a special kind of dialog whose purpose is to present content on a secondary display. A Presentation is associated with the target Display at creation time and configures its context and resource configuration according to the display's metrics.

    Notably, the Context of a presentation is different from the context of its containing Activity. It is important to inflate the layout of a presentation and load other resources using the presentation's own context to ensure that assets of the correct size and density for the target display are loaded.

    A presentation is automatically canceled (see cancel()) when the display to which it is attached is removed. An activity should take care of pausing and resuming whatever content is playing within the presentation whenever the activity itself is paused or resumed.

    Choosing a presentation display

    Before showing a Presentation it's important to choose the Display on which it will appear. Choosing a presentation display is sometimes difficult because there may be multiple displays attached. Rather than trying to guess which display is best, an application should let the system choose a suitable presentation display.

    There are two main ways to choose a Display.

    Using the media router to choose a presentation display

    The easiest way to choose a presentation display is to use the MediaRouter API. The media router service keeps track of which audio and video routes are available on the system. The media router sends notifications whenever routes are selected or unselected or when the preferred presentation display of a route changes. So an application can simply watch for these notifications and show or dismiss a presentation on the preferred presentation display automatically.

    The preferred presentation display is the display that the media router recommends that the application should use if it wants to show content on the secondary display. Sometimes there may not be a preferred presentation display in which case the application should show its content locally without using a presentation.

    Here's how to use the media router to create and show a presentation on the preferred presentation display using getPresentationDisplay().

     MediaRouter mediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute();
     if (route != null) {
         Display presentationDisplay = route.getPresentationDisplay();
         if (presentationDisplay != null) {
             Presentation presentation = new MyPresentation(context, presentationDisplay);
             presentation.show();
         }
     }

    The following sample code from ApiDemos demonstrates how to use the media router to automatically switch between showing content in the main activity and showing the content in a presentation when a presentation display is available.

    /**
     * <h3>Presentation Activity</h3>
     *
     * <p>
     * This demonstrates how to create an activity that shows some content
     * on a secondary display using a {@link Presentation}.
     * </p><p>
     * The activity uses the {@link MediaRouter} API to automatically detect when
     * a presentation display is available and to allow the user to control the
     * media routes using a menu item.  When a presentation display is available,
     * we stop showing content in the main activity and instead open up a
     * {@link Presentation} on the preferred presentation display.  When a presentation
     * display is removed, we revert to showing content in the main activity.
     * We also write information about displays and display-related events to
     * the Android log which you can read using <code>adb logcat</code>.
     * </p><p>
     * You can try this out using an HDMI or Wifi display or by using the
     * "Simulate secondary displays" feature in Development Settings to create a few
     * simulated secondary displays.  Each display will appear in the list along with a
     * checkbox to show a presentation on that display.
     * </p><p>
     * See also the {@link PresentationActivity} sample which
     * uses the low-level display manager to enumerate displays and to show multiple
     * simultaneous presentations on different displays.
     * </p>
     */
    public class PresentationWithMediaRouterActivity extends Activity {
        private final String TAG = "PresentationWithMediaRouterActivity";

        private MediaRouter mMediaRouter;
        private DemoPresentation mPresentation;
        private GLSurfaceView mSurfaceView;
        private TextView mInfoTextView;
        private boolean mPaused;

        /**
         * Initialization of the Activity after it is first created.  Must at least
         * call {@link android.app.Activity#setContentView setContentView()} to
         * describe what is to be displayed in the screen.
         */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // Be sure to call the super class.
            super.onCreate(savedInstanceState);

            // Get the media router service.
            mMediaRouter = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE);

            // See assets/res/any/layout/presentation_with_media_router_activity.xml for this
            // view layout definition, which is being set here as
            // the content of our screen.
            setContentView(R.layout.presentation_with_media_router_activity);

            // Set up the surface view for visual interest.
            mSurfaceView = (GLSurfaceView)findViewById(R.id.surface_view);
            mSurfaceView.setRenderer(new CubeRenderer(false));

            // Get a text view where we will show information about what's happening.
            mInfoTextView = (TextView)findViewById(R.id.info);
        }

        @Override
        protected void onResume() {
            // Be sure to call the super class.
            super.onResume();

            // Listen for changes to media routes.
            mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_VIDEO, mMediaRouterCallback);

            // Update the presentation based on the currently selected route.
            mPaused = false;
            updatePresentation();
        }

        @Override
        protected void onPause() {
            // Be sure to call the super class.
            super.onPause();

            // Stop listening for changes to media routes.
            mMediaRouter.removeCallback(mMediaRouterCallback);

            // Pause rendering.
            mPaused = true;
            updateContents();
        }

        @Override
        protected void onStop() {
            // Be sure to call the super class.
            super.onStop();

            // Dismiss the presentation when the activity is not visible.
            if

    转载于:https://www.cnblogs.com/bujiangjiu/p/4726280.html

    展开全文
  • android双屏显示的一些修改与尝试

    千次阅读 2015-07-13 23:16:30
    转载时请注明出处和作者 ... 作者:Xandy 用的是android2.3的代码 ...这些天来一直在看android display相关的代码和资料并作了一些尝试,现在将这些...经过阅读代码和查到的相关一些资料,对android双屏的支持总体思
    转载时请注明出处和作者
    作者:Xandy

    用的是android2.3的代码

    这些天来一直在看android display相关的代码和资料并作了一些尝试,现在将这些天来的工作记录如下,有错误的地方希望广大同行指正,谢谢!

    经过阅读代码和查到的相关一些资料,对android双屏的支持总体思路如下图所示:

    由于目前跟踪代码只跟到了surfaceflinger这一层,下面先从surfaceflinger说起:

    在frameworks\base\services\surfaceflinger\surfaceflinger.cpp这个文件中有如下代码片断:

    status_t SurfaceFlinger::readyToRun()
    {
        LOGI("SurfaceFlinger's main thread ready to run. Initializing graphics H/W...\n");
    
        // we only support one display currently
        int dpy = 0;
    
        {
            // initialize the main display
            GraphicPlane& plane(graphicPlane(dpy));
            DisplayHardware* const hw = new DisplayHardware(this, dpy);
            
            DisplayHardware* const hw1 = new DisplayHardware(this, 1); //这个是我加入测试HAL层用的,下面将介绍到
            
            plane.setDisplayHardware(hw);
        }
    
        // create the shared control-block
        mServerHeap = new MemoryHeapBase(4096,MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
        LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
        
        mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
        LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
        
        new(mServerCblk) surface_flinger_cblk_t;
    
        // initialize primary screen
        // (other display should be initialized in the same manner, but
        // asynchronously, as they could come and go. None of this is supported
        // yet).
        const GraphicPlane& plane(graphicPlane(dpy));
        const DisplayHardware& hw = plane.displayHardware();
        const uint32_t w = hw.getWidth();
        const uint32_t h = hw.getHeight();
        const uint32_t f = hw.getFormat();
        hw.makeCurrent();
    
        // initialize the shared control block
        mServerCblk->connected |= 1<<dpy;
        display_cblk_t* dcblk = mServerCblk->displays + dpy;
        memset(dcblk, 0, sizeof(display_cblk_t));
        dcblk->w            = plane.getWidth();
        dcblk->h            = plane.getHeight();
        dcblk->format       = f;
        dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
        dcblk->xdpi         = hw.getDpiX();
        dcblk->ydpi         = hw.getDpiY();
        dcblk->fps          = hw.getRefreshRate();
        dcblk->density      = hw.getDensity();
    
        // Initialize OpenGL|ES
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        glPixelStorei(GL_PACK_ALIGNMENT, 4); 
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnable(GL_SCISSOR_TEST);
        glShadeModel(GL_FLAT);
        glDisable(GL_DITHER);
        glDisable(GL_CULL_FACE);
    
        const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
        const uint16_t g1 = pack565(0x17,0x2f,0x17);
        const uint16_t textureData[4] = { g0, g1, g1, g0 };
        glGenTextures(1, &mWormholeTexName);
        glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);
    
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrthof(0, w, h, 0, 0, 1);
    
       LayerDim::initDimmer(this, w, h);
    
        mReadyToRunBarrier.open();
    
        /*
         *  We're now ready to accept clients...
         */
    
        // start boot animation
        property_set("ctl.start", "bootanim");
        
        return NO_ERROR;
    }

      重点看上面用黄色标出的那两行,其中DisplayHardware* const hw1 = new DisplayHardware(this, 1);是我加入用来测试HAL层的buffer分配用的,DisplayHardware这个是在frameworks\base\services\surfaceflinger\DisplayHardware\DisplayHardware.cpp这个文件中定义的,如以下代码片断:

    /*
     * Initialize the display to the specified values.
     *
     */
    DisplayHardware::DisplayHardware(const sp<SurfaceFlinger>& flinger,uint32_t dpy)
        : DisplayHardwareBase(flinger, dpy),mFlags(0)
    {
        init(dpy);
    }

      而在同文件中有如下代码片断:

    void DisplayHardware::init(uint32_t dpy)
    {
        mNativeWindow = new FramebufferNativeWindow(dpy);
        
        framebuffer_device_t const * fbDev = mNativeWindow->getDevice();
        mDpiX = mNativeWindow->xdpi;
        mDpiY = mNativeWindow->ydpi;
        mRefreshRate = fbDev->fps;
    
        mOverlayEngine = NULL;
        hw_module_t const* module;
        if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) 
        {
            overlay_control_open(module, &mOverlayEngine);
        }
    
        EGLint w, h, dummy;
        EGLint numConfigs=0;
        EGLSurface surface;
        EGLContext context;
    
        // initialize EGL
        EGLint attribs[] = 
        {
                EGL_SURFACE_TYPE,  
                EGL_WINDOW_BIT,
                EGL_NONE,        
                0,
                EGL_NONE
        };
    
        // debug: disable h/w rendering
        char property[PROPERTY_VALUE_MAX];
        if (property_get("debug.sf.hw", property, NULL) > 0) 
        {
            if (atoi(property) == 0) 
            {
                LOGW("H/W composition disabled");
                attribs[2] = EGL_CONFIG_CAVEAT;
                attribs[3] = EGL_SLOW_CONFIG;
            }
        }
    
        // TODO: all the extensions below should be queried through
        // eglGetProcAddress().
    
        // set to EGL wrapper to load SW OpenGLES only
         if (property_get("debug.sf.enable_hgl", property, "1") > 0)
         {
            if (atoi(property) == 0) 
            {
                eglSetImplementationAndroid(EGL_TRUE);
            }
        }
    
    /*下面这些都是和egl相关的,目前正在研究中,由于代码量太大,一起不好发上来,这里简单介绍一下,frameworks\base\opengl\libagl目录下是agl相关的一些代码,这些代码会生成libGLES_android.so 这个动态库,这点可以从此目录下的Android.mk文件里看出:
    
    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
    LOCAL_MODULE:= libGLES_android
    
        在frameworks\base\opengl\libs目录下是egl相关的一些代码,这些代码主要把agl这个库作了个封装,并向外提供相关接口*/
        EGLDisplay display = eglGetDisplay((NativeDisplayType)dpy);//(EGL_DEFAULT_DISPLAY);
        LOGI("******DisplayHardware.cpp display:%d******\n",(int)display);
        eglInitialize(display, NULL, NULL);
        eglGetConfigs(display, NULL, 0, &numConfigs);
    
        EGLConfig config;
        status_t err = EGLUtils::selectConfigForNativeWindow(display, attribs, mNativeWindow.get(), &config);
        LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
        
        EGLint r,g,b,a;
        eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
        eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
        eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
    
        if (mNativeWindow->isUpdateOnDemand()) 
            mFlags |= PARTIAL_UPDATES;
        
        if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) 
        {
            if (dummy == EGL_SLOW_CONFIG)
                mFlags |= SLOW_CONFIG;
        }
    
        /*
         * Create our main surface
         */
    
        surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
        eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
        eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
    
        if (mFlags & PARTIAL_UPDATES) 
        {
            // if we have partial updates, we definitely don't need to
            // preserve the backbuffer, which may be costly.
            eglSurfaceAttrib(display, surface,EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
        }
    
        if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) 
        {
            if (dummy == EGL_BUFFER_PRESERVED) 
            {
                mFlags |= BUFFER_PRESERVED;
            }
        }
        
        /* Read density from build-specific ro.sf.lcd_density property
         * except if it is overridden by qemu.sf.lcd_density.
         */
        if (property_get("qemu.sf.lcd_density", property, NULL) <= 0)
        {
            if (property_get("ro.sf.lcd_density", property, NULL) <= 0)
            {
                LOGW("ro.sf.lcd_density not defined, using 160 dpi by default.");
                strcpy(property, "160");
            }
        }
        else 
        {
            /* for the emulator case, reset the dpi values too */
            mDpiX = mDpiY = atoi(property);
        }
        mDensity = atoi(property) * (1.0f/160.0f);
    
    
        /*
         * Create our OpenGL ES context
         */
        
    
        EGLint contextAttributes[] = 
        {
    #ifdef EGL_IMG_context_priority
    #ifdef HAS_CONTEXT_PRIORITY
    #warning "using EGL_IMG_context_priority"
            EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
    #endif
    #endif
            EGL_NONE, EGL_NONE
        };
        context = eglCreateContext(display, config, NULL, contextAttributes);
    
        mDisplay = display;
        mConfig  = config;
        mSurface = surface;
        mContext = context;
        mFormat  = fbDev->format;
        mPageFlipCount = 0;
    
        /*
         * Gather OpenGL ES extensions
         */
    
        eglMakeCurrent(display, surface, surface, context);
    
        GLExtensions& extensions(GLExtensions::getInstance());
        extensions.initWithGLStrings(glGetString(GL_VENDOR),
                                                     glGetString(GL_RENDERER),
                                                     glGetString(GL_VERSION),
                                                     glGetString(GL_EXTENSIONS),
                                                     eglQueryString(display, EGL_VENDOR),
                                                     eglQueryString(display, EGL_VERSION),
                                                     eglQueryString(display, EGL_EXTENSIONS));
    
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
        glGetIntegerv(GL_MAX_VIEWPORT_DIMS, &mMaxViewportDims);
    
    
    #ifdef EGL_ANDROID_swap_rectangle
        if (extensions.hasExtension("EGL_ANDROID_swap_rectangle")) 
        {
            if (eglSetSwapRectangleANDROID(display, surface,0, 0, mWidth, mHeight) == EGL_TRUE) 
            {
                // This could fail if this extension is not supported by this
                // specific surface (of config)
                mFlags |= SWAP_RECTANGLE;
            }
        }
        // when we have the choice between PARTIAL_UPDATES and SWAP_RECTANGLE
        // choose PARTIAL_UPDATES, which should be more efficient
    #ifdef FSL_EPDC_FB
    #else
        if (mFlags & PARTIAL_UPDATES)
            mFlags &= ~SWAP_RECTANGLE;
    #endif
    #endif
    
        LOGI("EGL informations:");
        LOGI("# of configs : %d", numConfigs);
        LOGI("vendor    : %s", extensions.getEglVendor());
        LOGI("version   : %s", extensions.getEglVersion());
        LOGI("extensions: %s", extensions.getEglExtension());
        LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
        LOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
    
        LOGI("OpenGL informations:");
        LOGI("vendor    : %s", extensions.getVendor());
        LOGI("renderer  : %s", extensions.getRenderer());
        LOGI("version   : %s", extensions.getVersion());
        LOGI("extensions: %s", extensions.getExtension());
        LOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize);
        LOGI("GL_MAX_VIEWPORT_DIMS = %d", mMaxViewportDims);
        LOGI("flags = %08x", mFlags);
    
        // Unbind the context from this thread
        eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    }

      上面代码黄色标出的将会new一个framebufferNativeWindow,其实就是通过HAL层的Gralloc这个库映射到kernel层中的framebuffer

      在frameworks\base\libs\ui\FramebufferNativeWindow.cpp这个文件中有如下代码片断:

    FramebufferNativeWindow::FramebufferNativeWindow(uint32_t dpy)
        : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
    {
        hw_module_t const* module;
        char GRALLOC_MODE[10];
        char GRALLOC_FB[10];
        char GRALLOC_GPU[10];
    
        if(dpy == DISPLAY0)
        {
            strcpy(GRALLOC_MODE,GRALLOC_HARDWARE_MODULE_ID0);
            strcpy(GRALLOC_FB,GRALLOC_HARDWARE_FB0);
            strcpy(GRALLOC_GPU,GRALLOC_HARDWARE_GPU0);
        }
        else if(dpy == DISPLAY1)
        {
            strcpy(GRALLOC_MODE,GRALLOC_HARDWARE_MODULE_ID1);
            strcpy(GRALLOC_FB,GRALLOC_HARDWARE_FB1);
            strcpy(GRALLOC_GPU,GRALLOC_HARDWARE_GPU1);
        }
        else
        {
            strcpy(GRALLOC_MODE,GRALLOC_HARDWARE_MODULE_ID0);
            strcpy(GRALLOC_FB,GRALLOC_HARDWARE_FB0);
            strcpy(GRALLOC_GPU,GRALLOC_HARDWARE_GPU0);
        }
    
    /*这个函数的原型是没有传入参数的,为了增加对second display的支持自行加入的,上面这些代码也是后来加入的,为的是根据传入的dpy(display 0/1)打开相应的Gralloc和GPU的库文件*/
        
        if (hw_get_module(GRALLOC_MODE, &module) == 0) 
        {
            int stride;
            int err;
            int i;
            err = framebuffer_open(module,GRALLOC_FB, &fbDev);
            LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
            
            err = gralloc_open(module,GRALLOC_GPU, &grDev);
            LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
    
            // bail out if we can't initialize the modules
            if (!fbDev || !grDev)
                return;
            
            mUpdateOnDemand = (fbDev->setUpdateRect != 0);
            
            // initialize the buffer FIFO
            mNumBuffers = fbDev->reserved[0];
            if (mNumBuffers != 3 && mNumBuffers != 2) 
            {
                LOGE("The framebuffer number got from HAL is not supported(%d)", mNumBuffers);
                return;
            }
            mNumFreeBuffers = mNumBuffers;
    
            mBufferHead = mNumBuffers-1;
    
            for (i = 0; i < mNumBuffers; i++)
                buffers[i] = new NativeBuffer(fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
    
            for (i = 0; i < mNumBuffers; i++) 
            {
                err = grDev->alloc(grDev,fbDev->width, fbDev->height, fbDev->format,GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);
                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",i, fbDev->width, fbDev->height, strerror(-err));
            }
    
            const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 
            const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
            const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
            const_cast<int&>(ANativeWindow::minSwapInterval) = fbDev->minSwapInterval;
            const_cast<int&>(ANativeWindow::maxSwapInterval) = fbDev->maxSwapInterval;
        } 
        else 
        {
            LOGE("Couldn't get gralloc module");
        }
    
        ANativeWindow::setSwapInterval = setSwapInterval;
        ANativeWindow::dequeueBuffer = dequeueBuffer;
        ANativeWindow::lockBuffer = lockBuffer;
        ANativeWindow::queueBuffer = queueBuffer;
        ANativeWindow::query = query;
        ANativeWindow::perform = perform;
    }

      重点在上面用黄色标出的这几行代码,hw_get_module会根据传入的dpy选择打开gralloc0还是gralloc1,framebuffer_open会根据传入的dpy选择打开fb0还是fb1,gralloc_open会根据传入的dpy选择打开gpu0还是gpu1;接下来的几行代码都是和buffer相关,mNumBuffers在这里等于3,先new NativeBuffer得到相应的buffers[i](i=0/1/2),grDev->alloc将会为这些buffers分配内存。

      在hardware\libhardware\include\hardware\Gralloc.h文件中有如下定义,为了加入second display我这里作了一些修改

    /**
     * The id of this module
     */
    #define GRALLOC_HARDWARE_MODULE_ID0   "gralloc0"
    #define GRALLOC_HARDWARE_MODULE_ID1  "gralloc1"
    
    /**
     * Name of the graphics device to open
     */
    
    #define GRALLOC_HARDWARE_FB0 "fb0"
    #define GRALLOC_HARDWARE_FB1 "fb1"
    #define GRALLOC_HARDWARE_GPU0 "gpu0"
    #define GRALLOC_HARDWARE_GPU1 "gpu1"
    
    .
    .
    .
    .
    
    /** convenience API for opening and closing a supported device 下面这些封装都是在得到了module这个结构体之后得到相应的函数入口*/
    
    static inline int gralloc_open(const struct hw_module_t* module, const char * name,struct alloc_device_t** device) 
    {
        return module->methods->open(module, name, (struct hw_device_t**)device);
    }
    
    static inline int gralloc_close(struct alloc_device_t* device) 
    {
        return device->common.close(&device->common);
    }
    
    
    static inline int framebuffer_open(const struct hw_module_t* module,const char * name, struct framebuffer_device_t** device) 
    {
        return module->methods->open(module,name, (struct hw_device_t**)device);
    }
    
    static inline int framebuffer_close(struct framebuffer_device_t* device) 
    {
        return device->common.close(&device->common);
    }

      上面这些代码就是通过打开不同的gralloc模块,得到不同的函数入口地址,这里我对gralloc分别新建了两个,一个映射到fb0,一个映射到fb1,如下文件列表:


      

    其中libgralloc_sec_display是我后来加入的,先看libgralloc里面的内容:

    在gralloc.cpp这个文件里有如下代码片断:

    /*这里的open就是打开gralloc这个模块之后与在gralloc.h中module->methods->open相对应了*/
    static struct hw_module_methods_t gralloc_module_methods = 
    {
            open: gralloc_device_open
    };
    
    struct private_module_t HAL_MODULE_INFO_SYM = {
        base: 
        {
            common: 
            {
                tag: HARDWARE_MODULE_TAG,
                version_major: 1,
                version_minor: 0,
                id: GRALLOC_HARDWARE_MODULE_ID0,
                name: "Graphics Memory Allocator Module",
                author: "The Android Open Source Project",
                methods: &gralloc_module_methods
            },
            registerBuffer: gralloc_register_buffer,
            unregisterBuffer: gralloc_unregister_buffer,
            lock: gralloc_lock,
            unlock: gralloc_unlock,
        },
        framebuffer: 0,
        flags: 0,
        numBuffers: 0,
        bufferMask: 0,
        lock: PTHREAD_MUTEX_INITIALIZER,
        currentBuffer: 0,
        pmem_master: -1,
        pmem_master_base: 0,
        master_phys: 0
    };

      open的实现代码如下:

    int gralloc_device_open(const hw_module_t* module, const char* name,hw_device_t** device)
    {
        int status = -EINVAL;
    
        //name = GRALLOC_HARDWARE_FB0 or GRALLOC_HARDWARE_GPU0
        GRALLLOGI0("*********gralloc_devide_open : name = %s********\n",name);
        if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) 
        {
            gralloc_context_t *dev;
            dev = (gralloc_context_t*)malloc(sizeof(*dev));
    
            /* initialize our state here */
            memset(dev, 0, sizeof(*dev));
    
            /* initialize the procs */
            dev->device.common.tag = HARDWARE_DEVICE_TAG;
            dev->device.common.version = 0;
            dev->device.common.module = const_cast<hw_module_t*>(module);
            dev->device.common.close = gralloc_close;
    
            dev->device.alloc   = gralloc_alloc;
            dev->device.free    = gralloc_free;
    
            *device = &dev->device.common;
            status = 0;
        } 
        else 
        {
            status = fb_device_open(module, name, device);/* 这里是调用了同目录下framebuffer.cpp文件中的函数*/
        }
        return status;
    }

      同样在gralloc_sec_display这个里面也会有如上一样的内容,这里不再列出,其实以上说的这些都是在为framebuffer在内存中的分配作准备包括GPU在内存中的空间。

    在framebuffer.cpp文件中有如下代码片断:

    int fb_device_open(hw_module_t const* module, const char* name,hw_device_t** device)
    {
        int status = -EINVAL;
        char value[PROPERTY_VALUE_MAX];
    
        if (!strcmp(name, GRALLOC_HARDWARE_FB0)) 
        {
            alloc_device_t* gralloc_device;
            framebuffer_device_t *fbdev;
    
            nr_framebuffers = NUM_BUFFERS;
            property_get("ro.product.device", value, "");
            if (0 == strcmp(value, "imx50_rdp")) {
                nr_framebuffers = 2;
                no_ipu = 1;
            }
    
            status = gralloc_open(module,GRALLOC_HARDWARE_GPU0, &gralloc_device);
            if (status < 0)
                return status;
    
            /* initialize our state here */
            fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
            memset(dev, 0, sizeof(*dev));
    
            /* initialize the procs */
            dev->device.common.tag = HARDWARE_DEVICE_TAG;
            dev->device.common.version = 0;
            dev->device.common.module = const_cast<hw_module_t*>(module);
            dev->device.common.close = fb_close;
            dev->device.setSwapInterval = fb_setSwapInterval;
            dev->device.post            = fb_post;
            #ifndef FSL_EPDC_FB
            dev->device.setUpdateRect = 0;
            #else
            dev->device.setUpdateRect = fb_setUpdateRect;
            #endif
            dev->device.compositionComplete = fb_compositionComplete;
            #ifdef TVOUT_DISPLAY_SUPPORT
            dev->device.setSecRotation = fb_setSecRotation;
            #endif
    
            private_module_t* m = (private_module_t*)module;
            status = mapFrameBuffer(m);
            if (status >= 0) 
            {
                int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
                const_cast<uint32_t&>(dev->device.flags) = 0xfb0;
                const_cast<uint32_t&>(dev->device.width) = m->info.xres;
                const_cast<uint32_t&>(dev->device.height) = m->info.yres;
                const_cast<int&>(dev->device.stride) = stride;
                if(m->info.bits_per_pixel != 32) 
                {
                    const_cast<int&>(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565;
                }
                else
                {
                    const_cast<int&>(dev->device.format) = HAL_PIXEL_FORMAT_BGRA_8888;
                }
                const_cast<float&>(dev->device.xdpi) = m->xdpi;
                const_cast<float&>(dev->device.ydpi) = m->ydpi;
                const_cast<float&>(dev->device.fps) = m->fps;
                const_cast<int&>(dev->device.minSwapInterval) = 1;
                const_cast<int&>(dev->device.maxSwapInterval) = 1;
                *device = &dev->device.common;
                fbdev = (framebuffer_device_t*) *device;
                fbdev->reserved[0] = nr_framebuffers;
            }
    
        /* initialize the IPU lib IPC */
            if (!no_ipu)
                mxc_ipu_lib_ipc_init();
        }
        return status;
    }

      这里重点在上面黄色标出的两处,fb_post和刷屏相关,只要FB0里面的数据有变化,就会行动这里面的代码,mapFrameBuffer会把内核空间的fb0映射到用户空间,这样上层就能使用fb0了 。

      gralloc1与gralloc0的不同之处主要在于对fb的映射,gralloc0是把fb0映射到了用户空间并与LCD0绑定,而gralloc1则是把fb1映射到了用户空间并与LCD1绑定,在framebuffer_sec.cpp有如下代码片断:

    /********************************************************
    *name:mapTVFrameBufferLocked
    *param:module
    *author:Xandy
    *说明:此函数经过改装过,把fb1映射给了LCD1
    ********************************************************/
    
    int mapTVFrameBufferLocked(struct TV_fb_module_t* module)
    {
        // already initialized...
        if (module->TVframebuffer) 
        {
            return 0;
        }
    
        int TV_fd = -1;
        struct mxcfb_color_key key; 
    
        set_graphics_fb_mode(1, 1);
        TV_fd = open("/dev/graphics/fb1", O_RDWR, 0);
    
        if (TV_fd < 0)
            return -errno;
    
        struct fb_fix_screeninfo finfo;
        if (ioctl(TV_fd, FBIOGET_FSCREENINFO, &finfo) == -1)
            return -errno;
    
        struct fb_var_screeninfo info;
        if (ioctl(TV_fd, FBIOGET_VSCREENINFO, &info) == -1)
            return -errno;
    
        info.reserved[0] = 0;
        info.reserved[1] = 0;
        info.reserved[2] = 0;
        info.xoffset = 0;
        info.yoffset = 0;
        info.activate = FB_ACTIVATE_NOW;
                    

      而framebuffer.cpp相同的地方则如下:

    int mapFrameBufferLocked(struct private_module_t* module)
    {
        // already initialized...
        if (module->framebuffer) 
        {
            return 0;
        }
            
        char const * const device_template[] = {
                "/dev/graphics/fb%u",
                "/dev/fb%u",
                0 };
    
        int fd = -1;
        int i=0;
        char name[64];
    
        char value[PROPERTY_VALUE_MAX];
        property_get("ro.UI_TVOUT_DISPLAY", value, "");
        if (strcmp(value, "1") != 0) 
        {
            set_graphics_fb_mode(0, 0);
            while ((fd==-1) && device_template[i]) {
                snprintf(name, 64, device_template[i], 0);
                fd = open(name, O_RDWR, 0);
                i++;
            }
        }
        else
        {
            set_graphics_fb_mode(1, 0);
            while ((fd==-1) && device_template[i]) 
            {
                snprintf(name, 64, device_template[i], 1);
                fd = open(name, O_RDWR, 0);
                i++;
            }
        }
    
        if (fd < 0)
            return -errno;
    
        struct fb_fix_screeninfo finfo;
        if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
            return -errno;
    
        struct fb_var_screeninfo info;
        if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
            return -errno;

      下面看看串口打印出来的信息:

    /*系统起来后,开启ServiceManager,这是因为SurfaceFlinger是一个service*/
    I/sysproc ( 2098): Entered system_init()
    I/sysproc ( 2098): ServiceManager: 0x11d9f8
    I/SurfaceFlinger( 2098): SurfaceFlinger is starting  /*SurfaceFlinger启动,这个service将会一直运行*/
    I/SurfaceFlinger( 2098): SurfaceFlinger's main thread ready to run. Initializing graphics H/W...
    I/imx5x.gralloc0( 2098): *********gralloc_devide_open : name = fb0********  /*打开gralloc0之后,得到得到相应的函数入口并为fb0与gpu0分配内存*/
    I/imx5x.gralloc0( 2098): *********gralloc_devide_open : name = gpu0********
    /*fb0初始化之后的一些信息*/
    I/imx5x.gralloc0( 2098): 16bpp setting of Framebuffer catched!
    I/imx5x.gralloc0( 2098): using (fd=24)
    I/imx5x.gralloc0( 2098): id           = DISP3 BG
    I/imx5x.gralloc0( 2098): xres         = 800 px
    I/imx5x.gralloc0( 2098): yres         = 480 px
    I/imx5x.gralloc0( 2098): xres_virtual = 800 px
    I/imx5x.gralloc0( 2098): yres_virtual = 1536 px
    I/imx5x.gralloc0( 2098): bpp          = 16
    I/imx5x.gralloc0( 2098): r            = 11:5
    I/imx5x.gralloc0( 2098): g            =  5:6
    I/imx5x.gralloc0( 2098): b            =  0:5
    I/imx5x.gralloc0( 2098): width        = 127 mm (160.000000 dpi)
    I/imx5x.gralloc0( 2098): height       = 76 mm (160.421051 dpi)
    I/imx5x.gralloc0( 2098): refresh rate = 62.02 Hz
    I/imx5x.gralloc0( 2098): *********gralloc_devide_open : name = gpu0********
    I/imx5x.gralloc0( 2098): ******Gralloc.cpp numBuffers:3******
    I/imx5x.gralloc0( 2098): ******Gralloc.cpp numBuffers:3******
    I/imx5x.gralloc0( 2098): ******Gralloc.cpp numBuffers:3******
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay.cpp: overlay_device_open
    I/FslOverlay( 2098): overlay_device_open control pid 2098,tid 2106
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay.cpp: overlay_init_fbdev
    I/FslOverlay( 2098): /dev/graphics/fb0 fb_var: bits_per_pixel 16,xres 800,yres 480,xres_virtual 800,yres_virtual 1536
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay.cpp: create_control_shared_data
    I/FslOverlay( 2098): ***************create_control_shared_data mmap in*********************
    I/FslOverlay( 2098): ***************create_control_shared_data mmap out:0x2ea3e000****************
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay_thread.h: onFirstRef
    I/FslOverlay( 2098): Overlay HAL control device Created successfully
    /*load egl库*/
    I/libEGL  ( 2098): ******eglGetDisplay in egl : 0******
    I/FslOverlay( 2098): Overlay thread running pid 2098 tid 2108
    D/libEGL  ( 2098): loaded /system/lib/egl/libGLES_android.so
    I/libagl  ( 2098): ******eglGetDisplay in libagl : 0******
    I/libEGL  ( 2098): ******Egl.cpp IMPL_SOFTWARE dpy=1
    D/libEGL  ( 2098): loaded /system/lib/egl/libEGL_imx51.so
    D/libEGL  ( 2098): loaded /system/lib/egl/libGLESv1_CM_imx51.so
    D/libEGL  ( 2098): loaded /system/lib/egl/libGLESv2_imx51.so
    I/libEGL  ( 2098): ******Egl.cpp IMPL_HARDWARE dpy=1
    I/SurfaceFlinger( 2098): ******DisplayHardware.cpp display:1******
    I/libEGL  ( 2098): ******egl.cpp eglInitialize******
    I/libEGL  ( 2098): ******egl.cpp IMX5X,dp->disp[0].dpy=0x2******
    I/libEGL  ( 2098): initialized 0 dpy=0x2, ver=1.4, cnx=0x6be08b54
    I/libEGL  ( 2098): ******egl.cpp IMX5X,dp->disp[1].dpy=0x1******
    I/libagl  ( 2098): ******libagl.cpp eglInitialize******
    I/libEGL  ( 2098): initialized 1 dpy=0x1, ver=1.2, cnx=0x6be08c0c
    I/libEGL  ( 2098): ******egl egl.cpp eglCreateWindowSurface******
    W/SurfaceFlinger( 2098): ro.sf.lcd_de*****************mxcfb_set_par*****************
    
    
    /*ipu相关,这些都是在kernel和HAL进行的*/
    mxc_ipu mxc_ipu: Channel already disabled 7
    
    mxc_ipu mxc_ipu: Channel already uninitialized 7
    
    TVE: fb mode change event: xres=1280, yres=1024
    
    nsity not defined, using 160 dpi**********************fb mmap in:0x2f8c1000*******************
    
     by default.
    I/SurfaceFlinger( *****************************ipuv3 fb mmap in 0x2f8c1000*************************
    
    2098): EGL informations:
    I/SurfaceFlinger( 2098): # of configs : 35
    I/SurfaceFlinger( 2098): vendor    : Advanced Micro Devices, Inc
    I/SurfaceFlinger( 2098): version   : 1.4 Internal version 1.4.1
    I/SurfaceFlinger( 2098): extensions: eglCreatePbufferFromClientBuffer EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_ANDROID_image_native_buffer EGL_AMD_create_image
    I/SurfaceFlinger( 2098): Client API: NULL
    I/SurfaceFlinger( 2098): EGLSurface: 5-6-5-0, config=0x6
    I/SurfaceFlinger( 2098): OpenGL informations:
    I/SurfaceFlinger( 2098): vendor    : Advanced Micro Devices, Inc.
    I/SurfaceFlinger( 2098): renderer  : AMD Z430
    I/SurfaceFlinger( 2098): version   : OpenGL ES-CM 1.1
    I/SurfaceFlinger( 2098): extensions: GL_AMD_compressed_3DC_texture GL_AMD_compressed_ATC_texture GL_AMD_performance_monitor GL_ATI_compressed_texture_atitc GL_ATI_texture_compression_atitc GL_OES_blend_equation_separate GL_OES_blend_func_separate GL_OES_blend_subtract GL_OES_compressed_ETC1_RGB8_texture GL_OES_compressed_paletted_texture GL_OES_draw_texture GL_OES_extended_matrix_palette GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_framebuffer_object GL_OES_matrix_palette GL_OES_point_size_array GL_OES_point_sprite GL_OES_read_format GL_OES_stencil_wrap GL_OES_texture_cube_map GL_OES_texture_env_crossbar GL_OES_texture_mirrored_repeat 
    I/SurfaceFlinger( 2098): GL_MAX_TEXTURE_SIZE = 2048
    I/SurfaceFlinger( 2098): GL_MAX_VIEWPORT_DIMS = 2048
    I/SurfaceFlinger( 2098): flags = 00000000
    /*上面是在surfaceflinger.cpp上DisplayHardware* const hw = new DisplayHardware(this, dpy);这个所创建的,下面的则是我自己加入的DisplayHardware* const hw1 = new DisplayHardware(this, 1);这句所创建的,由于目前做的是车载双屏系统,后台一个电视,这里把xres与yres设置成了1280x1024px*/
    I/imx5x.gralloc1( 2098): *********gralloc_devide_open : name = fb1********
    I/imx5x.gralloc1( 2098): *********gralloc_devide_open : name = gpu1********
    I/imx5x.gralloc1( 2098): using (TV_fd=34)
    I/imx5x.gralloc1( 2098): id           = DISP3 BG - DI1
    I/imx5x.gralloc1( 2098): xres         = 1280 px
    I/imx5x.gralloc1( 2098): yres         = 1024 px
    I/imx5x.gralloc1( 2098): xres_virtual = 1280 px
    I/imx5x.gralloc1( 2098): yres_virtual = 3072 px
    I/imx5x.gralloc1( 2098): bpp          = 16
    I/imx5x.gralloc1( 2098): r            = 11:5
    I/imx5x.gralloc1( 2098): g            =  5:6
    I/imx5x.gralloc1( 2098): b            =  0:5
    I/imx5x.gralloc1( 2098): width        = 203 mm (160.157639 dpi)
    I/imx5x.gralloc1( 2098): height       = 163 mm (159.568100 dpi)
    I/imx5x.gralloc1( 2098): refresh rate = 60.56 Hz
    I/imx5x.gralloc1( 2098): *********gralloc_devide_open : name = gpu1********
    I/imx5x.gralloc1( 2098): ******Gralloc.cpp numBuffers:3******
    I/imx5x.gralloc1( 2098): ******Gralloc.cpp numBuffers:3******
    I/imx5x.gralloc1( 2098): ******Gralloc.cpp numBuffers:3******
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay.cpp: overlay_device_open
    I/FslOverlay( 2098): overlay_device_open control pid 2098,tid 2106
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay.cpp: overlay_init_fbdev
    I/FslOverlay( 209pmem: request for physical address of pmem region from process 2104.
    
    8): /dev/graphics/fb0 fb_var: bits_per_pixel 16,xres 800,yres 480,xres_virtual 800,yres_virtual 1536
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay.cpp: create_control_shared_data
    I/FslOverlay( 2098): ***************create_control_shared_data mmap in*********************
    I/FslOverlay( 2098): ***************create_control_shared_data mmap out:0x2ea48000****************
    I/FslOverlay( 2098): hardware/mx5x/liboverlay/overlay_thread.h: onFirstRef
    I/FslOverlay( 2098): Overlay HAL control device Created successfully
    I/libEGL  ( 2098): ******eglGetDisplay in egl : 1******
    I/SurfaceFlinger( 2098): ******DisplayHardware.cpp display:2******
    I/libEGL  ( 2098): ******egl.cpp eglInitialize******
    I/libEGL  ( 2098): ******egl.cpp IMX5X,dp->disp[0].dpy=0x3******
    I/libEGL  ( 2098): initialized 0 dpy=0x3, ver=1.4, cnx=0x6be08b54
    I/libEGL  ( 2098): ******egl.cpp IMX5X,dp->disp[1].dpy=0x0******
    /*这里还有一些问题需要解决,主要是egl相关的一些东西,目前正在研究中!*/
    I/libagl  ( 2098): libagl egl.cpp:display is valid!!******
    W/libEGL  ( 2098): 1: eglInitialize(0x0) failed (EGL_BAD_DISPLAY)
    I/libEGL  ( 2098): ******egl egl.cpp eglCreateWindowSurface******
    E/imx5x.gralloc1( 2098): FBIOPAN_DISPLAY failed
    W/SurfaceFlinger( 2098): ro.sf.lcd_density not defined, using 160 dpi by default.
    E/imx5x.gralloc1( 2098): FBIOPAN_DISPLAY failed
    I/FslOverlay( 2098): Overlay thread running pid 2098 tid 2111
    I/SurfaceFlinger( 2098): EGL informations:
    I/SurfaceFlinger( 2098): # of configs : 27
    I/SurfaceFlinger( 2098): vendor    : Advanced Micro Devices, Inc
    I/SurfaceFlinger( 2098): version   : 1.4 Internal version 1.4.1
    I/SurfaceFlinger( 2098): extensions: eglCreatePbufferFromClientBuffer EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_ANDROID_image_native_buffer EGL_AMD_create_image
    I/SurfaceFlinger( 2098): Client API: NULL
    I/SurfaceFlinger( 2098): EGLSurface: 5-6-5-0, config=0x6
    I/SurfaceFlinger( 2098): OpenGL informations:
    I/SurfaceFlinger( 2098): vendor    : Advanced Micro Devices, Inc.
    I/SurfaceFlinger( 2098): renderer  : AMD Z430
    I/SurfaceFlinger( 2098): version   : OpenGL ES-CM 1.1
    I/SurfaceFlinger( 2098): extensions: GL_AMD_compressed_3DC_texture GL_AMD_compressed_ATC_texture GL_AMD_performance_monitor GL_ATI_compressed_texture_atitc GL_ATI_texture_compression_atitc GL_OES_blend_equation_separate GL_OES_blend_func_separate GL_OES_blend_subtract GL_OES_compressed_ETC1_RGB8_texture GL_OES_compressed_paletted_texture GL_OES_draw_texture GL_OES_extended_matrix_palette GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_framebuffer_object GL_OES_matrix_palette GL_OES_point_size_array GL_OES_point_sprite GL_OES_read_format GL_OES_stencil_wrap GL_OES_texture_cube_map GL_OES_texture_env_crossbar GL_OES_texture_mirrored_repeat 
    I/SurfaceFlinger( 2098): GL_MAX_TEXTURE_SIZE = 2048
    I/SurfaceFlinger( 2098): GL_MAX_VIEWPORT_DIMS = 2048
    I/SurfaceFlinger( 2098): flags = 00000000
    展开全文
  • 这些天来一直在看...经过阅读代码和查到的相关一些资料,对android双屏的支持总体思路如下图所示: 由于目前跟踪代码只跟到了surfaceflinger这一层,下面先从surfaceflinger说起: 在frameworks\base\servic
  • Android设备双屏显示

    2017-04-07 12:38:16
    最近公司要求在Android触摸设备上通过hdmi接口连接外置显示器,实现双屏异现功能,打开软件后外置显示器播放动画,触摸设备则可以进行其他的用户交互。捣鼓了好几天这东西,现在和大家分享一下 首先你的安卓设备...
  • rk3399 android7.1 双屏显示配置参考
  • Android异步双屏显示

    千次阅读 2012-04-24 10:48:30
    用的是android2.3的代码 ...经过阅读代码和查到的相关一些资料,对android双屏的支持总体思路如下图所示: 由于目前跟踪代码只跟到了surfaceflinger这一层,下面先从surfaceflinger说起: 在
  • android 双屏异显

    2017-11-24 17:30:44
    android 双屏异显 android 双屏异显android 双屏异显android 双屏异显
  • Android板实现双屏显示,DisplayManager和Display的使用,无须引入其他框架。只需调用原生谷歌类即可
  • Android双屏驱动Service架构实现

    千次阅读 2016-10-23 21:17:00
    Android双屏显示,可能会和别的双屏机制不同,大多数情况下是一个android系统,分主副屏而已。我司的硬件是两个android系统,两个屏幕,内部通过一根usb直连(这根usb连接线很稳定,代工厂和我们讲的,坑~)。双屏...
  • 最近在做一个Android双屏异显的项目,要实现一台Android设备通过HDMI连接两个显示器,然后在一个App中同时显示两个不同的画面。 标题实际上Android并不存在真正的像Windows一样的双屏异显,Android的双屏异显实际上...
  • android双屏异显

    2018-07-31 11:55:28
    Android Presentation 双屏异显,现在Android设备,一个主屏和一个辅助显示器,现在客户需求让在辅助显示器上显示独特的内容
  • 硕士毕业论文,Android平台下双屏切换显示的设计。
  • android双屏问题

    2021-01-12 17:57:32
    如图,在副屏上的输入框,却在主屏显示了,但是dialog是可以在副屏上显示的 双屏是两个activity,Presentation的方式也试过,Presentation的方式,弹窗也是在主屏上显示 <p><img alt="" height="645" src=...
  • android 双屏异显demo源码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,150
精华内容 460
关键字:

安卓双屏显示