format binary
use64

;-------------------------------------------------------------------------------
; DESC:     SDL defines.
;-------------------------------------------------------------------------------
SDL_INIT_VIDEO = 0x00000020
SDL_OPENGL = 0x00000002
SDL_NOFRAME = 0x00000020
SDL_GL_RED_SIZE = 0
SDL_GL_GREEN_SIZE = 1
SDL_GL_BLUE_SIZE = 2
SDL_GL_DOUBLEBUFFER = 5
SDL_GL_DEPTH_SIZE = 6
SDL_GL_STENCIL_SIZE = 7
SDL_KEYDOWN = 2
SDL_KEYUP = 3
SDL_MOUSEMOTION = 4
SDL_MOUSEBUTTONDOWN = 5
SDL_MOUSEBUTTONUP = 6
SDL_QUIT = 12
SDLK_ESCAPE	= 27
SDLK_UP = 273
SDLK_DOWN = 274
SDLK_RIGHT = 275
SDLK_LEFT = 276
SDLK_a = 97
SDLK_z = 122
;-------------------------------------------------------------------------------
; DESC:     OpenGL enums.
;-------------------------------------------------------------------------------
GL_COLOR_BUFFER_BIT = 0x00004000
GL_STENCIL_BUFFER_BIT = 0x00000400
GL_VERTEX_PROGRAM_ARB = 0x8620
GL_FRAGMENT_PROGRAM_ARB = 0x8804
GL_PROGRAM_FORMAT_ASCII_ARB = 0x8875
GL_STATIC_DRAW = 0x88E4
GL_BUFFER_GPU_ADDRESS_NV = 0x8F1D
GL_READ_ONLY = 0x88B8
GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV = 0x8F1E
GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV = 0x8F20
GL_FALSE = 0
GL_TRUE = 1
GL_ZERO = 0
GL_TRIANGLES = 0x0004
GL_TRIANGLE_STRIP = 0x0005
GL_FLOAT = 0x1406
GL_STENCIL_TEST = 0x0B90
GL_DEPTH_TEST = 0x0B71
GL_NOTEQUAL = 0x0205
GL_KEEP = 0x1E00
GL_COUNT_UP_NV = 0x9088
GL_BOUNDING_BOX_NV = 0x908D
GL_CLOSE_PATH_NV = 0x00
GL_MOVE_TO_NV = 0x02
GL_RELATIVE_MOVE_TO_NV = 0x03
GL_LINE_TO_NV = 0x04
GL_STANDARD_FONT_NAME_NV = 0x9072
GL_USE_MISSING_GLYPH_NV = 0x90AA
GL_TRANSLATE_X_NV = 0x908E
;-------------------------------------------------------------------------------
; DESC:     Load libc function.
;-------------------------------------------------------------------------------
macro       LDLIBCF     name* {
            xor         edi,edi
            mov         rsi,g_str_#name
            call        [dlsym]
            mov         [name],rax
}
;-------------------------------------------------------------------------------
; DESC:     Load SDL function.
;-------------------------------------------------------------------------------
macro       LDSDLF      name* {
            mov         rdi,[g_libsdl]
            mov         rsi,g_str_#name
            call        [dlsym]
            mov         [name],rax
}
;-------------------------------------------------------------------------------
; DESC:     Load OpenGL function.
;-------------------------------------------------------------------------------
macro       LDGLF       name* {
            mov         rdi,g_str_#name
            call        [SDL_GL_GetProcAddress]
            mov         [name],rax
}
;-------------------------------------------------------------------------------
; DESC:     Set OpenGL attribute.
;-------------------------------------------------------------------------------
macro       STGLATTR    param*, value* {
            mov         edi,param
            mov         esi,value
            call        [SDL_GL_SetAttribute]
}
;-------------------------------------------------------------------------------
; DESC:     Define function pointer and name.
;-------------------------------------------------------------------------------
macro       DEFFUNC     name* {
align 1
g_str_#name db          `name,0
align 8
name        dq          0
}
;-------------------------------------------------------------------------------
; DESC:     ELF Header.
;-------------------------------------------------------------------------------
            org         0x400000
            db          0x7f,'ELF',2,1,1,0,0,0,0,0,0,0,0,0
            dw          2                                       ; File type - executable
            dw          62                                      ; Machine - AMD64/EM64T
            dd          1                                       ; File format version
            dq          Start                                   ; Process entry address
            dq          64                                      ; Program header table file offset
            dq          0                                       ; Section header table file offset
            dd          0                                       ; Processor-specific flags
            dw          64                                      ; Size of this header
            dw          56                                      ; Size of program header
            dw          3                                       ; Number of program headers
            dw          64                                      ; Size of section header
            dw          0                                       ; Number of section headers
            dw          0                                       ; Section header string table index
            dd          3                                       ; PT_INTERP
            dd          4                                       ; Flags - R
            dq          ELF_interp-0x400000                     ; Offset
            dq          ELF_interp,ELF_interp                   ; VirtAddr,PhysAddr
            dq          ELF_interp.SIZE,ELF_interp.SIZE         ; FileSiz,MemSiz
            dq          1                                       ; Align
            dd          2                                       ; PT_DYNAMIC
            dd          4                                       ; Flags - R
            dq          ELF_dynamic-0x400000                    ; Offset
            dq          ELF_dynamic,ELF_dynamic                 ; VirtAddr,PhysAddr
            dq          ELF_dynamic.SIZE,ELF_dynamic.SIZE       ; FileSiz,MemSiz
            dq          8                                       ; Align
            dd          1                                       ; PT_LOAD
            dd          7                                       ; Flags - RWE
            dq          0                                       ; Offset
            dq          0x400000,0x400000                       ; VirtAddr,PhysAddr
            dq          ELF_SIZE,ELF_SIZE                       ; FileSiz,MemSiz
            dq          0x100000                                ; Align
