diff options
author | Roman Peresipkyn <r.peresipkyn@samsung.com> | 2016-02-04 18:55:46 +0200 |
---|---|---|
committer | SooChan Lim <sc1.lim@samsung.com> | 2016-03-07 19:53:33 +0900 |
commit | 9d63e9e66c928e54d9cdaf4879a33523a9389d0c (patch) | |
tree | d946f6bf3c4c50ff348bbedeb39516aced4e5f1f | |
parent | b90f16ed20d7178acd52be9b81709b15eddc3a2a (diff) | |
download | libtdm-fbdev-9d63e9e66c928e54d9cdaf4879a33523a9389d0c.tar.gz libtdm-fbdev-9d63e9e66c928e54d9cdaf4879a33523a9389d0c.tar.bz2 libtdm-fbdev-9d63e9e66c928e54d9cdaf4879a33523a9389d0c.zip |
add implementation of fbdev's output callbacks except vblank related ones
Change-Id: I86b79d3ab8e8d8082e16033f221ae18880a5d8e7
Signed-off-by: Roman Peresipkyn <r.peresipkyn@samsung.com>
-rw-r--r-- | src/tdm_fbdev.c | 87 | ||||
-rw-r--r-- | src/tdm_fbdev.h | 22 | ||||
-rw-r--r-- | src/tdm_fbdev_display.c | 212 |
3 files changed, 241 insertions, 80 deletions
diff --git a/src/tdm_fbdev.c b/src/tdm_fbdev.c index 4c030ef..db99e0e 100644 --- a/src/tdm_fbdev.c +++ b/src/tdm_fbdev.c @@ -72,37 +72,37 @@ close: static tdm_error _tdm_fbdev_init_internal(void) { - struct fb_fix_screeninfo finfo; - struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo *finfo = calloc(1, sizeof(struct fb_fix_screeninfo)); + struct fb_var_screeninfo *vinfo = calloc(1, sizeof(struct fb_var_screeninfo)); int ret = -1; - ret = ioctl(fbdev_data->fbdev_fd, FBIOGET_VSCREENINFO, &vinfo); + ret = ioctl(fbdev_data->fbdev_fd, FBIOGET_VSCREENINFO, vinfo); if (ret < 0) { TDM_ERR("FBIOGET_VSCREENINFO ioctl failed errno=%d", errno); goto close_1; } - vinfo.reserved[0] = 0; - vinfo.reserved[1] = 0; - vinfo.reserved[2] = 0; - vinfo.xoffset = 0; - vinfo.yoffset = 0; - vinfo.activate = FB_ACTIVATE_NOW; + vinfo->reserved[0] = 0; + vinfo->reserved[1] = 0; + vinfo->reserved[2] = 0; + vinfo->xoffset = 0; + vinfo->yoffset = 0; + vinfo->activate = FB_ACTIVATE_NOW; /* * Explicitly request 32 bits per pixel colors with corresponding * red, blue and green color offsets and length of colors */ - vinfo.bits_per_pixel = 32; - vinfo.red.offset = 16; - vinfo.red.length = 8; - vinfo.green.offset = 8; - vinfo.green.length = 8; - vinfo.blue.offset = 0; - vinfo.blue.length = 8; - vinfo.transp.offset = 0; - vinfo.transp.length = 0; + vinfo->bits_per_pixel = 32; + vinfo->red.offset = 16; + vinfo->red.length = 8; + vinfo->green.offset = 8; + vinfo->green.length = 8; + vinfo->blue.offset = 0; + vinfo->blue.length = 8; + vinfo->transp.offset = 0; + vinfo->transp.length = 0; /* * Almost all framebuffers support off screen rendering. @@ -131,13 +131,13 @@ _tdm_fbdev_init_internal(void) * +-------------+ | +-------------+ | +-------------+ * | | */ - vinfo.yres_virtual = vinfo.yres * MAX_BUF; + vinfo->yres_virtual = vinfo->yres * MAX_BUF; ret = ioctl(fbdev_data->fbdev_fd, FBIOPAN_DISPLAY, vinfo); if(ret < 0) { TDM_INFO("page flip not supported, errno=%d", errno); - vinfo.yres_virtual = vinfo.yres; + vinfo->yres_virtual = vinfo->yres; /* * TODO: Does FBIOPAN_DISPLAY ioctl must be invoked for the second time? @@ -157,12 +157,15 @@ _tdm_fbdev_init_internal(void) goto close_1; } - if (finfo.smem_len <= 0) + if (finfo->smem_len <= 0) { TDM_ERR("Length of frame buffer mem less then 0"); goto close_1; } + fbdev_data->vinfo = vinfo; + fbdev_data->finfo = finfo; + /* * Output framebuffer's related information */ @@ -182,27 +185,27 @@ _tdm_fbdev_init_internal(void) " width = %d mm \n" " height = %d mm \n", fbdev_data->fbdev_fd, - vinfo.xres, - vinfo.yres, - vinfo.xres_virtual, - vinfo.yres_virtual, - vinfo.bits_per_pixel, - vinfo.red.offset, vinfo.red.length, - vinfo.green.offset, vinfo.green.length, - vinfo.blue.offset, vinfo.blue.length, - vinfo.transp.offset, vinfo.transp.length, - vinfo.activate, - vinfo.width, - vinfo.height); + vinfo->xres, + vinfo->yres, + vinfo->xres_virtual, + vinfo->yres_virtual, + vinfo->bits_per_pixel, + vinfo->red.offset, vinfo->red.length, + vinfo->green.offset, vinfo->green.length, + vinfo->blue.offset, vinfo->blue.length, + vinfo->transp.offset, vinfo->transp.length, + vinfo->activate, + vinfo->width, + vinfo->height); TDM_INFO("\n" " FInfo\n" " id = %s\n" " smem_len = %d\n" " line_length = %d\n", - finfo.id, - finfo.smem_len, - finfo.line_length); + finfo->id, + finfo->smem_len, + finfo->line_length); return TDM_ERROR_NONE; close_1: @@ -220,6 +223,9 @@ tdm_fbdev_deinit(tdm_backend_data *bdata) close(fbdev_data->fbdev_fd); + tdm_fbdev_destroy_layer(fbdev_data); + tdm_fbdev_destroy_output(fbdev_data); + free(fbdev_data); fbdev_data = NULL; } @@ -285,6 +291,13 @@ tdm_fbdev_init(tdm_display *dpy, tdm_error *error) goto failed_2; } + ret = tdm_fbdev_creat_layer(fbdev_data); + if (ret != TDM_ERROR_NONE) + { + TDM_INFO("init of output failed"); + goto failed_3; + } + TDM_INFO("init success!"); @@ -293,6 +306,8 @@ tdm_fbdev_init(tdm_display *dpy, tdm_error *error) return (tdm_backend_data*)fbdev_data; +failed_3: + tdm_fbdev_destroy_layer(fbdev_data); failed_2: tdm_fbdev_destroy_output(fbdev_data); diff --git a/src/tdm_fbdev.h b/src/tdm_fbdev.h index 45de32f..6fd02b6 100644 --- a/src/tdm_fbdev.h +++ b/src/tdm_fbdev.h @@ -51,6 +51,8 @@ tdm_error fbdev_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); tdm_error fbdev_layer_unset_buffer(tdm_layer *layer); /* Framebuffer moudel's internal macros, functions, structures */ +#define NEVER_GET_HERE() TDM_ERR("** NEVER GET HERE **") + #define RETURN_VAL_IF_FAIL(cond, val) {\ if (!(cond)) {\ TDM_ERR("'%s' failed", #cond);\ @@ -70,8 +72,8 @@ typedef struct _tdm_fbdev_data tdm_display *dpy; - struct fb_fix_screeninfo finfo; - struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo *finfo; + struct fb_var_screeninfo *vinfo; struct list_head buffer_list; } tdm_fbdev_data; @@ -92,14 +94,28 @@ struct _tdm_fbdev_output_data /* * Poinetr to Framebuffers's mapped memory */ - void *vaddr; + void *mem; int count_modes; tdm_output_mode *output_modes; + int mode_changed; + + /* + * We currently support only one mode + */ + const tdm_output_mode *current_mode; tdm_output_type connector_type; tdm_output_conn_status status; unsigned int connector_type_id; + + tdm_output_dpms dpms_value; + + /* + * Event handlers + */ + tdm_output_vblank_handler vblank_func; + tdm_output_commit_handler commit_func; }; struct _tdm_fbdev_layer_data diff --git a/src/tdm_fbdev_display.c b/src/tdm_fbdev_display.c index 823dbeb..b2bd509 100644 --- a/src/tdm_fbdev_display.c +++ b/src/tdm_fbdev_display.c @@ -40,9 +40,9 @@ _tdm_fbdev_display_find_buffer(tdm_fbdev_data *fbdev_data, tbm_surface_h buffer) static void _tdm_fbdev_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data) { -tdm_fbdev_data *fbdev_data; -tdm_fbdev_display_buffer *display_buffer; -tbm_bo bo; + tdm_fbdev_data *fbdev_data; + tdm_fbdev_display_buffer *display_buffer; + tbm_bo bo; if (!user_data) { @@ -109,25 +109,29 @@ tdm_fbdev_creat_output(tdm_fbdev_data *fbdev_data) * TODO: Size of framebuffer must be aligned to system page size before * it is mapped */ - size = fbdev_data->vinfo.xres * fbdev_data->vinfo.yres * fbdev_data->vinfo.bits_per_pixel / 8 * MAX_BUF; + size = fbdev_data->vinfo->xres * fbdev_data->vinfo->yres * fbdev_data->vinfo->bits_per_pixel / 8 * MAX_BUF; - output->vaddr = mmap(0, size, PROT_READ|PROT_WRITE, + TDM_INFO("\n" + "MMaped size: %zu\n", + size); + + output->mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fbdev_data->fbdev_fd, 0); - if (output->vaddr == MAP_FAILED) + if (output->mem == MAP_FAILED) { TDM_ERR("MMap framebuffer failed, errno=%d", errno); return TDM_ERROR_OPERATION_FAILED; } - memset(output->vaddr, 0, size); + memset(output->mem, 0, size); - output->width = fbdev_data->vinfo.xres; - output->height = fbdev_data->vinfo.yres; - output->pitch = fbdev_data->vinfo.width; - output->bpp = fbdev_data->vinfo.bits_per_pixel; + output->width = fbdev_data->vinfo->xres; + output->height = fbdev_data->vinfo->yres; + output->pitch = fbdev_data->vinfo->width; + output->bpp = fbdev_data->vinfo->bits_per_pixel; output->size = size; - output->max_width = fbdev_data->vinfo.xres_virtual; - output->max_height = fbdev_data->vinfo.yres_virtual; + output->max_width = fbdev_data->vinfo->xres_virtual; + output->max_height = fbdev_data->vinfo->yres_virtual; output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED; output->connector_type = TDM_OUTPUT_TYPE_LVDS; @@ -153,17 +157,23 @@ tdm_fbdev_creat_output(tdm_fbdev_data *fbdev_data) for(i = 0; i < output->count_modes ; i++) { - output->output_modes[i].width = fbdev_data->vinfo.xres; - output->output_modes[i].height = fbdev_data->vinfo.yres; + output->output_modes[i].width = fbdev_data->vinfo->xres; + output->output_modes[i].height = fbdev_data->vinfo->yres; output->output_modes[i].refresh = 60; output->output_modes[i].flags = -1; output->output_modes[i].type = -1; sprintf(output->output_modes[i].name, "%dx%d", - fbdev_data->vinfo.width, - fbdev_data->vinfo.height); + fbdev_data->vinfo->width, + fbdev_data->vinfo->height); } + /* + * We currently support only one mode + */ + if (output->count_modes == 1) + output->current_mode = &output->output_modes[0]; + output->fbdev_data = fbdev_data; fbdev_data->fbdev_output = output; @@ -178,10 +188,13 @@ tdm_fbdev_destroy_output(tdm_fbdev_data *fbdev_data) if (fbdev_output == NULL) goto close; - if (fbdev_output->vaddr == NULL) + free(fbdev_data->vinfo); + free(fbdev_data->finfo); + + if (fbdev_output->mem == NULL) goto close_2; - munmap(fbdev_output->vaddr, fbdev_output->size); + munmap(fbdev_output->mem, fbdev_output->size); if (fbdev_output->output_modes == NULL) goto close_2; @@ -197,7 +210,8 @@ close: tdm_error tdm_fbdev_creat_layer(tdm_fbdev_data *fbdev_data) { - tdm_fbdev_layer_data *layer = NULL; + tdm_fbdev_layer_data *layer; + tdm_fbdev_output_data *fbdev_output = fbdev_data->fbdev_output; /* * Framebuffer does not support layer, therefore create only @@ -213,9 +227,8 @@ tdm_fbdev_creat_layer(tdm_fbdev_data *fbdev_data) layer->capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC; layer->fbdev_data = fbdev_data; - layer->fbdev_output = fbdev_data->fbdev_output; - - + layer->fbdev_output = fbdev_output; + fbdev_output->fbdev_layer = layer; return TDM_ERROR_NONE; } @@ -223,7 +236,11 @@ tdm_fbdev_creat_layer(tdm_fbdev_data *fbdev_data) void tdm_fbdev_destroy_layer(tdm_fbdev_data *fbdev_data) { + tdm_fbdev_output_data *fbdev_output = fbdev_data->fbdev_output; + tdm_fbdev_layer_data *layer = fbdev_output->fbdev_layer; + if(layer != NULL) + free(layer); } tdm_error @@ -288,15 +305,17 @@ failed_get: tdm_error fbdev_display_get_fd(tdm_backend_data *bdata, int *fd) { - RETURN_VAL_IF_FAIL(bdata, TDM_ERROR_INVALID_PARAMETER); + tdm_fbdev_data *fbdev_data = (tdm_fbdev_data *)bdata; + + RETURN_VAL_IF_FAIL(fbdev_data, TDM_ERROR_INVALID_PARAMETER); RETURN_VAL_IF_FAIL(fd, TDM_ERROR_INVALID_PARAMETER); /* - * TODO: Shloud we implement this call, because it is tricky place since we don't know how drm - * file descriptor is used by software above in drm backend; - * + * TODO: Shloud we implement this call, because it is tricky place + * since we don't know how drm file descriptor is used by software + * above us; */ - *fd = -1; + *fd = fbdev_data->fbdev_fd; return TDM_ERROR_NONE; } @@ -341,8 +360,8 @@ fbdev_output_get_capability(tdm_output *output, tdm_caps_output *caps) for (i = 0; i < caps->mode_count; i++) caps->modes[i] = fbdev_output->output_modes[i]; - caps->mmWidth = fbdev_data->vinfo.width;; - caps->mmHeight = fbdev_data->vinfo.height; + caps->mmWidth = fbdev_data->vinfo->width;; + caps->mmHeight = fbdev_data->vinfo->height; caps->subpixel = -1; caps->min_w = fbdev_output->width; @@ -368,7 +387,6 @@ tdm_layer** fbdev_output_get_layers(tdm_output *output, int *count, tdm_error *error) { tdm_fbdev_output_data *fbdev_output= (tdm_fbdev_output_data *)output; - tdm_fbdev_layer_data *fbdev_layer = NULL; tdm_layer **layers; tdm_error ret; @@ -390,9 +408,7 @@ fbdev_output_get_layers(tdm_output *output, int *count, tdm_error *error) goto failed_get; } - fbdev_layer = fbdev_output->fbdev_layer; - - layers[0] = fbdev_layer; + layers[0] = fbdev_output->fbdev_layer;; if (error) *error = TDM_ERROR_NONE; @@ -427,48 +443,165 @@ fbdev_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) tdm_error fbdev_output_wait_vblank(tdm_output *output, int interval, int sync, void *user_data) { + + return TDM_ERROR_NONE; } tdm_error fbdev_output_set_vblank_handler(tdm_output *output, tdm_output_vblank_handler func) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); + + fbdev_output->vblank_func = func; + return TDM_ERROR_NONE; } tdm_error fbdev_output_commit(tdm_output *output, int sync, void *user_data) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + tdm_fbdev_layer_data *fbdev_layer; + tdm_fbdev_display_buffer *display_buffer; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + + fbdev_layer = fbdev_output->fbdev_layer; + + if (!fbdev_layer->display_buffer_changed) + return TDM_ERROR_NONE; + + fbdev_output->mode_changed = 0; + fbdev_layer->display_buffer_changed = 0; + fbdev_layer->info_changed = 0; + + display_buffer = fbdev_layer->display_buffer; + + /* + * Display buffer's content to screen + */ + memcpy(fbdev_output->mem, display_buffer->mem, sizeof(display_buffer->size) ); + return TDM_ERROR_NONE; } tdm_error fbdev_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER); + + fbdev_output->commit_func = func; + return TDM_ERROR_NONE; } tdm_error fbdev_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + tdm_fbdev_data *fbdev_data; + int ret; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + + /* + * Bypass context switching overhead + */ + if (fbdev_output->dpms_value == dpms_value) + return TDM_ERROR_NONE; + + fbdev_data = fbdev_output->fbdev_data; + + switch (dpms_value) + { + case TDM_OUTPUT_DPMS_ON: + + ret = ioctl(fbdev_data->fbdev_fd, FBIOBLANK, FB_BLANK_UNBLANK); + if (ret < 0) + { + TDM_ERR("FBIOBLANK UNBLANK ioctl failed, errno=%d", errno); + return TDM_ERROR_OPERATION_FAILED; + } + + break; + + case TDM_OUTPUT_DPMS_OFF: + + ret = ioctl(fbdev_data->fbdev_fd, FBIOBLANK, FB_BLANK_POWERDOWN); + if (ret < 0) + { + TDM_ERR("FBIOBLANK POWERDOWN ioctl failed, errno=%d", errno); + return TDM_ERROR_OPERATION_FAILED; + } + + break; + + case TDM_OUTPUT_DPMS_STANDBY: + case TDM_OUTPUT_DPMS_SUSPEND: + break; + + default: + NEVER_GET_HERE(); + break; + } + + fbdev_output->dpms_value = dpms_value; + return TDM_ERROR_NONE; } tdm_error fbdev_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(dpms_value, TDM_ERROR_INVALID_PARAMETER); + + *dpms_value = fbdev_output->dpms_value; + return TDM_ERROR_NONE; } tdm_error fbdev_output_set_mode(tdm_output *output, const tdm_output_mode *mode) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER); + + /* + * We currently support only one mode + */ + if (fbdev_output->count_modes == 1) + return TDM_ERROR_NONE; + + /* + * TODO: Implement mode switching + */ + fbdev_output->mode_changed = 0; + return TDM_ERROR_NONE; } tdm_error fbdev_output_get_mode(tdm_output *output, const tdm_output_mode **mode) { + tdm_fbdev_output_data *fbdev_output = (tdm_fbdev_output_data *)output; + + RETURN_VAL_IF_FAIL(fbdev_output, TDM_ERROR_INVALID_PARAMETER); + RETURN_VAL_IF_FAIL(*mode, TDM_ERROR_INVALID_PARAMETER); + + *mode = fbdev_output->current_mode; + return TDM_ERROR_NONE; } @@ -619,21 +752,18 @@ fbdev_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) display_buffer->height = tbm_surface_get_height(buffer); /* - * TODO: Have to get more correct bo's size - */ - display_buffer->size = display_buffer->width * display_buffer->height; - - format = tbm_surface_get_format(buffer); - (void)format; - /* * TODO: We have got drm format here, have to be checked whether * Framebuffer device supports this format. * Do we need it at all? */ + format = tbm_surface_get_format(buffer); + (void)format; bo = tbm_surface_internal_get_bo(buffer, 0); bo_handle = tbm_bo_map(bo, TBM_DEVICE_CPU, opt); + display_buffer->size = tbm_bo_size(bo); + /* * When surface will be about to be destroyed there will have been * invoked our destroy handler which will unmap bo and free |