Index: trunk/kernel/devices/dev_fbf.h
===================================================================
--- trunk/kernel/devices/dev_fbf.h	(revision 647)
+++ trunk/kernel/devices/dev_fbf.h	(revision 657)
@@ -1,6 +1,6 @@
 /*
- * dev_fbf.h - FBF (Block Device Controler) generic device API definition.
+ * dev_fbf.h - FBF (Frame Buffer) generic device API definition.
  * 
- * Author  Alain Greiner    (2016,2017,2018,2019)
+ * Author  Alain Greiner    (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -27,4 +27,6 @@
 #include <hal_kernel_types.h>
 #include <shared_fbf.h>
+#include <remote_rwlock.h>
+#include <bits.h>
 
 /****  Forward declarations  ****/
@@ -33,22 +35,60 @@
 
 /*****************************************************************************************
- *     Generic Frame Buffer Controler definition
+ *      Frame Buffer Controler API definition
  *
  * This device provide access to an external graphic display, that is seen
  * as a fixed size frame buffer, mapped in the kernel address space.
- * The supported  pixel encoding types are defined in the <shared_fbf.h> file.
- *
- * It supports three command types:
- * GET_CONFIG : return frame buffer size and type.
- * READ       : move bytes from frame buffer to memory / deschedule the calling thread.
- * WRITE      : move bytes from memory to frame buffer / deschedule the calling thread.
- *
- * The READ and WRITE operations do not use the FBF device waiting queue, 
- * the server thread, and the IOC IRQ. The client thread does not deschedule:
- * it registers the command in the thread descriptor, and calls directly the FBF driver.
- * that makes a (user <-> kernel) memcpy.
+ * The only pixel encoding type in the current implementation is one byte per pixel
+ * (256 levels of gray).
+ *
+ * It supports a first API, for the user syscalls, implementing a simple windows manager.
+ * This windows manager allows any process to create and use for display one (or several) 
+ * window(s). Each window defines a private buffer, dynamically allocated in user space,
+ * that can be directly accessed by the owner process.
+ * These windows can be moved in the frame buffer, they can be resized, they can overlap
+ * other windows, but a window must be entirely contained in the frame buffer.
+ *
+ * To avoid contention, the window descriptor, and the associated user buffer are not
+ * allocated in the cluster containing the FBF chdev, but are distributed: each window
+ * is allocated in the cluster defined by the thread that required the window creation.
+ *
+ * Each window has a single process owner, but all the windows are registered in the FBF
+ * chdev as a windows_tbl[] array, indexed by the window identifier (wid), and each entry
+ * contains an extended pointer on the window descriptor. All windows are also registered
+ * in a trans-cluster xlist, defining the overlapping order (last window in xlist has the
+ * highest priority). 
+ *
+ * To refresh a window <wid>, the owner process calls the dev_fbf_refresh_window()
+ * function, that sends parallel RPC_FBF_DISPLAY requests to other cores. All cores
+ * synchronously execute the dev_fbf_display() function. This function scan all windows
+ * to respect the overlaping order, and updates all pixels of the <wid> window.
  * 
- * Note: As we don't use any external DMA to move data, but a purely software approach,
- * there is no L2/L3 coherence issue.
+ * 1) This "syscall" API defines five syscalls : 
+ * - FBF_GET_CONFIG     : returns the FBF width, height, and pixel encoding type.
+ * - FBF_CREATE_WINDOW  : create a new window , owned by the calling process.
+ * - FBF_DELETE_WINDOW  : delete a registered window. 
+ * - FBF_MOVE_WINDOW    : move in FBF a registered window.
+ * - FBF_REFRESH_WINDOW : request refresh of a given window.
+ *
+ * These 5 operations do not use the FBF device waiting queue, the associated
+ * device thread and the FBF IRQ, as the client thread does NOT deschedule,
+ * and does NOT call the FBF driver.
+ *
+ * 2) Two extra syscalls exist but are deprecated:
+ * - FBF_DIRECT_WRITE   : move synchronously pixels from an user buffer to the FBF.
+ * - FBF_DIRECT_READ    : move synchronously pixels from the FBF to an user buffer.
+ *
+ * For these deprecated operations, the client thread calls
+ * directly the driver to move data between the user buffer and the FBF.
+ * 
+ * 3) The FBF device defines defines four command types to access FBF driver(s) :
+ * - FBF_DRIVER_KERNEL_WRITE : move pixels from a kernel window to the FBF.
+ * - FBF_DRIVER_KERNEL_READ  : move pixels from the FBF to a kernel window.
+ * - FBF_DRIVER_USER_WRITE   : move bytes from an user buffer to the FBF. 
+ * - FBF_DRIVER_USER_READ    : move bytes from the FBF to an user buffer. 
+ *
+ * Note: As we don't use any external DMA to move data to or from the frame buffer,
+ * but only software memcpy, there is no L2/L3 coherence issue for this device.
+ *
  *****************************************************************************************/
 
