|
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];
while ((fd==-1)
&& device_template[i])
{
snprintf(name, 64, device_template[i],
0);
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;
info.reserved[0]
= 0;
info.reserved[1]
= 0;
info.reserved[2]
= 0;
info.xoffset = 0;
info.yoffset = 0;
info.activate
= FB_ACTIVATE_NOW;
/*
* Explicitly request 5/6/5
*/
info.bits_per_pixel
= 16;
info.red.offset
= 11;
info.red.length
= 5;
info.green.offset
= 5;
info.green.length
= 6;
info.blue.offset
= 0;
info.blue.length
= 5;
info.transp.offset
= 0;
info.transp.length
= 0;
/*
* Request NUM_BUFFERS screens (at lest 2 for page flipping)
*/
info.yres_virtual
= info.yres
* NUM_BUFFERS;
uint32_t flags
= PAGE_FLIP;
if (ioctl(fd, FBIOPUT_VSCREENINFO,
&info)
==
-1) {
info.yres_virtual
= info.yres;
flags &=
~PAGE_FLIP;
LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
}
if (info.yres_virtual
< info.yres
* 2)
{
// we need at least 2 for page-flipping
info.yres_virtual
= info.yres;
flags &=
~PAGE_FLIP;
LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
info.yres_virtual, info.yres*2);
}
if (ioctl(fd, FBIOGET_VSCREENINFO,
&info)
==
-1)
return -errno;
int refreshRate
= 1000000000000000LLU /
(
uint64_t( info.upper_margin
+ info.lower_margin
+ info.yres
)
* ( info.left_margin
+ info.right_margin
+ info.xres
)
* info.pixclock
);
if (refreshRate
== 0)
{
// bleagh, bad info from the driver
refreshRate = 60*1000;
// 60 Hz
}
if (int(info.width)
<= 0
|| int(info.height)
<= 0)
{
// the driver doesn't return that information
// default to 160 dpi
info.width
= ((info.xres
* 25.4f)/160.0f
+ 0.5f);
info.height
= ((info.yres
* 25.4f)/160.0f
+ 0.5f);
}
float xdpi =
(info.xres
* 25.4f)
/ info.width;
float ydpi =
(info.yres
* 25.4f)
/ info.height;
float fps = refreshRate
/ 1000.0f;
LOGI( "using (fd=%d)/n"
"id = %s/n"
"xres = %d px/n"
"yres = %d px/n"
"xres_virtual = %d px/n"
"yres_virtual = %d px/n"
"bpp = %d/n"
"r = %2u:%u/n"
"g = %2u:%u/n"
"b = %2u:%u/n",
fd,
finfo.id,
info.xres,
info.yres,
info.xres_virtual,
info.yres_virtual,
info.bits_per_pixel,
info.red.offset, info.red.length,
info.green.offset, info.green.length,
info.blue.offset, info.blue.length
);
LOGI( "width = %d mm (%f dpi)/n"
"height = %d mm (%f dpi)/n"
"refresh rate = %.2f Hz/n",
info.width, xdpi,
info.height, ydpi,
fps
);
if (ioctl(fd, FBIOGET_FSCREENINFO,
&finfo)
==
-1)
return -errno;
if (finfo.smem_len
<= 0)
return -errno;
module->flags
= flags;
module->info
= info;
module->finfo
= finfo;
module->xdpi
= xdpi;
module->ydpi
= ydpi;
module->fps
= fps;
/*
* map the framebuffer
*/
int err;
size_t fbSize
= roundUpToPageSize(finfo.line_length
* info.yres_virtual);//对齐页
module->framebuffer
= new private_handle_t(dup(fd), fbSize,
0);
module->numBuffers
= info.yres_virtual
/ info.yres;
module->bufferMask
= 0;
void* vaddr
=
mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED,
fd, 0);
if (vaddr
== MAP_FAILED)
{
LOGE("Error mapping the framebuffer (%s)",
strerror(errno));
return -errno;
}
module->framebuffer->base
= intptr_t(vaddr);
memset(vaddr, 0, fbSize);
return 0;
}
|