You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

700 lines
22 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2018-2019. All rights reserved.
* Description: Gralloc
* Author: Hisilicon
* Created: 2019.11.07
*/
#include "gralloc_framebuffer.h"
#include <linux/fb.h>
#ifdef GRALLOC_NEED_SMMU_MAP
#include <linux/ion.h>
#endif
#include <cutils/properties.h>
#include <sys/ioctl.h>
#include <securec.h>
#include <GLES/gl.h>
#include "gfbg.h"
#include "gralloc_descriptor.h"
#include "gralloc_attribute.h"
#include "gralloc_format.h"
#include "mali_gralloc_formats.h"
#include "gralloc_debug.h"
#define GRALLOC_PROPERTY_FB_RESOLUTION "persist.vendor.display.resolution"
#define GRALLOC_PROPERTY_MASTER_DISPLAY "persist.vendor.display.master"
#define GRALLOC_PROPERTY_DISPLAY1_ATTACH_FB "persist.vendor.disp1.attach.fb"
#define GRALLOC_MAX_FB_RESOLUTION 8192
#define DEV_NAME_MAX_LEN 64
struct fb_dmabuf_export {
__u32 fd;
__u32 flags;
};
#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export)
static int gralloc_framebuffer_get_dmabuf(const private_module_t *m)
{
int ret = 0;
struct fb_dmabuf_export fb_dma_buf;
fb_dma_buf.fd = 0;
fb_dma_buf.flags = 0;
unsigned int id = ((hw_module_t *)m)->reserved[0];
if (id >= NUM_FB_DEVICES) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
ret = ioctl(m->framebuffer[id]->fd, FBIOGET_DMABUF, &fb_dma_buf);
if (ret != 0) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
return fb_dma_buf.fd;
}
static int gralloc_framebuffer_open_fb(unsigned int id)
{
int ret;
int device_fd;
char device_name[DEV_NAME_MAX_LEN];
if (id >= NUM_FB_DEVICES) {
GRALLOC_ERROR_INFO();
return -1;
}
/* open framebuffer device */
ret = snprintf_s(device_name, sizeof(device_name), sizeof(device_name) - 1, "/dev/graphics/fb%u", id);
if (ret < 0) {
GRALLOC_ERROR_INFO();
return -1;
}
device_fd = open(device_name, O_RDWR, 0);
if (device_fd < 0) {
GRALLOC_ERROR_INFO();
return -1;
}
ALOGI("gralloc open fb id:%d", id);
return device_fd;
}
static bool gralloc_get_fb_afbc_capability(const private_module_t *m, unsigned int id)
{
int ret = 0;
gfbg_capability_info fb_capability_info;
if (id >= NUM_FB_DEVICES) {
ALOGE("gralloc fb id is more than NUM_FB_DEVICES.");
return false;
}
ret = ioctl(m->framebuffer[id]->fd, GFBGIOGET_CAPABILITY, &fb_capability_info);
if (ret != 0) {
ALOGE("gralloc ioctl GFBGIOGET_CAPABILITY failed.");
return false;
}
return fb_capability_info.compression.is_support_afbc;
}
static int gralloc_framebuffer_get_fb_info(int device_fd, const struct fb_fix_screeninfo *fix_info,
const struct fb_var_screeninfo *var_info)
{
int ret;
if ((fix_info == nullptr) || (var_info == nullptr)) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
/* get framebuffer fix/vary info */
ret = ioctl(device_fd, FBIOGET_FSCREENINFO, fix_info);
if (ret < 0) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
ret = ioctl(device_fd, FBIOGET_VSCREENINFO, var_info);
if (ret < 0) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_set_fb_info(int device_fd, struct fb_var_screeninfo *var_info)
{
int ret;
unsigned int base = 10;
char custom_value[PROPERTY_VALUE_MAX] = {0};
char *str_save = nullptr;
if (var_info == nullptr) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
/* get fb resolution from the property. use default resolution from
FBIOGET_VSCREENINFO if the property is not set */
property_get(GRALLOC_PROPERTY_FB_RESOLUTION, custom_value, "");
if (strlen(custom_value) != 0) {
var_info->xres = (unsigned int)strtol(strtok_r(custom_value, "x", &str_save), nullptr, base);
var_info->yres = (unsigned int)strtol(strtok_r(nullptr, "x", &str_save), nullptr, base);
}
if ((var_info->xres > GRALLOC_MAX_FB_RESOLUTION) || (var_info->yres > GRALLOC_MAX_FB_RESOLUTION)) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
var_info->reserved[0] = 0;
var_info->reserved[1] = 0;
var_info->reserved[2] = 0; /* init reserved[2] is 0 */
var_info->xoffset = 0;
var_info->yoffset = 0;
var_info->activate = FB_ACTIVATE_NOW;
/* set framebuffer format */
var_info->bits_per_pixel = 32; /* 32bit */
var_info->transp.offset = 24; /* offset 24 of a channel */
var_info->transp.length = 8; /* 8 bit */
var_info->red.offset = 16; /* offset 16 of red channel */
var_info->red.length = 8; /* 8 bit */
var_info->green.offset = 8; /* offset 8 of green channel */
var_info->green.length = 8; /* 8 bits */
var_info->blue.offset = 0; /* offset 0 of blue channel */
var_info->blue.length = 8; /* 8 bits */
var_info->xres_virtual = var_info->xres;
var_info->yres_virtual = var_info->yres * NUM_FB_BUFFERS;
/* set framebuffer vary info */
ret = ioctl(device_fd, FBIOPUT_VSCREENINFO, var_info);
if (ret < 0) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_get_fb_dpi_and_fps(struct fb_var_screeninfo *var_info,
float *xdpi, float *ydpi, float *fps)
{
int refresh_rate;
if ((var_info == nullptr) || (xdpi == nullptr) || (ydpi == nullptr) || (fps == nullptr)) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
/* compute refresh rate */
if (static_cast<int>(var_info->pixclock) > 0) {
refresh_rate = static_cast<int>(1000000000000000LLU /
((var_info->upper_margin + var_info->lower_margin + var_info->yres + var_info->hsync_len) *
(var_info->left_margin + var_info->right_margin + var_info->xres + var_info->vsync_len) *
var_info->pixclock));
} else {
/* 60 Hz, fps = refresh_rate / 1000 , var_info.pixclock may be 0 when android run in Emulator */
refresh_rate = 60 * 1000;
}
if ((var_info->width == 0) || (var_info->height == 0)) {
var_info->width = ((var_info->xres * 25.4f) / 160.0f + 0.5f); /* (var_info.xres * 25.4f) / 160.0f + 0.5f) */
var_info->height = ((var_info->yres * 25.4f) / 160.0f + 0.5f); /* (var_info.yres * 25.4f) / 160.0f + 0.5f) */
}
*xdpi = (var_info->xres * 25.4f) / var_info->width; /* (var_info.xres * 25.4f) / 160.0f + 0.5f) */
*ydpi = (var_info->yres * 25.4f) / var_info->height; /* (var_info.yres * 25.4f) / 160.0f + 0.5f) */
*fps = refresh_rate / 1000.0f; /* 60 Hz, fps = refresh_rate / 1000.0f */
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_create_private_handle(unsigned int line_length, unsigned int yres_virtual,
int device_fd, struct private_handle_t **handle)
{
size_t framebuffer_size;
void *framebuffer_viraddr;
framebuffer_size = line_length * yres_virtual;
framebuffer_viraddr = mmap(nullptr, framebuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, 0);
if (framebuffer_viraddr == MAP_FAILED) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
*handle = new private_internal_handle_t(private_internal_handle_t::PRIV_FLAGS_FRAMEBUFFER,
framebuffer_size, framebuffer_viraddr,
GRALLOC_USAGE_HW_FB, GRALLOC_USAGE_HW_FB, dup(device_fd), 0);
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_init_locked(struct private_module_t *module)
{
int device_fd;
unsigned int id = ((hw_module_t *)module)->reserved[0];
struct fb_fix_screeninfo fix_info;
struct fb_var_screeninfo var_info;
float xdpi = 0.0f;
float ydpi = 0.0f;
float fps = 0.0f;
/* Nothing to do, already initialized */
if (module->framebuffer[id]) {
return GRALLOC_SUCCESS;
}
device_fd = gralloc_framebuffer_open_fb(id);
if (device_fd < 0) {
return GRALLOC_FAILURE;
}
/* get default fb info */
if (gralloc_framebuffer_get_fb_info(device_fd, &fix_info, &var_info) != GRALLOC_SUCCESS) {
close(device_fd);
return GRALLOC_FAILURE;
}
/* set fb info */
if (gralloc_framebuffer_set_fb_info(device_fd, &var_info) != GRALLOC_SUCCESS) {
close(device_fd);
return GRALLOC_FAILURE;
}
/* get set fb info */
if (gralloc_framebuffer_get_fb_info(device_fd, &fix_info, &var_info) != GRALLOC_SUCCESS) {
close(device_fd);
return GRALLOC_FAILURE;
}
/* get dpi and fps */
if (gralloc_framebuffer_get_fb_dpi_and_fps(&var_info, &xdpi, &ydpi, &fps) != GRALLOC_SUCCESS) {
close(device_fd);
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
module->xdpi[id] = xdpi;
module->ydpi[id] = ydpi;
module->fps[id] = fps;
module->vinfo[id] = var_info;
module->finfo[id] = fix_info;
module->swapInterval[id] = 0x1;
if (gralloc_framebuffer_create_private_handle(fix_info.line_length, var_info.yres_virtual,
device_fd, &(module->framebuffer[id])) != GRALLOC_SUCCESS) {
close(device_fd);
return GRALLOC_FAILURE;
}
module->numBuffers[id] = var_info.yres_virtual / var_info.yres;
module->bufferMask[id] = 0;
close(device_fd);
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_init(struct private_module_t *module)
{
int ret;
pthread_mutex_lock(&module->lock);
ret = gralloc_framebuffer_init_locked(module);
pthread_mutex_unlock(&module->lock);
return ret;
}
static int gralloc_framebuffer_swap_interval(struct framebuffer_device_t *dev, int interval)
{
private_module_t *m = nullptr;
unsigned int id;
if (dev == nullptr) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
m = reinterpret_cast<private_module_t *>(dev->common.module);
if (m == nullptr) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
id = ((hw_module_t *)m)->reserved[0];
if (interval < dev->minSwapInterval) {
interval = dev->minSwapInterval;
} else if (interval > dev->maxSwapInterval) {
interval = dev->maxSwapInterval;
}
m->swapInterval[id] = interval;
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_post(struct framebuffer_device_t *dev, buffer_handle_t buffer)
{
GRALLOC_IGNORE(dev);
GRALLOC_IGNORE(buffer);
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_composition_complete(struct framebuffer_device_t *dev)
{
GRALLOC_IGNORE(dev);
glFinish();
return GRALLOC_SUCCESS;
}
static int gralloc_framebuffer_device_close(struct hw_device_t *device)
{
framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t *>(device);
if (dev != nullptr) {
free(dev);
}
return GRALLOC_SUCCESS;
}
static unsigned int gralloc_framebuffer_get_id(unsigned long long usage)
{
unsigned int id;
char display1_fb_value[PROPERTY_VALUE_MAX] = {0};
unsigned int diaplay0_attach_fb_id;
unsigned int diaplay1_attach_fb_id;
char master_display[PROPERTY_VALUE_MAX] = {0};
unsigned int master_fb_id;
unsigned int external_fb_id;
diaplay0_attach_fb_id = 0; /* fb[0, 1, 2, 3], attach fb0 to display0 by default. */
property_get(GRALLOC_PROPERTY_DISPLAY1_ATTACH_FB, display1_fb_value, "3");
if (strncmp(display1_fb_value, "1", strlen("1")) == 0) {
diaplay1_attach_fb_id = 1; /* fb[0, 1, 2, 3], attach fb1 to display1 */
} else if (strncmp(display1_fb_value, "2", strlen("2")) == 0) {
diaplay1_attach_fb_id = 2; /* fb[0, 1, 2, 3], attach fb2 to display1 */
} else {
diaplay1_attach_fb_id = 3; /* fb[0, 1, 2, 3], attach fb3 to display1 by default */
}
/* bind master display to fb device */
property_get(GRALLOC_PROPERTY_MASTER_DISPLAY, master_display, "0");
if (strncmp(master_display, "1", strlen("1")) == 0) { /* use display1 as master display */
master_fb_id = diaplay1_attach_fb_id;
external_fb_id = diaplay0_attach_fb_id;
} else { /* use display0 as master display by default */
master_fb_id = diaplay0_attach_fb_id;
external_fb_id = diaplay1_attach_fb_id;
}
#ifdef GRALLOC_SUPPORT_MUTIPLE_DISPLAY
/* use external_fb_id if GRALLOC1_CONSUMER_USAGE_PRIVATE_19 is set, use master_fb_id by default */
id = ((usage & GRALLOC1_CONSUMER_USAGE_PRIVATE_19) != 0) ? external_fb_id : master_fb_id;
#else
GRALLOC_IGNORE(usage);
id = master_display_id;
#endif
return id;
}
static unsigned int gralloc_framebuffer_get_size(const private_module_t *m, unsigned int id, bool fb_support_afbc)
{
size_t framebuffer_size;
char afbc_property[PROPERTY_VALUE_MAX];
/* use AFBC as default format */
property_get(GRALLOC_PROPERTY_ENBALE_AFBC, afbc_property, "false");
if ((strcmp(afbc_property, "true") == 0) && fb_support_afbc) {
int w_align = GRALLOC_ALIGN(m->vinfo[id].xres, AFBC_ARGB_WIDEBLK_WIDTH_ALIGN);
int h_align = GRALLOC_ALIGN(m->vinfo[id].yres, AFBC_ARGB_WIDEBLK_HEIGHT_ALIGN);
int header_size = GRALLOC_ALIGN((w_align / AFBC_PIXELS_PER_BLOCK) *
(h_align / AFBC_PIXELS_PER_BLOCK) *
AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, 1024); /* 1024: 1k align */
/* 8: 8bit == 1byte */
int payload_size = w_align * h_align * (m->vinfo[id].bits_per_pixel / 8);
framebuffer_size = header_size + payload_size;
/* 4096: 4k align */
framebuffer_size = GRALLOC_ALIGN(framebuffer_size, 4096);
ALOGI("gralloc get afbc property true in gralloc_framebuffer_get_size");
} else {
framebuffer_size = m->finfo[id].line_length * m->vinfo[id].yres;
ALOGI("gralloc get afbc property false in gralloc_framebuffer_get_size");
}
return framebuffer_size;
}
static int gralloc_framebuffer_get_offset(private_module_t *m, unsigned int id, size_t framebuffer_size, off_t *offset)
{
uintptr_t framebuffer_viraddr;
unsigned int buffer_mask, buffer_nums;
buffer_mask = m->bufferMask[id];
buffer_nums = m->numBuffers[id];
if (buffer_nums > NUM_FB_BUFFERS) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
framebuffer_viraddr = (uintptr_t)m->framebuffer[id]->base;
if (buffer_mask >= ((1LU << buffer_nums) - 1)) {
buffer_mask = 0;
m->bufferMask[id] = 0;
}
/* find a free slot */
for (unsigned int i = 0; i < buffer_nums; i++) {
if (((buffer_mask & (unsigned int)(1LU << i)) == 0) &&
(id < NUM_FB_DEVICES)) {
m->bufferMask[id] |= (unsigned int)(1LU << i);
break;
}
framebuffer_viraddr += framebuffer_size;
}
*offset = framebuffer_viraddr - (uintptr_t)m->framebuffer[id]->base;
return GRALLOC_SUCCESS;
}
static unsigned long long gralloc_framebuffer_get_internal_format(unsigned long long format, bool fb_support_afbc)
{
unsigned long long internal_format;
char afbc_property[PROPERTY_VALUE_MAX];
/* use AFBC as default format */
property_get(GRALLOC_PROPERTY_ENBALE_AFBC, afbc_property, "false");
if ((strcmp(afbc_property, "true") == 0) && fb_support_afbc) {
internal_format = format |
(MALI_GRALLOC_INTFMT_AFBC_BASIC
| MALI_GRALLOC_INTFMT_AFBC_WIDEBLK
| MALI_GRALLOC_INTFMT_AFBC_SPLITBLK
| MALI_GRALLOC_INTFMT_AFBC_SPARSE
| MALI_GRALLOC_INTFMT_AFBC_YUV_TRANSFORM);
ALOGI("gralloc get afbc property true in gralloc_framebuffer_get_internal_format");
} else {
internal_format = format;
ALOGI("gralloc get afbc property false in gralloc_framebuffer_get_internal_format");
}
return internal_format;
}
static int gralloc_framebuffer_allocate_locked(private_module_t *m, buffer_descriptor_t *descriptors,
buffer_handle_t *out_buffers, const bool *shared_backend)
{
int ret;
size_t framebuffer_size;
unsigned int id;
off_t offset;
bool fb_support_afbc;
GRALLOC_IGNORE(shared_backend);
pthread_mutex_lock(&m->lock);
id = gralloc_framebuffer_get_id(descriptors->producer_usage | descriptors->consumer_usage);
if (id >= NUM_FB_DEVICES) {
pthread_mutex_unlock(&m->lock);
return GRALLOC_FAILURE;
}
/* (hw_module_t *)m)->reserved[0] will be covered by the last initialized fb id, so it
should be reinitialized when surfaceflinger allocates FrameBufferSurface again */
((hw_module_t *)m)->reserved[0] = id;
if (m->framebuffer[id] == nullptr) {
/* SurfaceFlinger process need init framebuffer by itself,
becasue framebuffer open is not in SF process */
ret = gralloc_framebuffer_init_locked(m);
if (ret != GRALLOC_SUCCESS) {
pthread_mutex_unlock(&m->lock);
return ret;
}
}
fb_support_afbc = gralloc_get_fb_afbc_capability(m, id);
ALOGI("gralloc id:%d, fb_support_afbc:%d", id, fb_support_afbc);
framebuffer_size = gralloc_framebuffer_get_size(m, id, fb_support_afbc);
gralloc_framebuffer_get_offset(m, id, framebuffer_size, &offset);
private_internal_handle_t *handle = new private_internal_handle_t(private_internal_handle_t::PRIV_FLAGS_FRAMEBUFFER,
framebuffer_size,
reinterpret_cast<void *>((uintptr_t)m->framebuffer[id]->base + offset),
descriptors->consumer_usage, descriptors->producer_usage, -1, offset);
handle->fd = gralloc_framebuffer_get_dmabuf(m);
handle->addr = (uintptr_t)m->finfo[id].smem_start + offset;
descriptors->format = HAL_PIXEL_FORMAT_BGRA_8888; /* fb use HAL_PIXEL_FORMAT_BGRA_8888 by default */
handle->format = descriptors->format;
handle->internal_format = gralloc_framebuffer_get_internal_format(descriptors->format, fb_support_afbc);
handle->width = descriptors->width;
handle->height = descriptors->height;
handle->internal_width = descriptors->width;
handle->internal_height = descriptors->height;
handle->pixel_stride = m->finfo[id].line_length / 4; /* ARGB pixel_stride is 4 * bytes_stride */
handle->bytes_stride = m->finfo[id].line_length;
handle->yuv_info = PRI_YUV_BT601_NARROW; /* use PRI_YUV_BT601_NARROW by default */
*out_buffers = handle;
pthread_mutex_unlock(&m->lock);
ALOGI("gralloc fb id:%d, usage:0x%llx, dma buf fd:%d, width:%d, height:%d, addr:0x%x",
id, descriptors->producer_usage | descriptors->consumer_usage,
handle->fd, handle->width, handle->height, handle->addr);
return GRALLOC_SUCCESS;
}
int gralloc_framebuffer_allocate(private_module_t *m, buffer_descriptor_t *descriptors,
buffer_handle_t *out_buffers, const bool *shared_backend)
{
int ret;
gralloc_debug_update_config();
if (out_buffers == nullptr) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
ret = gralloc_framebuffer_allocate_locked(m, descriptors, out_buffers, shared_backend);
if (ret < 0) {
GRALLOC_ERROR_INFO();
return GRALLOC_FAILURE;
}
private_internal_handle_t *handle = (private_internal_handle_t*)(*out_buffers);
gralloc_buffer_attr_allocate(m, handle);
if (gralloc_init_attribute_buffer(m, handle) != GRALLOC_SUCCESS) {
return GRALLOC_FAILURE;
}
if (gralloc_debug_dump_is_enabled()) {
gralloc_debug_dump_framebuffer(handle, m);
}
return GRALLOC_SUCCESS;
}
void gralloc_framebuffer_free(const private_module_t *m, buffer_handle_t buffer)
{
GRALLOC_IGNORE(m);
private_internal_handle_t *handle = (private_internal_handle_t*)buffer;
if (handle == nullptr) {
GRALLOC_ERROR_INFO();
return;
}
if (handle->fd > 0) {
close(handle->fd);
}
}
int gralloc_framebuffer_device_open(const hw_module_t *module, hw_device_t **device)
{
private_module_t *m = (private_module_t *)module;
gralloc1_device_t *gralloc_device = nullptr;
framebuffer_device_t *dev = nullptr;
unsigned int id;
if (device == nullptr || module == nullptr) {
return GRALLOC_FAILURE;
}
id = ((hw_module_t *)module)->reserved[0];
dev = reinterpret_cast<framebuffer_device_t *>(malloc(sizeof(framebuffer_device_t)));
if (dev == nullptr) {
return GRALLOC_FAILURE;
}
if (memset_s(dev, sizeof(*dev), 0, sizeof(*dev)) != EOK) {
free(dev);
return GRALLOC_FAILURE;
}
/* open gralloc device */
if (gralloc1_open(module, &gralloc_device) != GRALLOC_SUCCESS) {
GRALLOC_ERROR_INFO();
free(dev);
return GRALLOC_FAILURE;
}
/* init framebuffer */
if (gralloc_framebuffer_init(m) != GRALLOC_SUCCESS) {
GRALLOC_ERROR_INFO();
gralloc1_close(gralloc_device);
free(dev);
return GRALLOC_FAILURE;
}
/* configure parameters */
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = const_cast<hw_module_t *>(module);
dev->common.close = gralloc_framebuffer_device_close;
dev->setSwapInterval = gralloc_framebuffer_swap_interval;
dev->post = gralloc_framebuffer_post;
dev->setUpdateRect = nullptr;
dev->compositionComplete = &gralloc_framebuffer_composition_complete;
const_cast<unsigned int &>(dev->flags) = 0;
const_cast<unsigned int &>(dev->width) = m->vinfo[id].xres;
const_cast<unsigned int &>(dev->height) = m->vinfo[id].yres;
/* stride : pixel num of each line */
/* bits_per_pixel >> 3: bytes of per_pixel */
const_cast<int &>(dev->stride) = m->finfo[id].line_length / (m->vinfo[0].bits_per_pixel >> 3);
const_cast<int &>(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888;
const_cast<float &>(dev->xdpi) = m->xdpi[id];
const_cast<float &>(dev->ydpi) = m->ydpi[id];
const_cast<float &>(dev->fps) = m->fps[id];
const_cast<int &>(dev->minSwapInterval) = 0;
const_cast<int &>(dev->maxSwapInterval) = 1;
*device = &dev->common;
return GRALLOC_SUCCESS;
}