;-------------------------------------------------------------------------------
; NAME:     LoadFunctions
;-------------------------------------------------------------------------------
LoadFunctions:
            sub         rsp,8
            ; load SDL 1.2 library
            mov         rdi,g_str_libsdl
            mov         esi,1                                   ; RTLD_LAZY = 1
            call        [dlopen]
            mov         [g_libsdl],rax
            ; load SDL functions
            LDSDLF      SDL_Init
            LDSDLF      SDL_Quit
            LDSDLF      SDL_SetVideoMode
            LDSDLF      SDL_PollEvent
            LDSDLF      SDL_GetKeyState
            LDSDLF      SDL_GetTicks
            LDSDLF      SDL_GL_SwapBuffers
            LDSDLF      SDL_GL_GetProcAddress
            LDSDLF      SDL_GL_SetAttribute
            LDSDLF      SDL_GL_LoadLibrary
            ; load libc functions
            LDLIBCF     printf
            add         rsp,8
            ret
;-------------------------------------------------------------------------------
; NAME:     OpenWindow
;-------------------------------------------------------------------------------
OpenWindow:
            sub         rsp,8
            ; call SDL_Init
            mov         edi,SDL_INIT_VIDEO
            call        [SDL_Init]
            ; set OpenGL attributes
            STGLATTR    SDL_GL_DOUBLEBUFFER,1
            STGLATTR    SDL_GL_RED_SIZE,8
            STGLATTR    SDL_GL_GREEN_SIZE,8
            STGLATTR    SDL_GL_BLUE_SIZE,8
            STGLATTR    SDL_GL_DEPTH_SIZE,24
            STGLATTR    SDL_GL_STENCIL_SIZE,8
            ; call SDL_GL_LoadLibrary
            xor         edi,edi
            call        [SDL_GL_LoadLibrary]
            ; call SDL_SetVideoModeprogram
            mov         edi,800
            mov         esi,800
            xor         edx,edx
            mov         ecx,SDL_OPENGL+SDL_NOFRAME
            call        [SDL_SetVideoMode]
            add         rsp,8
            ret
