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
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;
|
|
}
|