Task

Implement the   Xiaolin Wu's line algorithm   described in Wikipedia.



This algorithm draws anti-aliased lines.



Related task

   See   Bresenham's line algorithm   for aliased lines.


 
 
/* ARM assembly Raspberry PI  */
/*  program xiaolin1.s   */
 
/* REMARK 1 : this program use routines in a include file 
   see task Include a file language arm assembly 
   for the routine affichageMess displayerror 
   see at end oh this program the instruction include */
 
/* REMARK 2 : display use a FrameBuffer device : see raspberry pi FrameBuffer documentation
              this solution write directly on the screen of raspberry pi
              other solution is to use X11 windows but X11 has a function drawline !! */
 
/* REMARK 3 : this program do not respect the convention for use, save and restau registers
              in rhe routine call !!!!   */
 
/*******************************************/
/* Constantes    */
/*******************************************/
.equ STDOUT,              1     @ Linux output console
.equ EXIT,                1     @ Linux syscall
.equ WRITE,               4     @ Linux syscall
.equ OPEN,                5
.equ CLOSE,               6
.equ IOCTL,               0x36
.equ MMAP,                0xC0
.equ UNMAP,               0x5B
.equ O_RDWR,              0x0002    @ open for reading and writing
.equ MAP_SHARED,          0x01      @ Share changes.
.equ PROT_READ,           0x1       @ Page can be read.
.equ PROT_WRITE,          0x2       @ Page can be written.
 
/*******************************************/
/* Initialized data                        */
/*******************************************/
.data
szMessErreur:   .asciz "File open error.\n"
szMessErreur1:  .asciz "File close error.\n"
szMessErreur2:  .asciz "File mapping error.\n"
szMessDebutPgm: .asciz "Program start. \n"
szMessFinOK:    .asciz "Normal end program. \n"
szMessErrFix:   .asciz  "Read error info fix framebuffer  \n"
szMessErrVar:   .asciz  "Read error info var framebuffer  \n"
szRetourligne:  .asciz  "\n"
szParamNom:     .asciz "/dev/fb0"         @ FrameBuffer device name
szLigneVar:     .ascii "Variables info : "
sWidth:        .fill 11, 1, ' ' 
                .ascii " * "
sHeight:        .fill 11, 1, ' ' 
                .ascii " Bits par pixel : "
sBits:           .fill 11, 1, ' '
                .asciz  "\n"
/*************************************************/
szMessErr: .ascii	"Error code hexa : "
sHexa: .space 9,' '
         .ascii "  decimal :  "
sDeci: .space 15,' '
         .asciz "\n"
.align 4
/* codes fonction pour la récupération des données fixes et variables */
FBIOGET_FSCREENINFO: .int 0x4602  @ function code for read infos fixes Framebuffer
FBIOGET_VSCREENINFO: .int 0x4600  @ function code for read infos variables Framebuffer
 
/*******************************************/
/* UnInitialized data */
/*******************************************/ 
.bss
.align 4
fix_info: .skip FBFIXSCinfo_fin                @ memory reserve for structure FSCREENINFO
.align 4
var_info: .skip FBVARSCinfo_fin                @ memory reserve for structure VSCREENINFO
/**********************************************/
/* -- Code section                            */
/**********************************************/
.text
.global main
 