;-------------------------------------------------------------------------------
; NAME:     LoadOGLFunctions
;-------------------------------------------------------------------------------
LoadOGLFunctions:
            sub         rsp,8
            LDGLF       glGetError
            LDGLF       glClear
            LDGLF       glEnable
            LDGLF       glDisable
            LDGLF       glEnableClientState
            LDGLF       glBindProgramARB
            LDGLF       glNamedProgramStringEXT
            LDGLF       glNamedProgramLocalParameter4fvEXT
            LDGLF       glNamedProgramLocalParameters4fvEXT
            LDGLF       glNamedBufferDataEXT
            LDGLF       glGetNamedBufferParameterui64vNV
            LDGLF       glMakeNamedBufferResidentNV
            LDGLF       glVertexAttribFormatNV
            LDGLF       glBufferAddressRangeNV
            LDGLF       glEnableVertexAttribArray
            LDGLF       glDrawArrays
            LDGLF       glPathCommandsNV
            LDGLF       glPathGlyphRangeNV
            LDGLF       glGenPathsNV
            LDGLF       glGetPathSpacingNV
            LDGLF       glGetPathMetricRangeNV
            LDGLF       glStencilFillPathNV
            LDGLF       glCoverFillPathNV
            LDGLF       glStencilFillPathInstancedNV
            LDGLF       glCoverFillPathInstancedNV
            LDGLF       glStencilFunc
            LDGLF       glStencilOp
            add         rsp,8
            ret
;-------------------------------------------------------------------------------
; NAME:     Init
;-------------------------------------------------------------------------------
Init:
            sub         rsp,8
            ; create vertex buffer object
            mov         edi,g_vbo.NAME
            mov         esi,g_vbo.DATA_SIZE
            mov         rdx,g_vbo.data
            mov         ecx,GL_STATIC_DRAW
            call        [glNamedBufferDataEXT]
            mov         edi,g_vbo.NAME
            mov         esi,GL_BUFFER_GPU_ADDRESS_NV
            mov         rdx,g_vbo.addr
            call        [glGetNamedBufferParameterui64vNV]
            mov         edi,g_vbo.NAME
            mov         esi,GL_READ_ONLY
            call        [glMakeNamedBufferResidentNV]
            ; create vertex program object
            mov         edi,g_vp.NAME
            mov         esi,GL_VERTEX_PROGRAM_ARB
            mov         edx,GL_PROGRAM_FORMAT_ASCII_ARB
            mov         ecx,g_vp.SRC_SIZE
            mov         r8,g_vp.src
            call        [glNamedProgramStringEXT]
            ; create Green fragment program object
            mov         edi,g_fp_green.NAME
            mov         esi,GL_FRAGMENT_PROGRAM_ARB
            mov         edx,GL_PROGRAM_FORMAT_ASCII_ARB
            mov         ecx,g_fp_green.SRC_SIZE
            mov         r8,g_fp_green.src
            call        [glNamedProgramStringEXT]
            ; create Mandelbrot fragment program object
            mov         edi,g_fp_mandelbrot.NAME
            mov         esi,GL_FRAGMENT_PROGRAM_ARB
            mov         edx,GL_PROGRAM_FORMAT_ASCII_ARB
            mov         ecx,g_fp_mandelbrot.SRC_SIZE
            mov         r8,g_fp_mandelbrot.src
            call        [glNamedProgramStringEXT]
            ; create font
            mov         edi,256
            call        [glGenPathsNV]
            mov         [g_font.glyph_base],eax
            mov         edi,[g_font.glyph_base]
            mov         esi,GL_STANDARD_FONT_NAME_NV
            mov         rdx,g_str_Sans
            xor         ecx,ecx
            xor         r8d,r8d
            mov         r9d,256
            sub         rsp,8
            mov         eax,2048.0
            push        rax
            push        -1
            push        GL_USE_MISSING_GLYPH_NV
            call        [glPathGlyphRangeNV]
            add         rsp,32
            ; setup OpenGL state
            mov         edi,GL_VERTEX_PROGRAM_ARB
            call        [glEnable]
            mov         edi,GL_FRAGMENT_PROGRAM_ARB
            call        [glEnable]
            ; check for GL errors
            call        [glGetError]
            mov         rdi,g_str_d
            mov         esi,eax
            call        [printf]
            ; init timer
            call        [SDL_GetTicks]
            cvtsi2ss    xmm0,eax
            shufps      xmm0,xmm0,0x00
            mulps       xmm0,dqword [g_0_001]
            movaps      dqword [g_time],xmm0
            movaps      dqword [g_time_prev],xmm0
            add         rsp,8
            ret
