5 Replies Latest reply on Nov 21, 2011 6:37 AM by gex2k11

    eglCreateContext: Context sharing between two EGLDisplays

    gex2k11
      Catalyst 11.10, Windows

      Hi everyone,

      I'm wondering if context sharing between two EGLDisplays (two different windows) is allowed/possible, or if it's somehow restricted.

      I initialize the first context with

      EGLContext c1 = eglCreateContext(disp1, windowConfig, 0, contextAttributes);

      the second with

      EGLContext c1 = eglCreateContext(disp2, windowConfig, c1, contextAttributes);

      With eglGetError then I get EGL_BAD_CONTEXT; and as a result c1 is EGL_NO_CONTEXT.

      I assume the initialization of the displays to be correct, because separately they work.

      Is this possible on Windows with Catalyst 11.10? or is it restricted? or might it be a bug?

      cheers

      Georg

        • eglCreateContext: Context sharing between two EGLDisplays
          gsellers

          Hi Georg,

          By two displays, do you mean that you are trying to share resources across two GPUs? If so, that's not supported. However, if both diplays are on the same adapter, it should work. Could you share a test application?

          Cheers,

          Graham

            • eglCreateContext: Context sharing between two EGLDisplays
              gex2k11

              Hi Graham,

              First thx for your reply. They are on the same adapter. As I'm using MS Windows XP the EGLDisplays are in this case just two different windows. I forgot to mention the adapter itself, it's a Radeon HD 4350.

              This is just a small test application to confirm if nothing else was the reason,

              i've encapsuled the Display creation and context creation in one class:

              class DisplayContext{

              public:
                  DisplayContext():
                    hwnd(0),hInstance(0),disp(0),windowConfig(0), context(0)
                  {

                  }

                  ~DisplayContext()
                  {

                  }
                 
                  bool OpenWindow(int width, int height, const TCHAR* wndClass, const TCHAR* wndName)
                  {
                     
                      hInstance = GetModuleHandle(NULL);
                      wcex.cbSize = sizeof(WNDCLASSEX);

                      wcex.style = CS_OWNDC;
                      wcex.lpfnWndProc = &DefWindowProc;
                      wcex.cbClsExtra = 0;
                      wcex.cbWndExtra = 0;
                      wcex.hInstance = hInstance;
                      wcex.hIcon = NULL;
                      wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
                      wcex.hbrBackground = 0; //(HBRUSH)(COLOR_WINDOW+1);
                      wcex.lpszMenuName = NULL;
                      wcex.lpszClassName = wndClass;
                      wcex.hIconSm = NULL;

                      RegisterClassEx(&wcex);
                      RECT rect = {0,0, width, height};
                      int style = WS_BORDER | WS_CAPTION;
                      AdjustWindowRect(&rect, style, FALSE);

                      hwnd = CreateWindow(wndClass, wndName, style,
                          CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, GetModuleHandle(NULL), NULL);
                      ShowWindow(hwnd, SW_SHOW);

                      return hwnd != 0;
                  }

                  bool CreateEGLContext(EGLContext share)
                  {
                      if(hwnd != 0) {
                          HDC hdc = GetDC(hwnd);

                          disp = eglGetDisplay(hdc);

                          EGLint major, minor;
                          eglInitialize(disp,&major, &minor);
                          eglBindAPI(EGL_OPENGL_ES_API);

                          EGLint attributes[] =
                          {
                              EGL_BUFFER_SIZE, 0,
                              EGL_RED_SIZE, 5,
                              EGL_GREEN_SIZE, 6,
                              EGL_BLUE_SIZE, 5,
                              // EGL_LUMINANCE_SIZE, 0,
                              EGL_ALPHA_SIZE, 0,
                              //EGL_ALPHA_MASK_SIZE, 0,
                              EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
                              EGL_CONFIG_CAVEAT, EGL_DONT_CARE,
                              EGL_CONFIG_ID, EGL_DONT_CARE,
                              //EGL_CONFORMANT, 0,
                              EGL_DEPTH_SIZE, 24,
                              EGL_LEVEL, 0,
                              EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE,
                              EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE,
                              EGL_NATIVE_RENDERABLE, EGL_DONT_CARE,
                              EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE,
                              EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                              EGL_SAMPLE_BUFFERS, 0,
                              EGL_SAMPLES, 0,
                              EGL_STENCIL_SIZE, 0,
                              EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                              EGL_TRANSPARENT_TYPE, EGL_NONE,
                              EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE,
                              EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE,
                              EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE,
                              EGL_NONE
                          };

                          EGLint surfaceAttributes[] = {EGL_NONE};
                          EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

                          EGLint nrOfConfigs;
                          eglChooseConfig(disp, attributes,&windowConfig,1,&nrOfConfigs);
                          surface = eglCreateWindowSurface(disp, windowConfig, hwnd,surfaceAttributes);

                          context = eglCreateContext(disp, windowConfig, share,contextAttributes);

                          return context != EGL_NO_CONTEXT;
                      }
                  }

                  EGLContext GetContext(){
                      return context;
                  }

              private:
                  WNDCLASSEX wcex;
                  HINSTANCE hInstance;
                  HWND hwnd;

                  EGLDisplay disp;
                  EGLConfig windowConfig;
                  EGLContext context;
                  EGLSurface surface;


              };

              They are called an instatiated as follows:

                          DisplayContext context1;
                          DisplayContext context2;

                          bool res = context1.OpenWindow(640,480, "TEST1", "TEST1");
                          res = context1.CreateEGLContext(EGL_NO_CONTEXT);

                          res = context2.OpenWindow(640,480, "TEST2", "TEST2");
                          res = context2.CreateEGLContext(context1.GetContext());

              while res always gets false after the second CreateEGLContext. When checking EGLGetError EGL_BAD_CONTEXT is returned after the second call to eglCreateContext.

              The functions from atioglxx.dll are called analogous to the existing egl demo.

              First the dll is loaded with

              HINSTANCE atioglxxDll = LoadLibrary(_T("atioglxx.dll"));

              The function pointers are declared as showed on the example of eglGetError:

              typedef EGLint EGLAPIENTRY eglGetError(void);

              EglFunctions::eglGetError* eglGetErrorPointer;

              Then the pointers are queried from the Dll:

              result = result & ((eglGetErrorPointer = (EglFunctions::eglGetError*)GetProcAddress(atioglxxDll, "eglGetError")) != 0);

              Finally a dll wrapper that implements the EGL interface itself calls the functions:

              EGLint EGLAPIENTRY eglGetError(void)
              {
                  return eglGetErrorPointer();
              }

              If you need any more information please tell me.

              Cheers, Georg

                • eglCreateContext: Context sharing between two EGLDisplays
                  gsellers

                  Hi Georg,

                  This is just a complete guess from looking at your code, but I think the problem is because you're calling eglInitialize every time you create a context and are actually using a different DC each time. On Windows EGL, the NativeDisplayType 'HDC' is the DC for the display, not the window, so (I think) our implementation is seeing the share_context as belonging to a different display (DC) and therefore refusing to share. You should call eglInitialize once for a display. Once the display (adapter) as been initialized, it need not be initialized again.

                  My suggestion would be to get the DC for the entire screen (call GetDC(NULL)), call eglGetDisplay using that DC and use the resulting display handle use that to initialize EGL. You could even call eglGetDisplay(EGL_DEFAULT_DISPLAY) and avoid the DC issue all together. After that, call eglInitialize once and then create as many contexts as you wish - but make sure to use the same EGLDisplay parameter in each creation call. To make separate contexts current to different windows, create an EGLSurface representing the window (with eglCreateWindowSurface) and then make the context(s) current to the window surface by passing the resulting surfaces to to eglMakeCurrent.

                  Let me know if that works. If not, we'll dig deeper.

                  Cheers,

                  Graham

                    • eglCreateContext: Context sharing between two EGLDisplays
                      gex2k11

                      Hi Graham,

                      thanks for your advice, sounds useful. Till now we used Imagination SDK which simulates PowerVR, but maybe in this case, so in this simulation, really two displays were simulated by two windows.

                      That may be the reason why the code worked till now. I'll try your suggestions and will keep you informed about the results, but I'm not back in the office till monday, so it will take at least unitl then.

                      Cheers Georg