Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Pbuffer

Help
Joao
2005-11-10
2013-04-17
  • Joao
    Joao
    2005-11-10

    Hi,

    I tried tu run a sample that used eglCreatePbufferSurface() in Pocket PC 2003, but all that was shown was a white screen. What is wrong? Is thre any working sample of pbuffer in Pocket PC? Is pbuffer already supported in this platform?

    The code is as follows:

    //#define SAMPLE_SURFACE_TYPE EGL_WINDOW_BIT
    //#define SAMPLE_SURFACE_TYPE EGL_PIXMAP_BIT

    #define SAMPLE_SURFACE_TYPE EGL_PBUFFER_BIT
    #define SAMPLE_WINDOW_WIDTH  128
    #define SAMPLE_WINDOW_HEIGHT 128

    //#define PIXMAP_COLOR_FORMAT 555
    //#define PIXMAP_COLOR_FORMAT 565
    #define PIXMAP_COLOR_FORMAT 888

    #if (PIXMAP_COLOR_FORMAT == 555) || (PIXMAP_COLOR_FORMAT == 565)
    #   define SAMPLE_PIXMAP_BITS 16
    #elif (PIXMAP_COLOR_FORMAT == 888)
    #   define SAMPLE_PIXMAP_BITS 32
    #else
    #   error PIXMAP_COLOR_FORMAT not properly defined.
    #endif

    #if defined (_MSC_VER)
    #   pragma warning(disable : 4115) /* named type definition in parentheses */
    #endif

    #include <windows.h>
    #include <math.h>
    #include "GLES/gl.h"
    #include "GLES/egl.h"

    #include <stdio.h>

    // WinCE stuff
    #define MAX_LOADSTRING                  100
    #define IDS_APP_TITLE                   1
    #define IDC_TESTAPP                     3

    /* EGL resources and Windows globals, defines, and prototypes */
    static LONG WINAPI  MainWndProc (HWND, UINT, WPARAM, LPARAM);
    static void         drawScene   (int width, int height);

    // GAPI is not used in emulators
    #ifndef _X86_
    #   define USE_GAPI
    #endif

    #ifndef USE_GAPI
    #   define SAMPLE_WINDOW_WIDTH  120
    #   define SAMPLE_WINDOW_HEIGHT 120
    #endif

    static const char   szAppName[] = "Gerbera OpenGL ES sample app";
    static HWND         ghWnd;

    static EGLDisplay   eglDisplay;
    static EGLConfig    eglConfig;
    static EGLContext   eglContext;
    static EGLSurface   eglWindowSurface;

    static const EGLint s_configAttribs[] =
    {
    #if (PIXMAP_COLOR_FORMAT == 555)
        EGL_RED_SIZE,       5,
        EGL_GREEN_SIZE,     5,
        EGL_BLUE_SIZE,      5,
    #elif (PIXMAP_COLOR_FORMAT == 565)
        EGL_RED_SIZE,       5,
        EGL_GREEN_SIZE,     6,
        EGL_BLUE_SIZE,      5,
    #elif (PIXMAP_COLOR_FORMAT == 888)
        EGL_RED_SIZE,       8,
        EGL_GREEN_SIZE,     8,
        EGL_BLUE_SIZE,      8,
    #else
    #   error You must define PIXMAP_COLOR_FORMAT
    #endif
        EGL_ALPHA_SIZE,     EGL_DONT_CARE,
        EGL_DEPTH_SIZE,     32,
        EGL_STENCIL_SIZE,   EGL_DONT_CARE,
        EGL_SURFACE_TYPE,   SAMPLE_SURFACE_TYPE,
        EGL_NONE
    };

    #if (SAMPLE_SURFACE_TYPE == EGL_PBUFFER_BIT)
    static const EGLint s_pbufferAttribs[] =
    {
        EGL_WIDTH,  SAMPLE_WINDOW_WIDTH,
        EGL_HEIGHT, SAMPLE_WINDOW_HEIGHT,
        EGL_NONE
    };
    #endif

    #if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)

    static HBITMAP  pixmap;

    /*-------------------------------------------------------------------*//*!
    * \brief   Create a DIB section bitmap.
    * \param   hDC DC handle.
    * \return  Returns the handle to the created bitmap.
    *//*-------------------------------------------------------------------*/

        DWORD*          bits;

    static HBITMAP createPixmap (
        HDC hDC)
    {

        const size_t    bmiSize = sizeof(BITMAPINFO) + 256U*sizeof(RGBQUAD);
        BITMAPINFO*     bmi;
        DWORD*          p;

        bmi = (BITMAPINFO*)malloc(bmiSize);
        memset(bmi, 0, bmiSize);

        bmi->bmiHeader.biSize           = sizeof(BITMAPINFOHEADER);
    #if defined (USE_GAPI)
        bmi->bmiHeader.biWidth          = GetSystemMetrics(SM_CXSCREEN),
        bmi->bmiHeader.biHeight         = -GetSystemMetrics(SM_CYSCREEN),
    #else
        bmi->bmiHeader.biWidth          = SAMPLE_WINDOW_WIDTH;
        bmi->bmiHeader.biHeight         = -SAMPLE_WINDOW_HEIGHT;
    #endif
        bmi->bmiHeader.biPlanes         = (short)1;
        bmi->bmiHeader.biBitCount       = (unsigned int) SAMPLE_PIXMAP_BITS;
        bmi->bmiHeader.biCompression    = BI_BITFIELDS;
        bmi->bmiHeader.biSizeImage      = 0;
        bmi->bmiHeader.biXPelsPerMeter  = 0;
        bmi->bmiHeader.biYPelsPerMeter  = 0;
        bmi->bmiHeader.biClrUsed        = 3;
        bmi->bmiHeader.biClrImportant   = 0;

        p = (DWORD*)bmi->bmiColors;

    #if (PIXMAP_COLOR_FORMAT == 555)
        p[0] = 0x1F << 0;   /* r */
        p[1] = 0x1F << 5;   /* g */
        p[2] = 0x1F << 10;  /* b */
    #elif (PIXMAP_COLOR_FORMAT == 565)
        p[0] = 0x1F << 0;   /* r */
        p[1] = 0x3F << 5;   /* g */
        p[2] = 0x1F << 11;  /* b */
    #elif (PIXMAP_COLOR_FORMAT == 888)
        p[0] = 0xFF;        /* r */
        p[1] = 0xFF00;      /* g */
        p[2] = 0xFF0000;    /* b */
    #else
    #   error SAMPLE_PIXMAP_BITS must be either 16 or 32
    #endif

        return CreateDIBSection(hDC, bmi, DIB_RGB_COLORS, &bits, NULL, 0);
    }

    /*-------------------------------------------------------------------*//*!
    * \brief   Destroy the given bitmap.
    * \param   bitmap  Bitmap handle.
    *//*-------------------------------------------------------------------*/

    static void deletePixmap (
        HBITMAP bitmap)
    {
        DeleteObject(bitmap);
    }

    #endif /* SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT */

    //
    //  FUNCTION: MyRegisterClass()
    //
    //  PURPOSE: Registers the window class.
    //
    //  COMMENTS:
    //
    //    It is important to call this function so that the application
    //    will get 'well formed' small icons associated with it.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
    {
        WNDCLASS    wc;

        wc.style            = 0;
        wc.lpfnWndProc      = (WNDPROC)MainWndProc;
        wc.cbClsExtra       = 0;
        wc.cbWndExtra       = 0;
        wc.hInstance        = hInstance;
        wc.hIcon            = NULL;
        wc.hCursor          = LoadCursor (NULL,IDC_ARROW);
        wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
        wc.lpszMenuName     = NULL;
        wc.lpszClassName    = szWindowClass;

        return RegisterClass(&wc);
    }

    //
    //  FUNCTION: InitInstance(HANDLE, int)
    //
    //  PURPOSE: Saves instance handle and creates main window
    //
    //  COMMENTS:
    //
    //    In this function, we save the instance handle in a global variable and
    //    create and display the main program window.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
        TCHAR   szTitle[MAX_LOADSTRING];            // The title bar text
        TCHAR   szWindowClass[MAX_LOADSTRING];      // The window class name

        // Initialize global strings
        LoadString(hInstance, IDC_TESTAPP, szWindowClass, MAX_LOADSTRING);
        LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

        MyRegisterClass(hInstance, szWindowClass);

    #if defined(USE_GAPI)
        ghWnd = CreateWindow(szWindowClass,
                             szTitle,
                             WS_VISIBLE,
                             CW_USEDEFAULT,
                             CW_USEDEFAULT,
                             GetSystemMetrics(SM_CXSCREEN),
                             GetSystemMetrics(SM_CYSCREEN),
                             NULL,
                             NULL,
                             hInstance,
                             NULL);
    #else
        ghWnd = CreateWindow(szWindowClass,
                             szTitle,
                             WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
                             CW_USEDEFAULT,
                             CW_USEDEFAULT,
                             SAMPLE_WINDOW_WIDTH,
                             SAMPLE_WINDOW_HEIGHT,
                             NULL,
                             NULL,
                             hInstance,
                             NULL);
    #endif
        if (!ghWnd)
            return FALSE;

    #if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
        {
            HDC dc = GetDC(ghWnd);
            pixmap = createPixmap(dc);
            ReleaseDC(ghWnd, dc);
        }
    #endif

        {
            /* EGL Setup */
            EGLint numConfigs;
            EGLint majorVersion;
            EGLint minorVersion;

            int error;

            eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
            eglInitialize(eglDisplay, &majorVersion, &minorVersion);
            eglGetConfigs(eglDisplay, NULL, 0, &numConfigs);
            eglChooseConfig(eglDisplay, s_configAttribs, &eglConfig, 1, &numConfigs);
            eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);

    #if (SAMPLE_SURFACE_TYPE == EGL_WINDOW_BIT)
            eglWindowSurface = eglCreateWindowSurface(eglDisplay, eglConfig, ghWnd, NULL);
    #elif (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
            eglWindowSurface = eglCreatePixmapSurface(eglDisplay, eglConfig, pixmap, NULL);
    #elif (SAMPLE_SURFACE_TYPE == EGL_PBUFFER_BIT)
            eglWindowSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, s_pbufferAttribs);
            error = eglGetError();
    #endif

            eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext);
            error = eglGetError();
        }

        ShowWindow(ghWnd, nCmdShow);
        UpdateWindow(ghWnd);

        return TRUE;
    }

    /*-------------------------------------------------------------------*//*!
    * \brief   Main procedure.
    * \param   hInstance       Instance handle.
    * \param   hPrevInstance   Previous instance handle.
    * \param   lpCmdLine       Command line.
    * \param   nCmdShow        Show command.
    * \return  Returns exit status.
    *//*-------------------------------------------------------------------*/

    int WINAPI WinMain (
        HINSTANCE   hInstance,
        HINSTANCE   hPrevInstance,
        LPWSTR      lpCmdLine,
        int         nCmdShow)
    {
        int i;
        MSG             msg;

        hPrevInstance;
        lpCmdLine;

        // Perform application initialization:
        if (!InitInstance (hInstance, nCmdShow))
        {
            return FALSE;
        }

        for(i = 0; i<6000; i++)
        {
            RECT rc;
            while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
            {
                if (GetMessage(&msg, NULL, 0, 0) )
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
                else
                    return 0;
            }

            GetClientRect(ghWnd, &rc);
            drawScene(rc.right, rc.bottom);
        }
        DestroyWindow(ghWnd);
        return 0;
    }

    /*-------------------------------------------------------------------*//*!
    * \brief   Main window procedure.
    * \param   hWnd    Window handle.
    * \param   uMsg    Message.
    * \param   wParam  Parameter.
    * \param   lParam  Parameter.
    * \return  Returns the return status.
    *//*-------------------------------------------------------------------*/

    static LONG WINAPI MainWndProc (
        HWND    hWnd,
        UINT    uMsg,
        WPARAM  wParam,
        LPARAM  lParam)
    {
        PAINTSTRUCT     ps;
        LONG            lRet = 1;

    // For sniffing messages:
    #if 0
        if (uMsg != WM_PAINT)
        {
            wchar_t str[128];
            swprintf(str, L"0x%X (%d)\n", uMsg, uMsg);
            //swprintf(str, L"0x%X (%d)\n", wParam, wParam);
            OutputDebugString(str);
        }
    #endif

        switch (uMsg)
        {
        case WM_PAINT:
            {
                HDC dc = BeginPaint(hWnd, &ps);
    #if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
                HDC hdcBitmap = CreateCompatibleDC((HDC)dc);
                HDC old = SelectObject(hdcBitmap, pixmap);

                int dx0 = 0;
                int dy0 = 0;
    #   if defined (USE_GAPI)

                int dx1 = GetSystemMetrics(SM_CXSCREEN);
                int dy1 = GetSystemMetrics(SM_CYSCREEN);
    #   else
                int dx1 = SAMPLE_WINDOW_WIDTH;
                int dy1 = SAMPLE_WINDOW_HEIGHT;
    #   endif

                int x=0,y=0;

                for (x = 1; x < 4; x+=2)
                for (y = 160; y < 260; y++)
                    ((unsigned short*)bits)[y*240 + x] = 0xFFFF;

    //          memset(bits, 0xff, 240*240*2);

                StretchBlt((HDC)dc, dx0, dy0, dx1, dy1, hdcBitmap, dx0, dy0, dx1, dy1, SRCCOPY);

                SelectObject(hdcBitmap, old);
    #else
                (void)dc; /* unreferenced */
    #endif
                EndPaint(hWnd, &ps);
            }
            break;

        case WM_SIZE:
            /* Resizing is handled each frame */
            break;

        case WM_KILLFOCUS:
        case WM_CLOSE:
            DestroyWindow (hWnd);
            break;

        case WM_DESTROY:
            /* Destroy all EGL resources */
            eglMakeCurrent(eglDisplay, NULL, NULL, NULL);
            eglDestroyContext(eglDisplay, eglContext);
            eglDestroySurface(eglDisplay, eglWindowSurface);
            eglTerminate(eglDisplay);
    #if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
            deletePixmap(pixmap);
    #endif
            PostQuitMessage (0);
            break;

        // exit with every key pressed
        case WM_KEYDOWN:
            DestroyWindow (hWnd);

        case WM_LBUTTONDOWN:
            DestroyWindow (hWnd);

            /* FALLTHROUGH */

        default:
            lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
            break;
        }

        return lRet;
    }

    /* OpenGL code */

    /*-------------------------------------------------------------------*//*!
    * \brief   Sets the perspective matrix to OpenGL.
    * \param   fovy    Vertical field-of-view.
    * \param   aspect  Aspect ratio.
    * \param   zNear   Distance to near plane.
    * \param   zFar    Distance to far plane.
    *//*-------------------------------------------------------------------*/

    static void perspective (
        GLfloat fovy,
        GLfloat aspect,
        GLfloat zNear,
        GLfloat zFar)
    {
        GLfloat xmin, xmax, ymin, ymax;

        ymax = zNear * (GLfloat)tan(fovy * 3.1415962f / 360.0);
        ymin = -ymax;
        xmin = ymin * aspect;
        xmax = ymax * aspect;

        glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
    }

    /*-------------------------------------------------------------------*//*!
    * \internal
    * \brief   Update state.
    * \param   width   Rendering width.
    * \param   height  Rendering height.
    *//*-------------------------------------------------------------------*/

    static void updateState (
        int width,
        int height)
    {
        static const GLfloat light_position[]   = { -50.f, 50.f, 200.f, 0.f };
        static const GLfloat light_ambient[]    = { 0.25f, 0.25f, 0.25f, 1.f };
        static const GLfloat light_diffuse[]    = { 1.f, 1.f, 1.f, 1.f };
        static const GLfloat material_spec[]    = { 0.f, 0.f, 0.f, 0.f };

        float aspect = height ? (float)width/(float)height : 1.0f;

        glMatrixMode        (GL_MODELVIEW);
        glLoadIdentity      ();

        glLightfv           (GL_LIGHT0, GL_POSITION, light_position);
        glLightfv           (GL_LIGHT0, GL_AMBIENT, light_ambient);
        glLightfv           (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
        glLightfv           (GL_LIGHT0, GL_SPECULAR, light_diffuse);
        glMaterialfv        (GL_FRONT_AND_BACK, GL_SPECULAR, material_spec);

        glEnable            (GL_LIGHTING);
        glEnable            (GL_LIGHT0);
        glEnable            (GL_COLOR_MATERIAL);
        glEnable            (GL_CULL_FACE);
        glEnable            (GL_NORMALIZE);

        glDisable           (GL_DEPTH_TEST);
        glDepthMask         (GL_FALSE);
        glClearDepthf       (1);

        glHint              (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

        glShadeModel        (GL_FLAT);
        glDisable           (GL_DITHER);
        glClearColor        (0.1f, 0.2f, 0.1f, 0.f );
        glColor4x           (0x10000, 0, 0, 0);
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);

        glMatrixMode        (GL_PROJECTION);
        glLoadIdentity      ();
        perspective         (60.f, aspect, 0.1f, 100.f);
    }

    /*-------------------------------------------------------------------*//*!
    * \brief   Draw the scene.
    * \param   width   Rendering width in pixels
    * \param   height  Rendering height in pixels
    *//*-------------------------------------------------------------------*/

    static void drawScene (
        int width,
        int height)
    {
        /* Vertices */
        static const GLbyte cubeVertices[] =
        {
            -10,  10,  10,
             10, -10,  10,
             10,  10,  10,
            -10, -10,  10,
            -10,  10, -10,
             10, -10, -10,
             10,  10, -10,
            -10, -10, -10
        };

        /* Vertex indices */
        static const GLubyte cubeIndices[] =
        {
            0, 3, 1, 2, 0, 1, /* front  */
            6, 5, 4, 5, 7, 4, /* back   */
            4, 7, 3, 0, 4, 3, /* left   */
            2, 1, 5, 6, 2, 5, /* right  */
            4, 0, 2, 6, 4, 2, /* top    */
            3, 7, 1, 7, 5, 1  /* bottom */
        };

        /* Normals */
        static const GLbyte cubeNormals[] =
        {
            -1,  1,  1,
             1, -1,  1,
             1,  1,  1,
            -1, -1,  1,
            -1,  1, -1,
             1, -1, -1,
             1,  1, -1,
            -1, -1, -1
        };

        const double time = fmod(GetTickCount() / 1000.0, 360.0);

        updateState (width, height);

        glClearColor    (0.1f, 0.2f, 0.4f, 0.f);
        glClear         (GL_COLOR_BUFFER_BIT);
        glVertexPointer (3, GL_BYTE, 0, cubeVertices);
        glNormalPointer (GL_BYTE, 0, cubeNormals);

        glMatrixMode    (GL_MODELVIEW);
        glLoadIdentity  ();

        glTranslatef    (0.f, 0.f, -30.f);
        glRotatef       ((float)(time*30.77f), 1.f, 2.f, 0.f);
        glRotatef       ((float)(time*21.311f), -.1f, 0.f, -5.f);

        glDrawElements  (GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, cubeIndices);

    #if (SAMPLE_SURFACE_TYPE == EGL_WINDOW_BIT)
        eglSwapBuffers  (eglDisplay, eglWindowSurface);
    #elif (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
        InvalidateRect(ghWnd, NULL, FALSE);
    #endif
    }

    /*----------------------------------------------------------------------*/

    Joo Paulo Silva do Monte Lima
    GPRT - Grupo de Pesquisa em Redes e Telecomunicaes

     
    • What exactly do you expect to happen? The specification says:

      "To post the color buffer to a window, call
      EGLBoolean eglSwapBuffers(EGLDisplay dpy,
      EGLSurface surface);
      If surface is a window surface, then the color buffer is copied to the native
      window associated with that surface. If surface is a pixmap or pbuffer surface,
      eglSwapBuffers has no effect."

      So for a window surface, you can post directly. For a bitmap, as the example shows, you can grab the underlying bitmap and draw it yourself (not implemented in Vincent BTW). PBuffers are really there for buffering inside the graphics card (e.g. to pass data from one rendering pass to the next).

      - HM

       
    • Matthew Scott
      Matthew Scott
      2005-11-19

      Just in case you didn't already catch this, Joao.

      Your code works great, except that you forgot to handle the case where SAMPLE_SURFACE_TYPE == EGL_PBUFFER_BIT at the bottom of drawScene. If you change that code to:

      #if (SAMPLE_SURFACE_TYPE == EGL_WINDOW_BIT || SAMPLE_SURFACE_TYPE == EGL_PBUFFER_BIT)
          eglSwapBuffers (eglDisplay, eglWindowSurface);
      #elif (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
          InvalidateRect(ghWnd, NULL, FALSE);
      #endif

      Then it renders your box instead of just a black screen.

      GenericBum