;-------------------------------------------------------------------------------
; NAME:     Update
;-------------------------------------------------------------------------------
Update:
            sub         rsp,8
            ;
            ; Handle user input
            ;
            xor         edi,edi
            call        [SDL_GetKeyState]
            cmp         byte [rax+SDLK_LEFT],1
            jne         @f
            movss       xmm0,[g_center]
            movss       xmm1,[g_time_delta]
            divss       xmm1,[g_zoom]
            subss       xmm0,xmm1
            movss       [g_center],xmm0
@@:
            cmp         byte [rax+SDLK_RIGHT],1
            jne         @f
            movss       xmm0,[g_center]
            movss       xmm1,[g_time_delta]
            divss       xmm1,[g_zoom]
            addss       xmm0,xmm1
            movss       [g_center],xmm0
@@:
            cmp         byte [rax+SDLK_DOWN],1
            jne         @f
            movss       xmm0,[g_center+4]
            movss       xmm1,[g_time_delta]
            divss       xmm1,[g_zoom]
            subss       xmm0,xmm1
            movss       [g_center+4],xmm0
@@:
            cmp         byte [rax+SDLK_UP],1
            jne         @f
            movss       xmm0,[g_center+4]
            movss       xmm1,[g_time_delta]
            divss       xmm1,[g_zoom]
            addss       xmm0,xmm1
            movss       [g_center+4],xmm0
@@:
            cmp         byte [rax+SDLK_a],1
            jne         @f
            movaps      xmm0,dqword [g_zoom]
            movaps      xmm1,dqword [g_time_delta]
            mulps       xmm1,dqword [g_zoom]
            addps       xmm0,xmm1
            movaps      dqword [g_zoom],xmm0
@@:
            cmp         byte [rax+SDLK_z],1
            jne         @f
            movaps      xmm0,dqword [g_zoom]
            movaps      xmm1,dqword [g_time_delta]
            mulps       xmm1,dqword [g_zoom]
            subps       xmm0,xmm1
            movaps      dqword [g_zoom],xmm0