main:
    ldr r0,iAdrszMessDebutPgm
    bl affichageMess                  @ display message
    ldr r0,iAdrszParamNom             @ frameBuffer device name
    mov r1,#O_RDWR                    @ flags read/write
    mov r2,#0                         @ mode 
    mov r7,#OPEN                      @ open device FrameBuffer 
    svc 0 
    cmp r0,#0                         @ error ?
    ble erreur
    mov r10,r0                        @ save FD du device FrameBuffer in r10
 
    ldr r1,iAdrFBIOGET_VSCREENINFO    @ read variables datas of FrameBuffer
    ldr r1,[r1]                       @ load code function
    ldr r2,iAdrvar_info               @ structure memory address
    mov r7, #IOCTL                    @ call system
    swi 0 
    cmp r0,#0
    blt erreurVar
    ldr r2,iAdrvar_info
    ldr r0,[r2,#FBVARSCinfo_xres]     @ load screen width
    ldr r1,iAdrsWidth                 @ and convert in string for display
    bl conversion10S
    ldr r0,[r2,#FBVARSCinfo_yres]     @ load screen height 
    ldr r1,iAdrsHeight                @ and convert in string for display
    bl conversion10S
    ldr r0,[r2,#FBVARSCinfo_bits_per_pixel]  @ load bits by pixel  
    ldr r1,iAdrsBits                  @ and convert in string for display
    bl conversion10S
    ldr r0,iAdrszLigneVar             @ display result 
    bl affichageMess
 
    mov r0,r10                        @ FD du FB
    ldr r1,iAdrFBIOGET_FSCREENINFO    @ read fixes datas of FrameBuffe
    ldr r1,[r1]                       @ load code function
    ldr r2,iAdrfix_info               @ structure memory address
    mov r7, #IOCTL                    @ call system
    svc 0 
    cmp r0,#0                         @ error ?
    blt erreurFix
    ldr r0,iAdrfix_info
 
    ldr r1,iAdrfix_info               @ read size memory for datas
    ldr r1,[r1,#FBFIXSCinfo_smem_len] @ in octets
                                      @ datas mapping
    mov r0,#0
    ldr r2,iFlagsMmap
    mov r3,#MAP_SHARED
    mov r4,r10
    mov r5,#0
    mov r7, #MMAP                     @ 192 call system for mapping
    swi #0 
    cmp r0,#0                         @ error ?
    beq erreur2    
    mov r9,r0                         @ save mapping address in r9
    /*************************************/
    /* display draw                      */
    bl dessin
    /************************************/
    mov r0,r9                         @ mapping close
    ldr r1,iAdrfix_info
    ldr r1,[r1,#FBFIXSCinfo_smem_len] @ mapping memory size
    mov r7,#UNMAP                     @call system 91 for unmapping
    svc #0                            @ error ?
    cmp r0,#0
    blt erreur1    
                                      @ close device FrameBuffer
    mov r0,r10                        @ load FB du device
    mov r7, #CLOSE                    @ call system
    swi 0 
    ldr r0,iAdrszMessFinOK            @ display end message
    bl affichageMess
    mov r0,#0                         @ return code = OK
    b 100f
erreurFix:                            @ display read error datas fix
    ldr r1,iAdrszMessErrFix           @ message address
    bl   displayError                 @ call display
    mov r0,#1                         @ return code = error
    b 100f
erreurVar:                            @ display read error datas var
    ldr r1,iAdrszMessErrVar
    bl   displayError
    mov r0,#1
    b 100f
erreur:                               @ display open error 
    ldr r1,iAdrszMessErreur
    bl   displayError
    mov r0,#1
    b 100f
erreur1:                              @ display unmapped error
    ldr r1,iAdrszMessErreur1
    bl   displayError
    mov r0,#1
    b 100f
erreur2:                              @ display mapped error
    ldr r1,iAdrszMessErreur2
    bl   displayError
    mov r0,#1
    b 100f
100:                                  @ end program
    mov r7, #EXIT
    svc 0 
/************************************/
iAdrszParamNom:           .int szParamNom
iFlagsMmap:               .int PROT_READ|PROT_WRITE
iAdrszMessErreur:         .int szMessErreur
iAdrszMessErreur1:        .int szMessErreur1
iAdrszMessErreur2:        .int szMessErreur2
iAdrszMessDebutPgm:       .int szMessDebutPgm
iAdrszMessFinOK:          .int szMessFinOK
iAdrszMessErrFix:         .int szMessErrFix
iAdrszMessErrVar:         .int szMessErrVar
iAdrszLigneVar:           .int szLigneVar
iAdrvar_info:             .int var_info
iAdrfix_info:             .int fix_info
iAdrFBIOGET_FSCREENINFO:  .int FBIOGET_FSCREENINFO
iAdrFBIOGET_VSCREENINFO:  .int FBIOGET_VSCREENINFO
iAdrsWidth:               .int sWidth
iAdrsHeight:              .int sHeight
iAdrsBits:                .int sBits
/***************************************************/
/*   dessin                  */
/***************************************************/
/* r9 framebuffer memory address   */
dessin:
    push {r1-r12,lr}                  @ save registers
    mov r0,#255                       @ red
    mov r1,#255                       @ green
    mov r2,#255                       @ blue    3 bytes 255 = white
    bl codeRGB                        @ code color RGB  32 bits
    mov r1,r0                         @ background color
    ldr r0,iAdrfix_info               @ load memory mmap size 
    ldr r0,[r0,#FBFIXSCinfo_smem_len]    
    bl coloriageFond                  @
    /* draw line 1  */
    mov r0,#200                       @ X start line
    mov r1,#200                       @ Y start line
    mov r2,#200                       @ X end line
    mov r3,#100                       @ Y end line
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]     @ load screen width
    bl drawLine
    /* draw line 2  */
    mov r0,#200
    mov r1,#200
    mov r2,#200
    mov r3,#300
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
    /* draw line 3  */
    mov r0,#200
    mov r1,#200
    mov r2,#100
    mov r3,#200
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
    /* draw line 4  */
    mov r0,#200
    mov r1,#200
    mov r2,#300
    mov r3,#200
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
    /* draw line 5  */
    mov r0,#200
    mov r1,#200
    mov r2,#100
    mov r3,#100
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
    /* draw line 6  */
    mov r0,#200
    mov r1,#200
    mov r2,#100         
    mov r3,#300
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
    /* draw line 7  */
    mov r0,#200
    mov r1,#200
    mov r2,#300
    mov r3,#300
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
    /* draw line 8  */
    mov r0,#200
    mov r1,#200
    mov r2,#300
    mov r3,#100
    ldr r4,iAdrvar_info
    ldr r4,[r4,#FBVARSCinfo_xres]
    bl drawLine
 
100:
    pop {r1-r12,lr}                 @ restaur registers
    bx lr                           @ end function
 
/********************************************************/
/*   set background color                               */
/********************************************************/
/* r0 contains size screen memory  */
/* r1 contains rgb code color      */
/* r9 contains screen memory address */
coloriageFond:
    push {r2,lr}
    mov r2,#0                     @ counter 
1:                                @ begin loop
    str r1,[r9,r2]
    add r2,#4
    cmp r2,r0
    blt 1b
    pop {r2,lr}
    bx lr
/********************************************************/
/*   Xiaolin Wu  line algorithm                        */
/*  no floating point compute,  multiply value for 128  */
/*  for integer compute                                 */
/********************************************************/
/* r0  x1 start line */
/* r1  y1 start line */
/* r2  x2 end line */
/* r3  y2 end line */
/* r4  screen width */
drawLine:
    push {fp,lr}      @ save registers ( no other registers save )
    mov r5,r0         @ save x1
    mov r6,r1         @ save y1
    cmp r2,r5         @ compar x2,x1
    subgt r1,r2,r5
    suble r1,r5,r2    @ compute dx=abs val de x1-x2
    cmp r3,r6         @ compar y2,y1
    subgt r0,r3,r6
    suble r0,r6,r3    @ compute dy = abs val de y1-y2
    cmp r1,r0         @ compare dx , dy
    blt 5f            @ dx < dy
                      @ dx > dy
    cmp r2,r5         @ compare x2,x1
    movlt r8,r5       @ x2 < x1 
    movlt r5,r2       @ swap x2,x1
    movlt r2,r8
    movlt r8,r6       @ swap y2,y1
    movlt r6,r3
    movlt r3,r8
    lsl r0,#7         @ * by 128
    mov r7,r2         @ save x2
    mov r8,r3         @ save y2
    cmp r1,#0         @ divisor = 0 ?
    moveq r10,#128
    beq 1f
    bl division       @ gradient compute (* 128)
    mov r10,r2        @ r10 contient le gradient
1:
    @ display start points
    mov r0,#64
    bl colorPixel
    mov r3,r0              @ RGB color 
    mov r0,r5              @ x1
    mov r1,r6              @ y1
    mov r2,r4              @ screen witdh 
    bl aff_pixel_codeRGB32 @ display pixel
    add r1,#1              @ increment y1
    bl aff_pixel_codeRGB32
    @ display end points
    mov r0,r7              @ x2
    mov r1,r8              @ y2
    bl aff_pixel_codeRGB32
    add r1,#1              @ increment y2 
    bl aff_pixel_codeRGB32
    cmp r8,r6              @ compar y2,y1
    blt 3f                 @ y2 < y1
    mov r4,r5              @ x =  x1 
    lsl r5,r6,#7           @ compute y1 * 128
    add r5,r10             @ compute intery = (y1 * 128 + gradient * 128)
2:                         @ start loop draw line pixels
    lsr r1,r5,#7           @ intery / 128  = y
    lsl r8,r1,#7
    sub r6,r5,r8           @ reminder of intery /128 = brightness
    mov r0,r6
    bl colorPixel          @ compute rgb color brightness
    mov r3,r0              @ rgb color
    mov r0,r4              @ x 
    bl aff_pixel_codeRGB32 @ display pixel 1
    add r1,#1              @ increment y
    rsb r0,r6,#128         @ compute 128 - brightness
    bl colorPixel          @ compute new rgb color
    mov r3,r0
    mov r0,r4
    bl aff_pixel_codeRGB32 @ display pixel 2
    add r5,r10             @ add gradient to intery
    add r4,#1              @ increment x
    cmp r4,r7              @ x < x2
    ble 2b                 @ yes -> loop
    b 100f                 @ else end
3:                         @ y2 < y1  
    mov r4,r7              @ x = x2 
    mov r7,r5              @ save x1
    lsl r5,r8,#7           @ y = y1 * 128 
    add r5,r10             @ compute intery = (y1 * 128 + gradient * 128)
4:
    lsr r1,r5,#7           @ y = ent(intery / 128)
    lsl r8,r1,#7
    sub r8,r5,r8           @ brightness = remainder
    mov r0,r8
    bl colorPixel
    mov r3,r0
    mov r0,r4
    bl aff_pixel_codeRGB32
    add r1,#1
    rsb r0,r8,#128
    bl colorPixel
    mov r3,r0
    mov r0,r4
    bl aff_pixel_codeRGB32
    add r5,r10
    sub r4,#1             @ decrement x
    cmp r4,r7             @ x > x1
    bgt 4b                @ yes -> loop
    b 100f
5:                        @ dx < dy
    cmp r3,r6             @ compare y2,y1
    movlt r8,r5           @ y2 < y1 
    movlt r5,r2           @ swap x1,x2
    movlt r2,r8
    movlt r8,r6           @ swap y1,y2
    movlt r6,r3
    movlt r3,r8
    mov r8,r1             @ swap r0,r1 for routine division
    mov r1,r0
    lsl r0,r8,#7          @ dx * by 128
    mov r7,r2             @ save x2
    mov r8,r3             @ save y2
    cmp r1,#0             @ dy = zero ?
    moveq r10,#128
    beq 6f
    bl division           @  compute gradient * 128
    mov r10,r2            @  gradient -> r10
6:
    @ display start points
    mov r0,#64
    bl colorPixel
    mov r3,r0             @ color pixel
    mov r0,r5             @ x1
    mov r1,r6             @ y1
    mov r2,r4             @ screen width
    bl aff_pixel_codeRGB32
    add r1,#1
    bl aff_pixel_codeRGB32
    @ display end points
    mov r0,r7
    mov r1,r8
    bl aff_pixel_codeRGB32
    add r1,#1
    bl aff_pixel_codeRGB32
    cmp r5,r7                  @ x1 < x2 ?
    blt 8f
    mov r4,r6                  @  y = y1
    lsl r5,#7                  @ compute x1 * 128
    add r5,r10                 @ compute interx
7:
    lsr r1,r5,#7               @ compute x = ent ( interx / 128)
    lsl r3,r1,#7
    sub r6,r5,r3               @ brightness = remainder
    mov r0,r6
    bl colorPixel
    mov r3,r0
    mov r0,r1                  @ new x
    add r7,r0,#1
    mov r1,r4                  @ y
    bl aff_pixel_codeRGB32
    rsb r0,r6,#128
    bl colorPixel
    mov r3,r0
    mov r0,r7                  @ new x + 1
    mov r1,r4                  @ y
    bl aff_pixel_codeRGB32
    add r5,r10
    add r4,#1
    cmp r4,r8
    ble 7b
    b 100f
8:
    mov r4,r8                  @  y = y2
    lsl r5,#7                  @ compute x1 * 128
    add r5,r10                 @ compute interx
9:
    lsr r1,r5,#7               @ compute x
    lsl r3,r1,#7
    sub r8,r5,r3
    mov r0,r8
    bl colorPixel
    mov r3,r0
    mov r0,r1                  @ new x
    add r7,r0,#1
    mov r1,r4                  @ y
    bl aff_pixel_codeRGB32
    rsb r0,r8,#128
    bl colorPixel
    mov r3,r0
    mov r0,r7                  @ new x + 1
    mov r1,r4                  @ y
    bl aff_pixel_codeRGB32
    add r5,r10
    sub r4,#1
    cmp r4,r6
    bgt 9b
    b 100f
100:
    pop {fp,lr}
    bx lr
/********************************************************/
/*   brightness color pixel                              */
/********************************************************/
/* r0 % brightness ( 0 to 128)  */
colorPixel:
    push {r1,r2,lr}    /* save des  2 registres frame et retour */
    cmp r0,#0
    beq 100f
    cmp r0,#128
    mov r0,#127
    lsl r0,#1          @ red = brightness * 2 ( 2 to 254)
    mov r1,r0          @ green = red
    mov r2,r0          @ blue = red
    bl codeRGB         @ compute rgb code color 32 bits
100:
    pop {r1,r2,lr}
    bx lr 
 
/***************************************************/
/*   display pixels  32 bits                       */
/***************************************************/
/* r9 framebuffer memory address */
/* r0 = x */
/* r1 = y */
/* r2 screen width in pixels */
/* r3 code color RGB 32 bits  */
aff_pixel_codeRGB32:
    push {r0-r4,lr}       @  save registers
                          @ compute location pixel
    mul r4,r1,r2          @ compute y * screen width
    add r0,r0,r4          @ + x
    lsl r0,#2             @ * 4 octets
    str r3,[r9,r0]        @ store rgb code in mmap memory
    pop {r0-r4,lr}        @ restaur registers
    bx lr
/********************************************************/
/*   Code color RGB                                     */
/********************************************************/
/* r0 red r1 green  r2 blue */
/* r0 returns RGB code      */
codeRGB:
    lsl r0,#16               @ shift red color 16 bits
    lsl r1,#8                @ shift green color 8 bits
    eor r0,r1                @ or two colors
    eor r0,r2                @ or 3 colors in r0
    bx lr
 
/***************************************************/
/*      ROUTINES INCLUDE                 */
/***************************************************/
.include "./affichage.inc"
 
/***************************************************/
/*      DEFINITION DES STRUCTURES                 */
/***************************************************/
/* structure FSCREENINFO */    
/* voir explication détaillée : https://www.kernel.org/doc/Documentation/fb/api.txt */
    .struct  0
FBFIXSCinfo_id:          /* identification string eg "TT Builtin" */
    .struct FBFIXSCinfo_id + 16  
FBFIXSCinfo_smem_start:    /* Start of frame buffer mem */
    .struct FBFIXSCinfo_smem_start + 4   
FBFIXSCinfo_smem_len:       /* Length of frame buffer mem */
    .struct FBFIXSCinfo_smem_len + 4   
FBFIXSCinfo_type:    /* see FB_TYPE_*        */
    .struct FBFIXSCinfo_type + 4  
FBFIXSCinfo_type_aux:      /* Interleave for interleaved Planes */
    .struct FBFIXSCinfo_type_aux + 4  
FBFIXSCinfo_visual:    /* see FB_VISUAL_*        */
    .struct FBFIXSCinfo_visual + 4  
FBFIXSCinfo_xpanstep:    /* zero if no hardware panning  */
    .struct FBFIXSCinfo_xpanstep + 2      
FBFIXSCinfo_ypanstep:    /* zero if no hardware panning  */
    .struct FBFIXSCinfo_ypanstep + 2 
FBFIXSCinfo_ywrapstep:      /* zero if no hardware ywrap    */
    .struct FBFIXSCinfo_ywrapstep + 4 
FBFIXSCinfo_line_length:    /* length of a line in bytes    */
    .struct FBFIXSCinfo_line_length + 4 
FBFIXSCinfo_mmio_start:     /* Start of Memory Mapped I/O   */
    .struct FBFIXSCinfo_mmio_start + 4     
FBFIXSCinfo_mmio_len:        /* Length of Memory Mapped I/O  */
    .struct FBFIXSCinfo_mmio_len + 4 
FBFIXSCinfo_accel:     /* Indicate to driver which    specific chip/card we have    */
    .struct FBFIXSCinfo_accel + 4 
FBFIXSCinfo_capabilities:     /* see FB_CAP_*            */
    .struct FBFIXSCinfo_capabilities + 4 
FBFIXSCinfo_reserved:     /* Reserved for future compatibility */
    .struct FBFIXSCinfo_reserved + 8    
FBFIXSCinfo_fin:
 
/* structure VSCREENINFO */    
    .struct  0
FBVARSCinfo_xres:           /* visible resolution        */ 
    .struct FBVARSCinfo_xres + 4  
FBVARSCinfo_yres:          
    .struct FBVARSCinfo_yres + 4 
FBVARSCinfo_xres_virtual:          /* virtual resolution        */
    .struct FBVARSCinfo_xres_virtual + 4 
FBVARSCinfo_yres_virtual:          
    .struct FBVARSCinfo_yres_virtual + 4 
FBVARSCinfo_xoffset:          /* offset from virtual to visible resolution */
    .struct FBVARSCinfo_xoffset + 4 
FBVARSCinfo_yoffset:          
    .struct FBVARSCinfo_yoffset + 4 
FBVARSCinfo_bits_per_pixel:          /* bits par pixel */
    .struct FBVARSCinfo_bits_per_pixel + 4     
FBVARSCinfo_grayscale:          /* 0 = color, 1 = grayscale,  >1 = FOURCC    */
    .struct FBVARSCinfo_grayscale + 4 
FBVARSCinfo_red:          /* bitfield in fb mem if true color, */
    .struct FBVARSCinfo_red + 4 
FBVARSCinfo_green:          /* else only length is significant */
    .struct FBVARSCinfo_green + 4 
FBVARSCinfo_blue:          
    .struct FBVARSCinfo_blue + 4 
FBVARSCinfo_transp:          /* transparency            */
    .struct FBVARSCinfo_transp + 4     
FBVARSCinfo_nonstd:          /* != 0 Non standard pixel format */
    .struct FBVARSCinfo_nonstd + 4 
FBVARSCinfo_activate:          /* see FB_ACTIVATE_*        */
    .struct FBVARSCinfo_activate + 4     
FBVARSCinfo_height:              /* height of picture in mm    */
    .struct FBVARSCinfo_height + 4 
FBVARSCinfo_width:           /* width of picture in mm     */
    .struct FBVARSCinfo_width + 4 
FBVARSCinfo_accel_flags:          /* (OBSOLETE) see fb_info.flags */
    .struct FBVARSCinfo_accel_flags + 4 
/* Timing: All values in pixclocks, except pixclock (of course) */    
FBVARSCinfo_pixclock:          /* pixel clock in ps (pico seconds) */
    .struct FBVARSCinfo_pixclock + 4     
FBVARSCinfo_left_margin:          
    .struct FBVARSCinfo_left_margin + 4 
FBVARSCinfo_right_margin:          
    .struct FBVARSCinfo_right_margin + 4 
FBVARSCinfo_upper_margin:          
    .struct FBVARSCinfo_upper_margin + 4 
FBVARSCinfo_lower_margin:          
    .struct FBVARSCinfo_lower_margin + 4 
FBVARSCinfo_hsync_len:          /* length of horizontal sync    */
    .struct FBVARSCinfo_hsync_len + 4     
FBVARSCinfo_vsync_len:          /* length of vertical sync    */
    .struct FBVARSCinfo_vsync_len + 4 
FBVARSCinfo_sync:          /* see FB_SYNC_*        */
    .struct FBVARSCinfo_sync + 4 
FBVARSCinfo_vmode:          /* see FB_VMODE_*        */
    .struct FBVARSCinfo_vmode + 4 
FBVARSCinfo_rotate:          /* angle we rotate counter clockwise */
    .struct FBVARSCinfo_rotate + 4     
FBVARSCinfo_colorspace:          /* colorspace for FOURCC-based modes */
    .struct FBVARSCinfo_colorspace + 4     
FBVARSCinfo_reserved:          /* Reserved for future compatibility */
    .struct FBVARSCinfo_reserved + 16        
FBVARSCinfo_fin:
 
 