android双屏显示的一些修改与尝试

时间:2024-03-07 21:38:55
转载时请注明出处和作者
作者: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