@@:
            ;
            ; Clear buffers
            ;
            mov         edi,GL_COLOR_BUFFER_BIT+GL_STENCIL_BUFFER_BIT
            call        [glClear]
            ;
            ; Setup vertex array and vertex program
            ;
            ; enable
            mov         edi,GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV
            call        [glEnableClientState]
            mov         edi,0
            call        [glEnableVertexAttribArray]
            ; set format
            mov         edi,0
            mov         esi,2
            mov         edx,GL_FLOAT
            mov         ecx,GL_FALSE
            mov         r8d,0
            call        [glVertexAttribFormatNV]
            ; set VBO address
            mov         edi,GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV
            mov         esi,0
            mov         rdx,[g_vbo.addr]
            mov         ecx,g_vbo.DATA_SIZE
            call        [glBufferAddressRangeNV]
            ; bind vertex program
            mov         edi,GL_VERTEX_PROGRAM_ARB
            mov         esi,g_vp.NAME
            call        [glBindProgramARB]
            ;
            ; Draw Mandelbrot
            ;
            ; update program parameters
            mov         edi,g_fp_mandelbrot.NAME
            mov         esi,GL_FRAGMENT_PROGRAM_ARB
            mov         edx,0
            mov         rcx,g_center
            call        [glNamedProgramLocalParameter4fvEXT]
            mov         edi,g_fp_mandelbrot.NAME
            mov         esi,GL_FRAGMENT_PROGRAM_ARB
            mov         edx,1
            mov         rcx,g_zoom
            call        [glNamedProgramLocalParameter4fvEXT]
            ; bind Mandelbrot fragment program
            mov         edi,GL_FRAGMENT_PROGRAM_ARB
            mov         esi,g_fp_mandelbrot.NAME
            call        [glBindProgramARB]
            ; draw
            mov         edi,GL_TRIANGLE_STRIP
            mov         esi,0
            mov         edx,4
            call        [glDrawArrays]
            ;
            ; Draw path
            ;
            ; bind Green fragment program
            mov         edi,GL_FRAGMENT_PROGRAM_ARB
            mov         esi,g_fp_green.NAME
            call        [glBindProgramARB]
            mov         edi,GL_STENCIL_TEST
            call        [glEnable]
            mov         edi,GL_NOTEQUAL
            mov         esi,0
            mov         edx,0x1f
            call        [glStencilFunc]
            mov         edi,GL_KEEP
            mov         esi,GL_KEEP
            mov         edx,GL_ZERO
            call        [glStencilOp]
            mov         edi,GL_STENCIL_TEST
            call        [glDisable]
            add         rsp,8
            ret
;-------------------------------------------------------------------------------
; NAME:     RunMainLoop
;-------------------------------------------------------------------------------
RunMainLoop:
            event       equ rbp-32
            push        rbp
            mov         rbp,rsp
            sub         rsp,64
.MainLoop:
            ; get current time in seconds
            call        [SDL_GetTicks]
            cvtsi2ss    xmm0,eax
            shufps      xmm0,xmm0,0x00
            mulps       xmm0,dqword [g_0_001]
            movaps      dqword [g_time],xmm0
            subps       xmm0,dqword [g_time_prev]
            movaps      dqword [g_time_delta],xmm0
            movaps      xmm0,dqword [g_time]
            movaps      dqword [g_time_prev],xmm0
            ; process window events
.EventLoop:
            lea         rdi,[event]
            call        [SDL_PollEvent]
            test        eax,eax
            jz          .EventLoopEnd
            cmp         byte [event+0],SDL_KEYDOWN
            je          .Keydown
            cmp         byte [event+0],SDL_KEYUP
            je          .Keyup
            jmp         .EventLoop
.Keydown:
            cmp         dword [event+8],SDLK_ESCAPE
            je          .MainLoopEnd
            jmp         .EventLoop
.Keyup:
            ; process event
            jmp         .EventLoop
.EventLoopEnd:
            ; draw and update
            call        Update
            ; swap
            call        [SDL_GL_SwapBuffers]
            jmp         .MainLoop
.MainLoopEnd:
            mov         rsp,rbp
            pop         rbp
            ret
            restore     event
;-------------------------------------------------------------------------------
; NAME: Start
; DESC: Program entry point.
;-------------------------------------------------------------------------------
Start:
            call        LoadFunctions
            call        OpenWindow
            call        LoadOGLFunctions
            call        Init
            call        RunMainLoop
            call        [SDL_Quit]
            ; terminate process
            mov         eax,60
            xor         edi,edi
            syscall

align 4
g_font:
.glyph_base dd          0

align 16
g_center    dd          -0.75,0.0,0.0,0.0
g_zoom      dd          4 dup 0.8
g_time      dd          4 dup 0.0
g_time_prev dd          4 dup 0.0
g_time_delta dd         4 dup 0.0
g_0_001     dd          4 dup 0.001

align 1
g_str_d     db          '%d',10,0
g_str_Sans  db          'Sans',0

