static sunxi_disp_t *sunxi_disp_init(const char *device) { int tmp, version; struct fb_var_screeninfo fb_var; struct fb_fix_screeninfo fb_fix; sunxi_disp_t *ctx = (sunxi_disp_t*)calloc(1, sizeof(sunxi_disp_t)); if (!ctx) return NULL; /* use /dev/fb0 by default */ if (!device) device = "/dev/fb0"; if (!strcmp(device, "/dev/fb0")) ctx->fb_id = 0; else if (!strcmp(device, "/dev/fb1")) ctx->fb_id = 1; else goto error; ctx->fd_disp = open("/dev/disp", O_RDWR); /* maybe it's even not a sunxi hardware */ if (ctx->fd_disp < 0) goto error; /* version check */ tmp = SUNXI_DISP_VERSION; version = ioctl(ctx->fd_disp, DISP_CMD_VERSION, &tmp); if (version < 0) { close(ctx->fd_disp); goto error; } ctx->fd_fb = open(device, O_RDWR); if (ctx->fd_fb < 0) { close(ctx->fd_disp); goto error; } if (ioctl(ctx->fd_fb, FBIOGET_VSCREENINFO, &fb_var) < 0 || ioctl(ctx->fd_fb, FBIOGET_FSCREENINFO, &fb_fix) < 0) { close(ctx->fd_fb); close(ctx->fd_disp); goto error; } ctx->xres = fb_var.xres; ctx->yres = fb_var.yres; ctx->bits_per_pixel = fb_var.bits_per_pixel; ctx->framebuffer_paddr = fb_fix.smem_start; ctx->framebuffer_size = fb_fix.smem_len; ctx->framebuffer_height = ctx->framebuffer_size / (ctx->xres * ctx->bits_per_pixel / 8); ctx->gfx_layer_size = ctx->xres * ctx->yres * fb_var.bits_per_pixel / 8; if (ctx->framebuffer_size < ctx->gfx_layer_size) { close(ctx->fd_fb); close(ctx->fd_disp); goto error; } /* mmap framebuffer memory */ ctx->framebuffer_addr = (uint8_t *)mmap(0, ctx->framebuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->fd_fb, 0); if (ctx->framebuffer_addr == MAP_FAILED) { close(ctx->fd_fb); close(ctx->fd_disp); goto error; } /* Get the id of the screen layer */ if (ioctl(ctx->fd_fb, ctx->fb_id == 0 ? FBIOGET_LAYER_HDL_0 : FBIOGET_LAYER_HDL_1, &ctx->gfx_layer_id)) { close(ctx->fd_fb); close(ctx->fd_disp); goto error; } if (sunxi_layer_reserve(ctx) < 0) { close(ctx->fd_fb); close(ctx->fd_disp); goto error; } return ctx; error: if (ctx) free(ctx); return NULL; }
rpi_disp_t *rpi_disp_init(const char *device, void *xserver_fbmem) { rpi_disp_t *ctx = calloc(sizeof(rpi_disp_t), 1); struct fb_var_screeninfo fb_var; struct fb_fix_screeninfo fb_fix; int tmp, version; int gfx_layer_size; int ovl_layer_size; /* use /dev/fb0 by default */ if (!device) device = "/dev/fb0"; if (strcmp(device, "/dev/fb0") == 0) { ctx->fb_id = 0; } else if (strcmp(device, "/dev/fb1") == 0) { ctx->fb_id = 1; } else { free(ctx); return NULL; } /* store the already existing mapping done by xserver */ ctx->xserver_fbmem = xserver_fbmem; #if 0 ctx->fd_disp = open("/dev/disp", O_RDWR); /* maybe it's even not a sunxi hardware */ if (ctx->fd_disp < 0) { free(ctx); return NULL; } /* version check */ tmp = SUNXI_DISP_VERSION; version = ioctl(ctx->fd_disp, DISP_CMD_VERSION, &tmp); if (version < 0) { close(ctx->fd_disp); free(ctx); return NULL; } #endif ctx->fd_fb = open(device, O_RDWR); if (ctx->fd_fb < 0) { close(ctx->fd_disp); free(ctx); return NULL; } if (ioctl(ctx->fd_fb, FBIOGET_VSCREENINFO, &fb_var) < 0 || ioctl(ctx->fd_fb, FBIOGET_FSCREENINFO, &fb_fix) < 0) { close(ctx->fd_fb); close(ctx->fd_disp); free(ctx); return NULL; } ctx->xres = fb_var.xres; ctx->yres = fb_var.yres; ctx->bits_per_pixel = fb_var.bits_per_pixel; ctx->framebuffer_paddr = fb_fix.smem_start; ctx->framebuffer_size = fb_fix.smem_len; ctx->framebuffer_height = ctx->framebuffer_size / (ctx->xres * ctx->bits_per_pixel / 8); ctx->gfx_layer_size = ctx->xres * ctx->yres * fb_var.bits_per_pixel / 8; if (ctx->framebuffer_size < ctx->gfx_layer_size) { close(ctx->fd_fb); close(ctx->fd_disp); free(ctx); return NULL; } if (ctx->xserver_fbmem) { /* use already existing mapping */ ctx->framebuffer_addr = ctx->xserver_fbmem; } else { /* mmap framebuffer memory */ ctx->framebuffer_addr = (uint8_t *)mmap(0, ctx->framebuffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, ctx->fd_fb, 0); if (ctx->framebuffer_addr == MAP_FAILED) { close(ctx->fd_fb); close(ctx->fd_disp); free(ctx); return NULL; } } ctx->cursor_enabled = 0; ctx->cursor_x = -1; ctx->cursor_y = -1; #if 0 if (sunxi_layer_reserve(ctx) < 0) { close(ctx->fd_fb); close(ctx->fd_disp); free(ctx); return NULL; } ctx->fd_g2d = open("/dev/g2d", O_RDWR); #endif ctx->blt2d.self = ctx; ctx->blt2d.overlapped_blt = rpi_blt; ctx->blt2d.standard_blt = NULL; ctx->blt2d.fill = rpi_fill; return ctx; }