add implementation of fbdev's output callbacks except vblank related ones 65/61365/1
authorRoman Peresipkyn <r.peresipkyn@samsung.com>
Thu, 4 Feb 2016 16:55:46 +0000 (18:55 +0200)
committerSooChan Lim <sc1.lim@samsung.com>
Mon, 7 Mar 2016 10:53:33 +0000 (19:53 +0900)
Change-Id: I86b79d3ab8e8d8082e16033f221ae18880a5d8e7
Signed-off-by: Roman Peresipkyn <r.peresipkyn@samsung.com>
src/tdm_fbdev.c
src/tdm_fbdev.h
src/tdm_fbdev_display.c

index 4c030ef..db99e0e 100644 (file)
@@ -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);
 
index 45de32f..6fd02b6 100644 (file)
@@ -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
index 823dbeb..b2bd509 100644 (file)
@@ -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