ifndef                  _PBUFFER_ASM
_PBUFFER_ASM            equ     1

; ------------------------------------------------------
; Structures
PBUFFER                 struct
hRC                     dword   ?
hDC                     HDC     ?
hBuffer                 dword   ?
_Width                  dword   ?
Height                  dword   ?
ColorBits               dword   ?
DepthBits               dword   ?
StencilBits             dword   ?
PBUFFER                 ends

; ------------------------------------------------------
; Variables
wglCreatePbufferARB     PFNWGLCREATEPBUFFERARBPROC 0
wglGetPbufferDCARB      PFNWGLGETPBUFFERDCARBPROC 0
wglReleasePbufferDCARB  PFNWGLRELEASEPBUFFERDCARBPROC 0
wglDestroyPbufferARB    PFNWGLDESTROYPBUFFERARBPROC 0
wglQueryPbufferARB      PFNWGLQUERYPBUFFERARBPROC 0
wglBindTexImageARB      PFNWGLBINDTEXIMAGEARBPROC 0
wglReleaseTexImageARB   PFNWGLRELEASETEXIMAGEARBPROC 0

_PBuffer_Flags          dd      WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB
                        dd      WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB
                        dd      WGL_MIPMAP_TEXTURE_ARB, TRUE
                        dd      0

_Std_AttribList         dd      WGL_DRAW_TO_PBUFFER_ARB, TRUE
                        dd      WGL_COLOR_BITS_ARB
_Color_Attrib           dd      0
                        dd      WGL_ALPHA_BITS_ARB
_Alpha_Attrib           dd      0
                        dd      WGL_DEPTH_BITS_ARB
_Depth_Attrib           dd      0
                        dd      WGL_STENCIL_BITS_ARB
_Stencil_Attrib         dd      0
                        dd      WGL_BIND_TO_TEXTURE_RGBA_ARB, TRUE
                        dd      0

_Flt_AttribList         real4   0.0

; ------------------------------------------------------
; Name: Init_PBuffer_Context()
; Desc: Obtain necessary functions if possible
Init_PBuffer_Context    proc
                        invoke  wglGetProcAddress, CSTR("wglChoosePixelFormatARB")
                        mov     wglChoosePixelFormatARB,eax
                        invoke  wglGetProcAddress, CSTR("wglCreatePbufferARB")
                        mov     wglCreatePbufferARB,eax
                        invoke  wglGetProcAddress, CSTR("wglGetPbufferDCARB")
                        mov     wglGetPbufferDCARB,eax
                        invoke  wglGetProcAddress, CSTR("wglReleasePbufferDCARB")
                        mov     wglReleasePbufferDCARB,eax
                        invoke  wglGetProcAddress, CSTR("wglDestroyPbufferARB")
                        mov     wglDestroyPbufferARB,eax
                        invoke  wglGetProcAddress, CSTR("wglQueryPbufferARB")
                        mov     wglQueryPbufferARB,eax
                        invoke  wglGetProcAddress, CSTR("wglBindTexImageARB")
                        mov     wglBindTexImageARB,eax 
                        invoke  wglGetProcAddress, CSTR("wglReleaseTexImageARB")
                        mov     wglReleaseTexImageARB,eax
                        .if     wglChoosePixelFormatARB != NULL && wglCreatePbufferARB != NULL && wglGetPbufferDCARB != NULL && \
                                wglReleasePbufferDCARB != NULL && wglDestroyPbufferARB != NULL && wglQueryPbufferARB != NULL && \
                                wglBindTexImageARB != NULL && wglReleaseTexImageARB != NULL
                                ; PBuffers are supported.
                                mov     eax,TRUE
                                ret
                        .endif
                        xor     eax,eax
                        ret
Init_PBuffer_Context    endp

