Announcement

Collapse
No announcement yet.

%pfd_doublebuffer

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • %pfd_doublebuffer

    When using %pfd_support_gdi, to allow Graphic statements to draw to a Graphic control that is used as the OpenGL rendering context, I noticed that I cannot use %pfd_doublebuffer. If I do, the Graphic statements are not drawn.

    However (trying to head off an expected response), let's not jump to the conclusion of "Well, then, don't use a Graphic control!".

    I'd like to understand all the limitations first. A couple of constraints (DC source and %pfd_doublebuffer) aren't enough to make a no-use decision.

  • #2
    These flags are mutually exclusive in the current implementation of OpenGL.
    Forum: http://www.jose.it-berater.org/smfforum/index.php

    Comment


    • #3
      Hi Jose,
      I've gone to MSDN, here, and read of the constraint. Thanks for pointing me there.

      Comment


      • #4
        But Jose,
        Thinking on it a bit more ...

        When replacing %pfd_doublebuffer with %pfd_support_gdi, so I can use Graphic drawing statements on a graphic control, I can see flickering in the Graphic control during animation (code example below).

        That means if I want both OpenGL and Graphic statements, I'll have to implement my own buffering. One more constraint to be aware of.

        Example of flickering (imperfectly formed cube in image):



        Code:
        'Compilable Example:
        #Compile Exe
        #Dim All
        #Include "win32api.inc"
        #Include "gl.inc"
        #Include "glu.inc"
        
        %ID_Timer = 1000
        
        Global hDlg, hDC, hRC As Dword
        Global anglex, angley, anglez, scalefactor As Single
        
        Function PBMain() As Long
          Dialog New Pixels, 0, "OpenGL Example",,, 320, 240,%WS_OverlappedWindow To hDlg
          Dialog Show Modal hdlg Call dlgproc
        End Function
        
        CallBack Function dlgproc()
           Local pt As Point
           Local XDelta, YDelta As Single
           Static SpinInWork,XLast,YLast As Long
        
           Select Case Cb.Msg
              Case %WM_InitDialog : GetRenderContext
                                    InitializeScene
                                    SetTimer(hDlg, %ID_Timer, 50, %NULL)
                                    ScaleFactor = 1
              Case %WM_Timer      : DrawScene 1,1,1  'redraw with rotation on all 3 axes
              Case %WM_Paint      : DrawScene 0,0,0  'redraw with no rotation
              Case %WM_Size       : ResizeScene Lo(Word, Cb.LParam), Hi(Word, Cb.LParam)
                                    DrawScene 0,0,0  'redraw with no rotation
              Case %WM_Close      : wglmakecurrent %null, %null 'unselect rendering context
                                    wgldeletecontext hRC        'delete the rendering context
                                    releasedc hDlg, hDC         'release device context
              Case %WM_MouseWheel
                 Select Case Hi(Integer,Cb.WParam)
                    Case > 0  : ScaleFactor = ScaleFactor + 0.1 : DrawScene 0,0,0
                    Case < 0  : ScaleFactor = ScaleFactor - 0.1 : DrawScene 0,0,0
                 End Select
              Case %WM_SetCursor
                 Select Case Hi(Word, Cb.LParam)
                    Case %WM_LButtonDown
                       KillTimer Cb.Hndl, %ID_Timer
                       SpinInWork = 1
                       GetCursorPos pt              'pt has xy screen coordinates
                       ScreenToClient hDC, pt       'pt now has dialog client coordinates
                       XLast = Pt.x
                       YLast = Pt.y
                    Case %WM_MouseMove
                       If SpinInWork Then
                          GetCursorPos pt           'pt has xy screen coordinates
                          ScreenToClient hDC, pt    'pt now has dialog client coordinates
                          XDelta = XLast - Pt.x
                          YDelta = YLast - Pt.y
                          DrawScene -YDelta, -XDelta, 0
                          XLast = pt.x
                          YLast = pt.y
                       End If
                    Case %WM_LButtonUp
                       SetTimer(hDlg, %ID_Timer, 50, %NULL)
                       SpinInWork = 0
                 End Select
           End Select
        End Function
        
        Sub GetRenderContext
           Local pfd As PIXELFORMATDESCRIPTOR   'pixel format properties for device context
           pfd.nSize       =  SizeOf(PIXELFORMATDESCRIPTOR)
           pfd.nVersion    =  1
           pfd.dwFlags     = %pfd_draw_to_window Or %pfd_support_opengl Or %pfd_support_gdi
           pfd.dwlayermask = %pfd_main_plane
           pfd.iPixelType  = %pfd_type_rgba
           pfd.ccolorbits  = 24
           pfd.cdepthbits  = 24
        
           hDC = GetDC(hDlg)                                      'DC for dialog
           SetPixelFormat(hDC, ChoosePixelFormat(hDC, pfd), pfd)  'set properties of device context
           hRC = wglCreateContext (hDC)                           'get rendering context
           wglMakeCurrent hDC, hRC                                'make the RC current
        End Sub
        
        Sub InitializeScene
           glClearColor 0,0,0,0     'sets color to be used with glClear
           glClearDepth 1           'sets zvalue to be used with glClear
           glEnable %gl_depth_test                             'enable depth testing
           glHint %gl_perspective_correction_hint, %gl_nicest  'best quality rendering
           BuildDisplayList 1
        End Sub
        
        Sub ResizeScene (w As Long, h As Long)
           glViewport 0, 0, w, h               'resize viewport to match window size
           glMatrixMode %gl_projection         'select the projection matrix
           glLoadIdentity                    'reset the projection matrix
           gluPerspective 45, w/h, 0.1, 100  'set frustum using viewport aspect ratio
           glMatrixMode %gl_modelview          'select the modelview matrix
        End Sub
        
        Sub DrawScene (dx As Single, dy As Single, dz As Single)
           glClear %gl_color_buffer_bit Or %gl_depth_buffer_bit  'clear buffers
           glLoadIdentity               'clear the modelview matrix
        
           gluLookAt 0,0,6,0,0,0,0,1,0
        
           glScalef scalefactor, scalefactor, scalefactor
        
           anglex = anglex + dx : glRotatef anglex, 1,0,0
           angley = angley + dy : glRotatef angley, 0,1,0
           anglez = anglez + dz : glRotatef anglez, 0,0,1
        
           glCallList 1
        
           SwapBuffers hDC              'display the buffer (image)
        End Sub
        
        Sub BuildDisplayList(ListNumber As Long)
           glNewList ListNumber, %gl_compile
              glBegin %GL_QUADS
                 glColor3f   0.0,  1.0,  0.0         ' Set the color to green
                 glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Top)
                 glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Top)
                 glVertex3f -1.0,  1.0,  1.0         ' Bottom left of the quad (Top)
                 glVertex3f  1.0,  1.0,  1.0         ' Bottom right of the quad (Top)
        
                 glColor3f   1.0,  0.5,  0.0         ' Set the color to orange
                 glVertex3f  1.0, -1.0,  1.0         ' Top right of the quad (Bottom)
                 glVertex3f -1.0, -1.0,  1.0         ' Top left of the quad (Bottom)
                 glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Bottom)
                 glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Bottom)
        
                 glColor3f   1.0,  0.0,  0.0         ' Set the color to red
                 glVertex3f  1.0,  1.0,  1.0         ' Top right of the quad (Front)
                 glVertex3f -1.0,  1.0,  1.0         ' Top left of the quad (Front)
                 glVertex3f -1.0, -1.0,  1.0         ' Bottom left of the quad (Front)
                 glVertex3f  1.0, -1.0,  1.0         ' Bottom right of the quad (Front)
        
                 glColor3f   1.0,  1.0,  0.0         ' Set the color to yellow
                 glVertex3f  1.0, -1.0, -1.0         ' Top right of the quad (Back)
                 glVertex3f -1.0, -1.0, -1.0         ' Top left of the quad (Back)
                 glVertex3f -1.0,  1.0, -1.0         ' Bottom left of the quad (Back)
                 glVertex3f  1.0,  1.0, -1.0         ' Bottom right of the quad (Back)
        
                 glColor3f   0.0,  0.0,  1.0         ' Set the color to blue
                 glVertex3f -1.0,  1.0,  1.0         ' Top right of the quad (Left)
                 glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Left)
                 glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Left)
                 glVertex3f -1.0, -1.0,  1.0         ' Bottom right of the quad (Left)
        
                 glColor3f   1.0,  0.0,  1.0         ' Set the color to violet
                 glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Right)
                 glVertex3f  1.0,  1.0,  1.0         ' Top left of the quad (Right)
                 glVertex3f  1.0, -1.0,  1.0         ' Bottom left of the quad (Right)
                 glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Right)
              glEnd
           glEndList
        End Sub
        Last edited by Gary Beene; 20 Mar 2013, 06:36 PM.

        Comment


        • #5
          I know this is an old post, but I'm working on print previews for opengl code, and this ties into it. The following is Gary's code above, modified to draw opengl into a dibsection. While the pixel format is set up as single buffer, the dibsection is essentially the new "back buffer". Using this technique:

          1. Essentially double buffers..
          2. Can directly draw your opengl scene to the dibsection, ALONG with GDI commands. For my purpose, these will generally be pretty simple uses, map legend, map heading, north arrow etc.
          3. Most print drivers support StretchDIBits function, which allows direct copying to a printer context (you would want to make sure the glClearColor is white).

          Code:
          'Compilable Example:
          #COMPILE EXE
          #DIM ALL
          #INCLUDE "win32api.inc"
          #INCLUDE "gl.inc"
          #INCLUDE "glu.inc"
          
          %ID_Timer = 1000
          
          %backred=100
          %backgrn=100
          %backblu=100
          
          %timerms=50
          
          FUNCTION PBMAIN() AS LONG
            LOCAL hDlg AS DWORD
            DIALOG NEW PIXELS, 0, "OpenGL DIBSection Example",,, 320, 240, %WS_OVERLAPPEDWINDOW TO hDlg
            DIALOG SHOW MODAL hdlg CALL dlgproc
          END FUNCTION
          
          CALLBACK FUNCTION dlgproc()
             STATIC SpinInWork,XLast,YLast AS LONG
             STATIC DibPtr, memDC, hDC, hRC, hDIB AS DWORD
             STATIC bmInfo AS BITMAPINFO
             STATIC scalefactor AS SINGLE
             LOCAL pt AS POINT
             LOCAL XDelta, YDelta AS SINGLE
             LOCAL rc AS rect
          
             SELECT CASE CB.MSG
                CASE %WM_INITDIALOG
                  ogerr(1)
                  GetClientRect(CB.HNDL, rc)
                  hDC=GetDC(CB.HNDL)
                  hDIB=CreateDIB(rc.right*3, rc.bottom*3, DibPtr, memDC, bminfo)
                  SetBkMode(memDC, %TRANSPARENT)
                  hRC=GetRenderContext(CB.HNDL, memDC, hDIB)
                  IF ISFALSE(hRC) THEN
                    ? "Couldn't Create Render Context, Exiting."
                    DestroyWindow(CB.HNDL)
                    EXIT FUNCTION
                  END IF
                  InitializeScene
                  ScaleFactor=1
                  ResizeScene(bminfo)
                  ogerr(0)
                  SetTimer(CB.HNDL, %ID_Timer, %timerms, %NULL)
                CASE %WM_TIMER, %WM_SIZE : DrawScene(CB.HNDL, 1,1,1, scalefactor, DibPtr, bminfo)  'redraw with rotation on all 3 axes
                CASE %WM_PAINT : RefreshScene(CB.HNDL, DibPtr, bminfo)
                CASE %WM_CLOSE
                  wglmakecurrent %null, %null 'unselect rendering context
                  wgldeletecontext hRC        'delete the rendering context
                  IF hDib THEN DeleteObject(hDIB) 'delete the DIB object handle
                  ReleaseDC(CB.HNDL, hDC)         'release device context
                CASE %WM_MOUSEWHEEL
                   SELECT CASE HI(INTEGER,CB.WPARAM)
                      CASE > 0
                        ScaleFactor = ScaleFactor + 0.1
                        DrawScene(CB.HNDL,0,0,0, scalefactor, DibPtr, bminfo)
                      CASE < 0
                        ScaleFactor = ScaleFactor - 0.1
                        DrawScene(CB.HNDL,0,0,0, scalefactor, DibPtr, bminfo)
                   END SELECT
                CASE %WM_LBUTTONDOWN
                   KillTimer CB.HNDL, %ID_Timer
                   SpinInWork = 1
                   GetCursorPos(pt)              'pt has xy screen coordinates
                   ScreenToClient(hDC, pt)       'pt now has dialog client coordinates
                   XLast = Pt.x
                   YLast = Pt.y
                CASE %WM_MOUSEMOVE
                   IF SpinInWork THEN
                      GetCursorPos(pt)           'pt has xy screen coordinates
                      ScreenToClient(hDC, pt)    'pt now has dialog client coordinates
                      XDelta = XLast - Pt.x
                      YDelta = YLast - Pt.y
                      DrawScene(CB.HNDL,-YDelta, -XDelta, 0, scalefactor, DibPtr, bminfo)
                      XLast = pt.x
                      YLast = pt.y
                   END IF
                CASE %WM_LBUTTONUP
                   SetTimer(CB.HNDL, %ID_Timer, %timerms, %NULL)
                   SpinInWork = 0
             END SELECT
          END FUNCTION
          
          FUNCTION GetRenderContext(BYVAL hwnd AS DWORD, memDC AS DWORD, BYVAL hDib AS DWORD) AS DWORD
             LOCAL lresult  AS LONG
             LOCAL pfd      AS PIXELFORMATDESCRIPTOR   'pixel format properties for device context
             LOCAL hRC    AS DWORD
          
             pfd.nSize       =  SIZEOF(PIXELFORMATDESCRIPTOR)
             pfd.nVersion    =  1
             pfd.dwFlags     = %PFD_DRAW_TO_WINDOW OR %PFD_SUPPORT_OPENGL OR %PFD_DRAW_TO_BITMAP OR %PFD_SUPPORT_GDI
             pfd.dwlayermask = %pfd_main_plane
             pfd.iPixelType  = %pfd_type_rgba
             pfd.ccolorbits  = 24
             pfd.cdepthbits  = 32
          
             SelectObject(memDC, hDIB)
             SetPixelFormat(memDC, ChoosePixelFormat(memDC, pfd), pfd)
          
             hRC=wglCreateContext(memDC)      'get rendering context
             IF hRC THEN wglMakeCurrent memDC, hRC  'Make the RC current
             FUNCTION=hRC
          END FUNCTION
          
          SUB InitializeScene
             glClearColor(%backred/255,%backgrn/255,%backblu/255,0)
             glClearDepth 1           'sets zvalue to be used with glClear
             glEnable %gl_depth_test                             'enable depth testing
             glHint %gl_perspective_correction_hint, %gl_nicest  'best quality rendering
             BuildDisplayList 1
          END SUB
          
          SUB ResizeScene (BYREF bminfo AS BITMAPINFO)
             glViewport 0, 0, bmInfo.bmiHeader.biWidth, bmInfo.bmiHeader.biHeight 'resize viewport to match DIBSECTION size
             glMatrixMode %gl_projection         'select the projection matrix
             glLoadIdentity                    'reset the projection matrix
             gluPerspective 45, bmInfo.bmiHeader.biWidth/bmInfo.bmiHeader.biHeight, 0.1, 100  'set frustum using viewport aspect ratio
             glMatrixMode %gl_modelview          'select the modelview matrix
          END SUB
          
          SUB DrawScene (BYVAL hWnd AS DWORD, dx AS SINGLE, dy AS SINGLE, dz AS SINGLE, scalef AS SINGLE, BYVAL DibPtr AS DWORD, BYREF bminfo AS BITMAPINFO)
             STATIC errcnt AS LONG
             STATIC anglex, angley, anglez AS SINGLE
             LOCAL rc AS rect
             glClear(%gl_color_buffer_bit OR %gl_depth_buffer_bit)  'clear buffers
             glLoadIdentity               'clear the modelview matrix
          
             gluLookAt 0,0,6,0,0,0,0,1,0
          
             glScalef scalef, scalef, scalef
          
             anglex = anglex + dx : glRotatef anglex, 1,0,0
             angley = angley + dy : glRotatef angley, 0,1,0
             anglez = anglez + dz : glRotatef anglez, 0,0,1
          
             glCallList 1
             IF DibPtr THEN
               glFinish
               Draw_GDI(wglGetCurrentDC(), 1, bminfo) : GdiFlush()
               RefreshScene(hWnd, DibPtr, bminfo)
             END IF
             IF errcnt=0 THEN errcnt=ogerr(0) 'for testing, check oglerr, but just display once..
          END SUB
          
          SUB RefreshScene(BYVAL hWnd AS DWORD, BYVAL DibPtr AS DWORD, BYREF bminfo AS BITMAPINFO)
            'just simply copies dib to screen DC, call on
            'an updated scene, or a wm_paint
            'This will stretch the bitmap to screen, so some distortion may be seen
            'when resizing the screen.  To combat this, one would need to delete the current
            'DIB, create a new one with the new screen aspect, and delete and create a new render context
            ' OR
            'allow resize, but keep original aspect ratio (like with a print preview)
            LOCAL rc AS rect
            LOCAL hDC AS DWORD
            GetClientRect(hWnd, rc)
            hDC=GetDC(hWnd)
            StretchDIBits(hDC, _
                          0, _
                          0, _
                          rc.right, _
                          rc.bottom, _
                          0, _
                          0, _
                          bmInfo.bmiHeader.biWidth, _
                          bmInfo.bmiHeader.biHeight, _
                          BYVAL DibPtr, _
                          BYVAL VARPTR(bminfo), _
                          %DIB_RGB_COLORS, _
                          %SRCCOPY)
            ReleaseDC(hWnd, hDC)
          END SUB
          
          SUB DRAW_GDI(BYVAL hDibDC AS DWORD, BYVAL inc AS LONG, BYREF bminfo AS BITMAPINFO)  '<<<<<<<<<<<DH
            'Draw GDI Stuff here...for testing
            LOCAL teststr AS STRING
            LOCAL TXT AS SIZE
            STATIC dflg AS LONG
            STATIC x AS LONG
          
            teststr="THIS IS A HAPPY LITTLE GDI TEST.."
          
            GetTextExtentPoint32(hDibDC, BYVAL STRPTR(teststr), LEN(teststr), TXT)
            IF dflg THEN
              x-=inc
              IF x<0 THEN x=0 : dflg=0
            ELSE
              x+=inc
              IF (x+txt.cx)>bmInfo.bmiHeader.biWidth THEN x=bmInfo.bmiHeader.biWidth-txt.cx : dflg=1
            END IF
            Textout(hDibDC, X, 100, BYVAL STRPTR(teststr), LEN(teststr))
          END SUB
          
          SUB BuildDisplayList(ListNumber AS LONG)
             glNewList ListNumber, %gl_compile
                glBegin %GL_QUADS
                   glColor3f   0.0,  1.0,  0.0         ' Set the color to green
                   glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Top)
                   glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Top)
                   glVertex3f -1.0,  1.0,  1.0         ' Bottom left of the quad (Top)
                   glVertex3f  1.0,  1.0,  1.0         ' Bottom right of the quad (Top)
          
                   glColor3f   1.0,  0.5,  0.0         ' Set the color to orange
                   glVertex3f  1.0, -1.0,  1.0         ' Top right of the quad (Bottom)
                   glVertex3f -1.0, -1.0,  1.0         ' Top left of the quad (Bottom)
                   glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Bottom)
                   glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Bottom)
          
                   glColor3f   1.0,  0.0,  0.0         ' Set the color to red
                   glVertex3f  1.0,  1.0,  1.0         ' Top right of the quad (Front)
                   glVertex3f -1.0,  1.0,  1.0         ' Top left of the quad (Front)
                   glVertex3f -1.0, -1.0,  1.0         ' Bottom left of the quad (Front)
                   glVertex3f  1.0, -1.0,  1.0         ' Bottom right of the quad (Front)
          
                   glColor3f   1.0,  1.0,  0.0         ' Set the color to yellow
                   glVertex3f  1.0, -1.0, -1.0         ' Top right of the quad (Back)
                   glVertex3f -1.0, -1.0, -1.0         ' Top left of the quad (Back)
                   glVertex3f -1.0,  1.0, -1.0         ' Bottom left of the quad (Back)
                   glVertex3f  1.0,  1.0, -1.0         ' Bottom right of the quad (Back)
          
                   glColor3f   0.0,  0.0,  1.0         ' Set the color to blue
                   glVertex3f -1.0,  1.0,  1.0         ' Top right of the quad (Left)
                   glVertex3f -1.0,  1.0, -1.0         ' Top left of the quad (Left)
                   glVertex3f -1.0, -1.0, -1.0         ' Bottom left of the quad (Left)
                   glVertex3f -1.0, -1.0,  1.0         ' Bottom right of the quad (Left)
          
                   glColor3f   1.0,  0.0,  1.0         ' Set the color to violet
                   glVertex3f  1.0,  1.0, -1.0         ' Top right of the quad (Right)
                   glVertex3f  1.0,  1.0,  1.0         ' Top left of the quad (Right)
                   glVertex3f  1.0, -1.0,  1.0         ' Bottom left of the quad (Right)
                   glVertex3f  1.0, -1.0, -1.0         ' Bottom right of the quad (Right)
                glEnd
             glEndList
          END SUB
          
          FUNCTION CreateDIB(BYVAL w AS LONG, BYVAL h AS LONG, BYREF DibPtr AS DWORD, BYREF memDC AS DWORD, BYREF bminfo AS BITMAPINFO) AS DWORD '(byval tpg as dword) AS LONG
            memDC=CreateCompatibleDC(0) : IF memDC=0 THEN EXIT FUNCTION
            bmInfo.bmiHeader.biSize        = SIZEOF(bmInfo.bmiHeader)
            bmInfo.bmiHeader.biWidth       = w
            bmInfo.bmiHeader.biHeight      = h
            bmInfo.bmiHeader.biPlanes      = 1
            bmInfo.bmiHeader.biBitCount    = 32
            bmInfo.bmiHeader.biCompression = %BI_RGB
            bmInfo.bmiHeader.biSizeImage   = 0 'since BI_RGB, set to 0 (no compression)
            FUNCTION=CreateDIBSection(memDC, bmInfo, %DIB_RGB_COLORS, BYVAL VARPTR(DibPtr), %null, %null)
          END FUNCTION
          
          FUNCTION ogerr(BYVAL silent AS LONG) AS LONG
              LOCAL lresult AS LONG
              lresult=glGetError()
              FUNCTION=lresult
              IF silent THEN EXIT FUNCTION
              SELECT CASE lresult
                  CASE %GL_INVALID_ENUM      : ? "Invalid Value as enumeration"
                  CASE %GL_INVALID_VALUE     : ? "value out of range"
                  CASE %GL_INVALID_OPERATION : ? "Invalid Operation"
                  CASE %GL_NO_ERROR
                  CASE %GL_STACK_OVERFLOW    : ? "stack overflow"
                  CASE %GL_STACK_UNDERFLOW   : ? "stack underflow"
                  CASE %GL_OUT_OF_MEMORY     : ? "Out of Memory"
              END SELECT
          END FUNCTION
          "Show me a young Conservative and I'll show you someone with no heart. Show me an old Liberal and I'll show you someone with no brains." ― Winston Churchill
          "Socialism is the philosophy of failure, the creed of ignorance and the gospel of envy." ― Winston Churchill

          Comment

          Working...
          X