align 8
g_vbo:
.NAME=1
.addr       dq          0
.data       dd          -1.0,1.0,-1.0,-1.0,1.0,1.0,1.0,-1.0
.DATA_SIZE=$-.data

align 1
g_vp:
.NAME=1
.src:
            db          '!!NVvp4.0',10
            db          'main:'
            db              'MOV result.position,vertex.attrib[0];'
            db              'MOV result.attrib[0],vertex.attrib[0];'
            db          'RET;'
            db          'END',0
.SRC_SIZE=$-.src-1

align 1
g_fp_green:
.NAME=2
.src:
            db          '!!NVfp4.0',10
            db          'main:'
            db              'MOV result.color,{0,1,0,1};'
            db          'RET;'
            db          'END',0
.SRC_SIZE=$-.src-1

align 1
g_fp_mandelbrot:
.NAME=3
.src:
            db          '!!NVfp4.0',10
            db          'TEMP R0,R1,R2,R3;'
            db          'PARAM Center=program.local[0];'
            db          'PARAM Zoom=program.local[1];'
            db          'CMul:'
            db              'MUL R1.x,R0.x,R0.z;'
            db              'MUL R1.y,R0.y,R0.w;'
            db              'MUL R1.z,R0.x,R0.w;'
            db              'MUL R1.w,R0.y,R0.z;'
            db              'SUB R0.x,R1.x,R1.y;'
            db              'ADD R0.y,R1.z,R1.w;'
            db              'RET;'
            db          'CSq:'
            db              'MUL R1.x,R0.x,R0.x;'
            db              'MUL R1.y,R0.y,R0.y;'
            db              'SUB R1.x,R1.x,R1.y;'
            db              'MUL R0.y,R0.x,R0.y;'
            db              'ADD R0.y,R0.y,R0.y;'
            db              'MOV R0.x,R1.x;'
            db              'RET;'
            db          'Dist:'
            db              'MOV R2,{0,0,1,0};'
            db              'MOV R3,fragment.attrib[0];'
            ;db             'MUL R3.x,R3.x,1.777;'
            db              'DIV R3.xy,R3.xyxy,Zoom.x;'
            db              'ADD R3.xy,R3.xyxy,Center.xyxy;'
            db              'REP 512;'
            db                  'MOV R0,R2;'
            db                  'CAL CMul;'
            db                  'ADD R0.xy,R0.xyxy,R0.xyxy;'
            db                  'ADD R0.xy,R0.xyxy,{1,0};'
            db                  'MOV R2.zw,R0.xyxy;'
            db                  'MOV R0.xy,R2;'
            db                  'CAL CSq;'
            db                  'ADD R0.xy,R0.xyxy,R3.xyxy;'
            db                  'MOV R2.xy,R0;'
            db                  'DP2 R0.x,R2,R2;'
            db                  'SGT.CC0 R0.y,R0.x,100;'
            db                  'IF NE0.y;'
            db                      'DP2 R0.y,R2.zwzw,R2.zwzw;'
            db                      'DIV R0.z,R0.x,R0.y;'
            db                      'RSQ R0.z,R0.z;'
            db                      'RCP R0.z,R0.z;'
            db                      'MUL R0.z,R0.z,0.5;'
            db                      'LG2 R0.x,R0.x;'
            db                      'MUL R0.x,R0.x,0.69314718246460;'
            db                      'MUL R0.x,R0.x,R0.z;'
            db                      'MUL R0.x,R0.x,Zoom;'
            db                      'RET;'
            db                  'ENDIF;'
            db              'ENDREP;'
            db              'MOV R0,0;'
            db              'RET;'
            db          'main:'
            db              'CAL Dist;'
            db              'RSQ R0.x,R0.x;'
            db              'RSQ R0.x,R0.x;'
            db              'MOV result.color,R0.x;'
            db              'RET;'
            db          'END',0
.SRC_SIZE=$-.src-1