@@ -59,7 +99,13 @@
 typedef struct fbf_extend_s
 {
-    uint32_t           width;         /*! number of pixels per line.                     */
-    uint32_t           height;        /*! total number of lines.                         */
-    uint32_t           subsampling;   /*! pixel encoding type.                           */
+    remote_rwlock_t windows_lock;        /*! lock protecting windows xlist               */
+    xlist_entry_t   windows_root;        /*! root of the windows xlist                   */
+
+    xptr_t          windows_tbl[CONFIG_FBF_WINDOWS_MAX_NR];         /*! window desc.     */
+    bitmap_t        windows_bitmap[CONFIG_FBF_WINDOWS_MAX_NR >> 5]; /*! wid allocator    */
+
+    uint32_t        width;               /*! number of pixels per line.                  */
+    uint32_t        height;              /*! total number of lines.                      */
+    uint32_t        subsampling;         /*! pixel encoding type.                        */
 }
 fbf_extend_t;
@@ -70,5 +116,5 @@
  *****************************************************************************************/
 
-enum fbf_impl_e
+typedef enum
 {
     IMPL_FBF_SCL =   0,     
@@ -77,20 +123,55 @@
 fbf_impl_t;
 
+/******************************************************************************************
+ * This structure defines the FBF command for all drivers implementing the FBF device.
+ *****************************************************************************************/
+
+typedef enum
+{
+    FBF_DRIVER_USER_READ     = 1,
+    FBF_DRIVER_USER_WRITE    = 2,
+    FBF_DRIVER_KERNEL_READ   = 3,
+    FBF_DRIVER_KERNEL_WRITE  = 4,
+}
+fbf_driver_cmd_type_t;
+
 typedef struct fbf_command_s
 {
     xptr_t      dev_xp;        /*! extended pointer on device descriptor                 */
-    uint32_t    type;          /*! requested operation type.                             */
-    uint32_t    length;        /*! number of bytes.                                      */
-    uint32_t    offset;        /*! offset in frame buffer (bytes)                        */
-    void      * buffer;        /*! pointer on memory buffer in user space                */
+    uint32_t    type;          /*! requested driver operation type.                      */
+    uint32_t    npixels;       /*! number of bytes.                                      */
+    uint32_t    offset;        /*! offset in frame buffer (pixels)                       */
+    void      * buffer;        /*! pointer on memory buffer (kernel or user)             */
     uint32_t    error;         /*! operation status (0 if success)                       */
 }
 fbf_command_t;
 
-
-/******************************************************************************************
- * This function returns a printable string for a given FBF command  <cmd_type>.
- ******************************************************************************************
- * @ cmd_type   :  FBF command type (defined in shared_fbf.h file).
+/******************************************************************************************
+ * This structure defines an FBF window descriptor, allocated to a given user process.
+ * The window descriptor and the associated buffer are allocated in the cluster where
+ * is running the thread requesting the window creation.
+ * The <wid> allocator, the window_tbl[] array, and the root of the xlist of windows are
+ * imlemented in the FBF device extension.
+ *****************************************************************************************/
+
+typedef struct fbf_window_s
+{
+    pid_t          pid;         /*! owner process identifier                             */
+    uint32_t       wid;         /*! window identifier                                    */
+    uint32_t       height;      /*! number of lines in window                            */
+    uint32_t       width;       /*! number of pixels per line in window                  */
+    uint32_t       l_min;       /*! first line index in FBF                              */
+    uint32_t       p_min;       /*! first pixel index in FBF                             */
+    uint8_t      * buffer;      /*! pointer on buffer in user space                      */
+    bool_t         hidden;      /*! no display on FBF when true                          */
+    xlist_entry_t  xlist;       /*! member of registered FBF windows list                */
+}
+fbf_window_t;
+
+/******************************************************************************************
+ * This function returns a printable string for a given FBF user command  <cmd_type>.
+ * WARNING : It must be kept consistent with the enum in the <shared_fbf.h> file
+ ******************************************************************************************
+ * @ cmd_type   :  FBF user command type (defined in shared_fbf.h file).
  * @ returns a string pointer.
  *****************************************************************************************/
@@ -100,5 +181,5 @@
  * This function completes the FBF chdev descriptor initialisation.
  * It calls the specific driver initialisation function, to initialise the hardware
- * device and the chdev extension. It must be called by a local thread.
+ * device, and the chdev extension. It must be called by a local thread.
  ******************************************************************************************
  * @ chdev      : pointer on FBF chdev descriptor.
@@ -107,7 +188,9 @@
 
 /******************************************************************************************
- * This function returns the frame buffer size and type.
+ * This function implements the fbf_get_config() syscall, and returns the FBF
+ * size and type. It can be called by a client thread running in any cluster.
  * It does NOT access the hardware, as the size and type have been registered
- * in the chdev descriptor extension.
+ * in the chdev descriptor extension by the dev_fbf_init() function.
+ * It can be called by any thread running in any cluster.
  ******************************************************************************************
  * @ width     : [out] number of pixels per line.
@@ -120,20 +203,162 @@
 
 /******************************************************************************************
- * This blocking function moves <length> bytes between the frame buffer, starting from
- * byte defined by <offset>, and an user buffer defined by the <user_buffer> argument.
- * It can be called by a client thread running in any cluster.
- * The transfer direction are defined by the <cmd_type> argument.
+ * This function implements the fbf_create_window() syscall.
+ * It registers a new window in the windows_tbl[] array, and the windows list,
+ * registers in the reference cluster an ANON vseg, that will be mapped in local cluster. 
+ * The window index <wid> is dynamically allocated. The owner is the calling process.
+ * The FBF window is defined by the <nlines>, <npixels>, <l_min>, <p_min> arguments.
+ * It can be called by any thread running in any cluster. As this vseg is not directly 
+ * mapped to the frame buffer, the owner process can access this private buffer without
+ * syscall. As for any vseg, the physical memory is allocated on demand at each page fault.
+* The created vseg base address in user space is returned in the <user_base> argument.
+ *
+ * Implementation note:
+ * 1. it allocates memory in the local cluster for the window,
+ * 2. it creates in the associated vseg,
+ * 3. it initializes the window descriptor,
+ * 4. it takes the lock protecting the windows in write mode,
+ * 5. it allocates a new  <wid>,
+ * 6. it registers the window in the window_tbl[] array,
+ * 7. it registers the window in the windows list,
+ * 8. it releases the lock protecting windows.
+ * It does not call the FBF driver. 
+ ******************************************************************************************
+ * @ nlines      : [in]  number of lines in window.
+ * @ npixels     : [in]  number of pixels per line in window.
+ * @ l_min       : [in]  first pixel index in FBF.
+ * @ p_min       : [in]  first line index in FBF.
+ * @ user_base   : [out] pointer on allocated buffer base in user space.
+ * @ return the <wid> index if success / returns -1 if failure
+ *****************************************************************************************/
+uint32_t dev_fbf_create_window( uint32_t   nlines,
+                                uint32_t   npixels,
+                                uint32_t   l_min,
+                                uint32_t   p_min,
+                                intptr_t * user_base );
+
+/******************************************************************************************
+ * This function implements the fbf_delete_window() syscall to delete a FBF window,
+ * and release all memory allocated for this window and for the associated vseg.
+ * releases the memory allocated for the window buffer and for the window descriptor.
+ * It can be called by any thread running in any cluster.
+ *
+ * Implementation note:
+ * 1. it takes the lock protecting windows in write mode,
+ * 2. it set the hidden flag in deleted window descriptor,
+ * 3. it refresh the FBF window,
+ * 4. it removes the window from windows_tbl[] array,
+ * 5. it removes the window from xlist,      
+ * 6. it releases the wid to bitmap,
+ * 7. it releases the lock protecting windows,
+ * 8. it releases the memory allocated for window descriptor,
+ * 9. it deletes the associated vseg in all clusters
+ * It does not call directly the FBF driver.
+ ******************************************************************************************
+ * @ wid       : [in] window index in window_tbl[].
+ * @ returns 0 if success / returns -1 if wid not registered.
+ *****************************************************************************************/
+error_t dev_fbf_delete_window( uint32_t wid );
+                                
+/******************************************************************************************
+ * This function implements the fbf_move_window() syscall.
+ * It moves a window identified by the <wid> argument to a new position in the FBF,
+ * defined by the <l_min> and <p_min> arguments.
+ * It can be called by any thread running in any cluster.
+ *
+ * Implementation note:
+ * 1. it takes the lock protecting windows in write mode,
+ * 2. it gives the modified window the lowest priority,
+ * 3. it set the "hidden" flag in window descriptor,
+ * 4. it refresh the FBF for the current window position,
+ * 5. it set the new coordinates in the window descriptor,
+ * 6. it gives the modified window the highest priority,
+ * 7. it reset the "hidden" flag in window descriptor,
+ * 8. it refresh the FBF for the new window position,
+ * 9. it releases the lock protecting windows,
+ * It does not call directly the FBF driver.
+ ******************************************************************************************
+ * @ wid       : [in] window index in window_tbl[].
+ * @ l_min     : [in] new first pixel index in FBF.
+ * @ p_min     : [in] new first line index in FBF.
+ * @ returns 0 if success / returns -1 if illegal arguments.
+ *****************************************************************************************/
+error_t dev_fbf_move_window( uint32_t wid,
+                             uint32_t l_min,
+                             uint32_t p_min );
+
+/******************************************************************************************
+ * This function implements the fbf_resize_window() syscall.
+ * It changes the <width> and <height> of a window identified by the <wid> argument.
+ * It updates the associated vseg "size" if required, but does not change the vseg "base".
+ * When the new window buffer is larger than the existing one, it is 0 filled.
+ * It can be called by any thread running in any cluster.
+ *
+ * Implementation note:
+ * 1.  it takes the lock protecting windows in write mode,
+ * 2.  it gives the modified window the lowest priority,
+ * 3.  it set the "hidden" flag in window descriptor,
+ * 4.  it refresh the FBF for the current window,
+ * 5.  it set the new size in the window descriptor,
+ * 6.  it resizes the associated vseg if required,
+ * 7.  if fill the window buffer extension with 0 if required,
+ * 8.  it gives the modified window the highest priority,
+ * 9.  it reset the "hidden" flag in window descriptor,
+ * 10. it refresh the FBF for the new window,
+ * 11. it releases the lock protecting windows,
+ * It does not call directly the FBF driver.
+ ******************************************************************************************
+ * @ wid       : [in] window index in window_tbl[].
+ * @ width     : [in] new number of pixels per line.
+ * @ height    : [in] new number of lines.
+ * @ returns 0 if success / returns -1 if illegal arguments.
+ *****************************************************************************************/
+error_t dev_fbf_resize_window( uint32_t wid,
+                               uint32_t width,
+                               uint32_t height );
+
+/******************************************************************************************
+ * This function implements the fbf_refresh_window() syscall.
+ * It allows an owner process to signal the windows manager that some lines of a window
+ * identified by the <wid>, <line_min>, and <line_max> argument have been modified, and
+ * must be refreshed in the FBF. It scans all the registered FBF windows to respect the
+ * overlap order defined by the windows xlist.
+ * It can be called by any thread running in any cluster.
+ *
+ * Implementation note:
+ * 1. it takes the lock protecting windows in read mode,
+ * 2. it refresh the FBF,
+ * 3. it releases the lock protecting windows,
+ * It does not call directly the FBF driver.
+ ******************************************************************************************
+ * @ wid        : [in] window index in window_tbl[]
+ * @ line_first : [in] first line index in window.
+ * @ line_last  : [in] last line index (excluded).
+ * @ returns 0 if success / returns -1 if wid not registered.
+ *****************************************************************************************/
+error_t dev_fbf_refresh_window( uint32_t wid,
+                                uint32_t line_first,
+                                uint32_t line_last );
+
+/******************************************************************************************
+ * WARNING : This function is deprecated ( january 2020 [AG] ). It was defined 
+ * to implement the fbf_read() and fbf_write() deprecated syscalls.
+ *
+ * It  moves <length> bytes between the frame buffer, starting from pixel defined
+ * by the <offset> argument, and an user buffer defined by the <user_buffer> argument.
+ * The transfer direction are defined by the <is_write> argument.
+ * An error is returned when <offset> + <npixels> is larger than the FBF size.
  * The request is registered in the client thread descriptor, but the client thread is
  * not descheduled, and calls directly the FBF driver.
- ******************************************************************************************
- * @ cmd_type    : FBF_READ / FBF_WRITE / FBF_SYNC_READ / FBF_SYN_WRITE.
- * @ user_buffer : pointer on memory buffer in user space.
- * @ length      : number of bytes.
- * @ offset      : first byte in frame buffer.    
- * @ returns 0 if success / returns EINVAL if error.
- *****************************************************************************************/
-error_t dev_fbf_move_data( uint32_t   cmd_type,
+ * It can be called by a client thread running in any cluster.
+ ******************************************************************************************
+ * @ is_write    : [in] write FBF weh true / read FBF when false
+ * @ user_buffer : [in] pointer on memory buffer in user space.
+ * @ npixels     : [in] number of bytes.
+ * @ offset      : [in] first byte in frame buffer.    
+ * @ returns 0 if success / returns -1 if error.
+ *****************************************************************************************/
+error_t dev_fbf_move_data( bool_t     is_write,
                            void     * user_buffer,
-                           uint32_t   length,
+                           uint32_t   npixels,
                            uint32_t   offset );
 