; ------------------------------------------------------
; Name: Init_PBuffer()
; Desc: Create a PBuffer
Init_PBuffer            proc    uses edi Buf_Struct:dword, _Size:dword, ColorBits:dword, DepthBits:dword, StencilBits:dword
                        local   hCurrentDC:HDC
                        local   Pixel_Format:GLint
                        local   numFormats:dword

                        mov     edi,Buf_Struct

                        mov     [edi + PBUFFER._Width], CMEM(_Size)
                        mov     [edi + PBUFFER.Height], CMEM(_Size)
                        mov     [edi + PBUFFER.ColorBits], CMEM(ColorBits)
                        mov     [edi + PBUFFER.DepthBits], CMEM(DepthBits)
                        mov     [edi + PBUFFER.StencilBits], CMEM(StencilBits)

                        mov     _Color_Attrib, CMEM(ColorBits)
                        .if     ColorBits == 32
                                mov     _Alpha_Attrib,8
                        .else
                                mov     _Alpha_Attrib,0
                        .endif
                        mov     _Depth_Attrib, CMEM(DepthBits)
                        mov     _Stencil_Attrib, CMEM(StencilBits)

                        ; Get the current device context
                        invoke  wglGetCurrentDC
                        mov     hCurrentDC,eax 

                        invoke  wglChoosePixelFormatARB, hCurrentDC, addr _Std_AttribList, addr _Flt_AttribList, 1, addr Pixel_Format, addr numFormats
                        .if     eax == 0 
                                ret
                        .endif
                        invoke  wglCreatePbufferARB, hCurrentDC, Pixel_Format, [edi + PBUFFER._Width], [edi + PBUFFER.Height], addr _PBuffer_Flags
                        mov     [edi + PBUFFER.hBuffer],eax
                        .if     eax == 0 
                                ret
                        .endif

                        invoke  wglGetPbufferDCARB, eax
                        mov     [edi + PBUFFER.hDC],eax
                        .if     eax == 0 
                                ret
                        .endif

                        invoke  wglCreateContext, eax
                        mov     [edi + PBUFFER.hRC],eax
                        .if     eax == 0 
                                ret
                        .endif
                        
                        lea     eax,[edi + PBUFFER._Width]
                        invoke  wglQueryPbufferARB, [edi + PBUFFER.hBuffer], WGL_PBUFFER_WIDTH_ARB, eax

                        lea     eax,[edi + PBUFFER.Height]
                        invoke  wglQueryPbufferARB, [edi + PBUFFER.hBuffer], WGL_PBUFFER_HEIGHT_ARB, eax

                        mov     eax,TRUE
                        ret
Init_PBuffer            endp

; ------------------------------------------------------
; Name: Destroy_PBuffer()
; Desc: Delete the given rendering buffer
Destroy_PBuffer         proc    uses esi Buf_Struct:dword
                        
                        mov     esi,Buf_Struct

                        mov     eax,[esi + PBUFFER.hRC]
                        .if     eax != NULL
                                invoke  wglDeleteContext, eax
                        .endif
                        mov     eax,[esi + PBUFFER.hDC]
                        .if     eax != NULL
                                invoke  wglReleasePbufferDCARB, [esi + PBUFFER.hBuffer], eax
                        .endif
                        mov     eax,[esi + PBUFFER.hBuffer]
                        .if     eax != NULL
                                invoke  wglDestroyPbufferARB, eax
                        .endif
                        ret
Destroy_PBuffer         endp

; ------------------------------------------------------
; Name: Select_Render()
; Desc: Select the given rendering buffer as rendering target
Select_Render           proc    hDC:HDC, hRC:dword
                        invoke  wglMakeCurrent, hDC, hRC
                        ret
Select_Render           endp

; ------------------------------------------------------
; Name: Bind_PBuffer()
; Desc: Select a pbuffer for rendering purposes
Bind_PBuffer            proc    Buf_Struct:dword
                        mov     eax,Buf_Struct
                        invoke  wglBindTexImageARB, [eax + PBUFFER.hBuffer], WGL_FRONT_LEFT_ARB
                        ret
Bind_PBuffer            endp

; ------------------------------------------------------
; Name: Unbind_PBuffer()
; Desc: Unbind a previously locked pbuffer
Unbind_PBuffer          proc    Buf_Struct:dword
                        mov     eax,Buf_Struct
                        invoke  wglReleaseTexImageARB, [eax + PBUFFER.hBuffer], WGL_FRONT_LEFT_ARB
                        ret
Unbind_PBuffer          endp

endif