align 1
g_str_libsdl db         'libSDL-1.2.so.0',0

align 8
g_libsdl    dq          0
            ; libc functions
dlopen      dq          0
dlsym       dq          0
            DEFFUNC     printf
            ; SDL functions
            DEFFUNC     SDL_Init
            DEFFUNC     SDL_Quit
            DEFFUNC     SDL_SetVideoMode
            DEFFUNC     SDL_PollEvent
            DEFFUNC     SDL_GetKeyState
            DEFFUNC     SDL_GetTicks
            DEFFUNC     SDL_GL_LoadLibrary
            DEFFUNC     SDL_GL_GetProcAddress
            DEFFUNC     SDL_GL_SetAttribute
            DEFFUNC     SDL_GL_SwapBuffers
            ; misc commands
            DEFFUNC     glGetError
            DEFFUNC     glClear
            DEFFUNC     glEnable
            DEFFUNC     glDisable
            DEFFUNC     glEnableClientState
            ; matrix commands
            DEFFUNC     glMatrixLoadIdentityEXT
            ; program commands
            DEFFUNC     glBindProgramARB
            DEFFUNC     glNamedProgramStringEXT
            DEFFUNC     glNamedProgramLocalParameter4fvEXT
            DEFFUNC     glNamedProgramLocalParameters4fvEXT
            ; buffer commands
            DEFFUNC     glNamedBufferDataEXT
            DEFFUNC     glGetNamedBufferParameterui64vNV
            DEFFUNC     glMakeNamedBufferResidentNV
            ; vertex array commands
            DEFFUNC     glVertexAttribFormatNV
            DEFFUNC     glBufferAddressRangeNV
            DEFFUNC     glEnableVertexAttribArray
            ; draw calls
            DEFFUNC     glDrawArrays
            ; path commands
            DEFFUNC     glPathCommandsNV
            DEFFUNC     glPathGlyphRangeNV
            DEFFUNC     glGenPathsNV
            DEFFUNC     glGetPathSpacingNV
            DEFFUNC     glGetPathMetricRangeNV
            DEFFUNC     glStencilFillPathNV
            DEFFUNC     glStencilFillPathInstancedNV
            DEFFUNC     glCoverFillPathNV
            DEFFUNC     glCoverFillPathInstancedNV
            ; stencil commands
            DEFFUNC     glStencilFunc
            DEFFUNC     glStencilOp
align 8
ELF_dynamic:
            dq          1,ELF_strtab.libdl-ELF_strtab           ; DT_NEEDED
            dq          5,ELF_strtab                            ; DT_STRTAB
            dq          6,ELF_symtab                            ; DT_SYMTAB
            dq          10,ELF_strtab.SIZE                      ; DT_STRSZ
            dq          11,24                                   ; DT_SYMENT
            dq          7,ELF_rela                              ; DT_RELA
            dq          8,ELF_rela.SIZE                         ; DT_RELASZ
            dq          9,24                                    ; DT_RELAENT
            dq          0,0                                     ; terminator
.SIZE=$-ELF_dynamic

ELF_strtab:
            db          0
.libdl      db          'libdl.so.2',0
.dlopen     db          'dlopen',0
.dlsym      db          'dlsym',0
.SIZE=$-ELF_strtab

align 4
ELF_symtab:
            dd          ELF_strtab.dlopen-ELF_strtab
            db          (1 shl 4)+2,0
            dw          0
            dq          0,0
            dd          ELF_strtab.dlsym-ELF_strtab
            db          (1 shl 4)+2,0
            dw          0
            dq          0,0
.SIZE=$-ELF_symtab

align 8
ELF_rela:
            dq          dlopen,(0 shl 32)+1,0
            dq          dlsym,(1 shl 32)+1,0
.SIZE=$-ELF_rela

ELF_interp  db          '/lib/ld-linux-x86-64.so.2',0
.SIZE=$-ELF_interp

ELF_SIZE=$-$$
