Fixed problems with OpenGL ES window resizing.
authorMike Gorchak <lestat@i.com.ua>
Thu, 11 Jun 2009 05:57:32 +0000
changeset 319364e4442676a6
parent 3192 ec126b077b96
child 3194 c18c03927a77
Fixed problems with OpenGL ES window resizing.
src/video/photon/SDL_photon.c
src/video/photon/SDL_photon.h
     1.1 --- a/src/video/photon/SDL_photon.c	Wed Jun 10 18:32:42 2009 +0000
     1.2 +++ b/src/video/photon/SDL_photon.c	Thu Jun 11 05:57:32 2009 +0000
     1.3 @@ -385,42 +385,42 @@
     1.4          status = PgGetGraphicsHWCaps(&hwcaps);
     1.5          if (status != 0) {
     1.6              PhRect_t extent;
     1.7 -            PdOffscreenContext_t *curctx;
     1.8 +            PdOffscreenContext_t* curctx;
     1.9  
    1.10              /* If error happens, this also could mean, that photon is working */
    1.11              /* under custom (not listed by photon) video mode                 */
    1.12 -            status = PhWindowQueryVisible(Ph_QUERY_GRAPHICS, 0, 0, &extent);
    1.13 +            status=PhWindowQueryVisible(Ph_QUERY_GRAPHICS, 0, 0, &extent);
    1.14              if (status != 0) {
    1.15                  SDL_SetError("Photon: Can't get graphics driver region");
    1.16                  SDL_free(didata->cursor);
    1.17                  SDL_free(didata);
    1.18                  return -1;
    1.19              }
    1.20 -            modeinfo.width = extent.lr.x + 1;
    1.21 -            modeinfo.height = extent.lr.y + 1;
    1.22 +            modeinfo.width=extent.lr.x+1;
    1.23 +            modeinfo.height=extent.lr.y+1;
    1.24              /* Hardcode 60Hz, as the base refresh rate frequency */
    1.25 -            hwcaps.current_rrate = 60;
    1.26 +            hwcaps.current_rrate=60;
    1.27              /* Clear current video driver name, no way to get it somehow */
    1.28 -            hwcaps.chip_name[0] = 0x00;
    1.29 +            hwcaps.chip_name[0]=0x00;
    1.30  
    1.31              /* Create offscreen context from video memory, which is currently */
    1.32              /* displayed on the screen                                        */
    1.33 -            curctx = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY);
    1.34 -            if (curctx == NULL) {
    1.35 +            curctx=PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY);
    1.36 +            if (curctx==NULL)
    1.37 +            {
    1.38                  SDL_SetError("Photon: Can't get display area capabilities");
    1.39                  SDL_free(didata->cursor);
    1.40                  SDL_free(didata);
    1.41                  return -1;
    1.42              }
    1.43              /* Retrieve current bpp */
    1.44 -            modeinfo.type = curctx->format;
    1.45 +            modeinfo.type=curctx->format;
    1.46              PhDCRelease(curctx);
    1.47          } else {
    1.48              /* Get current video mode details */
    1.49              status = PgGetVideoModeInfo(hwcaps.current_video_mode, &modeinfo);
    1.50              if (status != 0) {
    1.51 -                SDL_SetError
    1.52 -                    ("Photon: Can't get current video mode information");
    1.53 +                SDL_SetError("Photon: Can't get current video mode information");
    1.54                  SDL_free(didata->cursor);
    1.55                  SDL_free(didata);
    1.56                  return -1;
    1.57 @@ -1243,6 +1243,12 @@
    1.58  
    1.59  #if defined(SDL_VIDEO_OPENGL_ES)
    1.60          if (phdata->gfinitialized == SDL_TRUE) {
    1.61 +            /* Destroy photon handle to GF surface */
    1.62 +            if (wdata->phsurface != NULL) {
    1.63 +                PhDCRelease(wdata->phsurface);
    1.64 +                wdata->phsurface=NULL;
    1.65 +            }
    1.66 +
    1.67              /* Destroy OpenGL ES surface if it was created */
    1.68              if (wdata->gles_surface != EGL_NO_SURFACE) {
    1.69                  eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
    1.70 @@ -1670,13 +1676,22 @@
    1.71          return NULL;
    1.72      }
    1.73  
    1.74 +    /* Store last used context and surface */
    1.75 +    phdata->lgles_surface=wdata->gles_surface;
    1.76 +    phdata->lgles_context=wdata->gles_context;
    1.77 +
    1.78      /* Make just created context current */
    1.79      status =
    1.80          eglMakeCurrent(phdata->egldisplay, wdata->gles_surface,
    1.81                         wdata->gles_surface, wdata->gles_context);
    1.82      if (status != EGL_TRUE) {
    1.83 +        /* Reset last used context and surface */
    1.84 +        phdata->lgles_surface=EGL_NO_SURFACE;
    1.85 +        phdata->lgles_context=EGL_NO_CONTEXT;
    1.86 +
    1.87          /* Destroy OpenGL ES surface */
    1.88          eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
    1.89 +        wdata->gles_surface=EGL_NO_SURFACE;
    1.90          gf_surface_free(wdata->gfsurface);
    1.91          eglDestroyContext(phdata->egldisplay, wdata->gles_context);
    1.92          wdata->gles_context = EGL_NO_CONTEXT;
    1.93 @@ -1739,6 +1754,7 @@
    1.94          if (status != 0) {
    1.95              /* Destroy OpenGL ES surface */
    1.96              eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
    1.97 +            wdata->gles_surface=EGL_NO_SURFACE;
    1.98              gf_surface_free(wdata->gfsurface);
    1.99              eglDestroyContext(phdata->egldisplay, wdata->gles_context);
   1.100              wdata->gles_context = EGL_NO_CONTEXT;
   1.101 @@ -1752,6 +1768,7 @@
   1.102      if (wdata->phsurface == NULL) {
   1.103          /* Destroy OpenGL ES surface */
   1.104          eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
   1.105 +        wdata->gles_surface=EGL_NO_SURFACE;
   1.106          gf_surface_free(wdata->gfsurface);
   1.107          eglDestroyContext(phdata->egldisplay, wdata->gles_context);
   1.108          wdata->gles_context = EGL_NO_CONTEXT;
   1.109 @@ -1782,12 +1799,17 @@
   1.110      }
   1.111  
   1.112      if ((window == NULL) && (context == NULL)) {
   1.113 +        /* Reset last used context and surface */
   1.114 +        phdata->lgles_surface=EGL_NO_SURFACE;
   1.115 +        phdata->lgles_context=EGL_NO_CONTEXT;
   1.116 +
   1.117 +        /* Unset current context */
   1.118          status =
   1.119              eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
   1.120                             EGL_NO_CONTEXT);
   1.121          if (status != EGL_TRUE) {
   1.122              /* Failed to set current GL ES context */
   1.123 -            SDL_SetError("Photon: Can't set OpenGL ES context");
   1.124 +            SDL_SetError("Photon: Can't empty current OpenGL ES context");
   1.125              return -1;
   1.126          }
   1.127      } else {
   1.128 @@ -1807,10 +1829,19 @@
   1.129                  ("Photon: OpenGL ES context is not belong to this window");
   1.130              return -1;
   1.131          }
   1.132 +
   1.133 +        /* Store last set surface and context */
   1.134 +        phdata->lgles_surface=wdata->gles_surface;
   1.135 +        phdata->lgles_context=wdata->gles_context;
   1.136 +
   1.137 +        /* Set new current context */
   1.138          status =
   1.139              eglMakeCurrent(phdata->egldisplay, wdata->gles_surface,
   1.140                             wdata->gles_surface, wdata->gles_context);
   1.141          if (status != EGL_TRUE) {
   1.142 +            /* Reset last used context and surface */
   1.143 +            phdata->lgles_surface=EGL_NO_SURFACE;
   1.144 +            phdata->lgles_context=EGL_NO_CONTEXT;
   1.145              /* Failed to set current GL ES context */
   1.146              SDL_SetError("Photon: Can't set OpenGL ES context");
   1.147              return -1;
   1.148 @@ -1894,6 +1925,12 @@
   1.149          return;
   1.150      }
   1.151  
   1.152 +    if (wdata->phsurface==NULL) {
   1.153 +        SDL_SetError
   1.154 +            ("Photon: Photon OpenGL ES surface is not initialized");
   1.155 +        return;
   1.156 +    }
   1.157 +
   1.158      /* Many applications do not uses glFinish(), so we call it for them */
   1.159      glFinish();
   1.160  
   1.161 @@ -1945,6 +1982,13 @@
   1.162      /* Check if OpenGL ES connection has been initialized */
   1.163      if (phdata->egldisplay != EGL_NO_DISPLAY) {
   1.164          if (context != EGL_NO_CONTEXT) {
   1.165 +            /* Check if we are destroying current active context */
   1.166 +            if (phdata->lgles_context==context) {
   1.167 +                /* Release current context */
   1.168 +                eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   1.169 +                phdata->lgles_context=EGL_NO_CONTEXT;
   1.170 +                phdata->lgles_surface=EGL_NO_SURFACE;
   1.171 +            }
   1.172              status = eglDestroyContext(phdata->egldisplay, context);
   1.173              if (status != EGL_TRUE) {
   1.174                  /* Error during OpenGL ES context destroying */
   1.175 @@ -1961,6 +2005,104 @@
   1.176  #endif /* SDL_VIDEO_OPENGL_ES */
   1.177  }
   1.178  
   1.179 +/* Helper function, which re-creates surface, not an API */
   1.180 +int photon_gl_recreatesurface(_THIS, SDL_Window * window, uint32_t width, uint32_t height)
   1.181 +{
   1.182 +#if defined(SDL_VIDEO_OPENGL_ES)
   1.183 +    SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
   1.184 +    SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
   1.185 +    SDL_DisplayData *didata =
   1.186 +        (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
   1.187 +    SDL_bool makecurrent=SDL_FALSE;
   1.188 +    int32_t gfstatus;
   1.189 +
   1.190 +    /* Check if context has been initialized */
   1.191 +    if (wdata->gles_context == EGL_NO_CONTEXT) {
   1.192 +        /* If no, abort surface re-creating */
   1.193 +        return -1;
   1.194 +    }
   1.195 +
   1.196 +    /* Check if last used surface the same as one which must be re-created */
   1.197 +    if (phdata->lgles_surface == wdata->gles_surface) {
   1.198 +        makecurrent=SDL_TRUE;
   1.199 +        /* Flush all current drawings */
   1.200 +        glFinish();
   1.201 +        /* Wait until OpenGL ES rendering is completed */
   1.202 +        eglWaitGL();
   1.203 +        /* Release current context */
   1.204 +        eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   1.205 +        phdata->lgles_surface=EGL_NO_SURFACE;
   1.206 +    }
   1.207 +
   1.208 +    /* Check if we need to destroy previous surface */
   1.209 +    if (wdata->gles_surface != EGL_NO_SURFACE) {
   1.210 +        /* Destroy photon handle to GF surface */
   1.211 +        if (wdata->phsurface != NULL) {
   1.212 +            PhDCRelease(wdata->phsurface);
   1.213 +            wdata->phsurface=NULL;
   1.214 +        }
   1.215 +
   1.216 +        /* Destroy previous surface */
   1.217 +        eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
   1.218 +
   1.219 +        /* Set surface to uninitialized */
   1.220 +        wdata->gles_surface = EGL_NO_SURFACE;
   1.221 +
   1.222 +        if (wdata->gfsurface!=NULL) {
   1.223 +           gf_surface_free(wdata->gfsurface);
   1.224 +           wdata->gfsurface=NULL;
   1.225 +        }
   1.226 +    }
   1.227 +
   1.228 +    /* Create new GF surface */
   1.229 +    gfstatus =
   1.230 +        gf_surface_create(&wdata->gfsurface, phdata->gfdev, width,
   1.231 +                          height,
   1.232 +                          qnxgf_sdl_to_gf_pixelformat(didata->current_mode.
   1.233 +                                                      format), NULL,
   1.234 +                          GF_SURFACE_CREATE_2D_ACCESSIBLE |
   1.235 +                          GF_SURFACE_CREATE_3D_ACCESSIBLE |
   1.236 +                          GF_SURFACE_CREATE_SHAREABLE);
   1.237 +    if (gfstatus != GF_ERR_OK) {
   1.238 +        SDL_SetError("Photon: Can't create GF 3D surface (%08X)", gfstatus);
   1.239 +        return -1;
   1.240 +    }
   1.241 +
   1.242 +    /* Create new pixmap 3D target surface */
   1.243 +    wdata->gles_surface =
   1.244 +        eglCreatePixmapSurface(phdata->egldisplay,
   1.245 +                               wdata->gles_configs[wdata->gles_config],
   1.246 +                               wdata->gfsurface, NULL);
   1.247 +    if (wdata->gles_surface == EGL_NO_SURFACE) {
   1.248 +        gf_surface_free(wdata->gfsurface);
   1.249 +        wdata->gfsurface=NULL;
   1.250 +        SDL_SetError("Photon: Can't create EGL pixmap surface");
   1.251 +        return -1;
   1.252 +    }
   1.253 +
   1.254 +    wdata->phsurface = PdCreateOffscreenContextGF(wdata->gfsurface);
   1.255 +    if (wdata->phsurface == NULL) {
   1.256 +        /* Destroy OpenGL ES surface */
   1.257 +        eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
   1.258 +        wdata->gles_surface=EGL_NO_SURFACE;
   1.259 +        gf_surface_free(wdata->gfsurface);
   1.260 +        wdata->gfsurface=NULL;
   1.261 +        SDL_SetError("Photon: Can't bind GF surface to Photon\n");
   1.262 +        return -1;
   1.263 +    }
   1.264 +
   1.265 +    /* Check if we need to set this surface and context as current */
   1.266 +    if (makecurrent == SDL_TRUE) {
   1.267 +        return photon_gl_makecurrent(_this, window, wdata->gles_context);
   1.268 +    } else {
   1.269 +        return 0;
   1.270 +    }
   1.271 +#else
   1.272 +    /* Do nothing, if OpenGL ES support is not compiled in */
   1.273 +    return 0;
   1.274 +#endif /* SDL_VIDEO_OPENGL_ES */
   1.275 +}
   1.276 +
   1.277  /*****************************************************************************/
   1.278  /* SDL Event handling function                                               */
   1.279  /*****************************************************************************/
   1.280 @@ -2519,6 +2661,13 @@
   1.281                                                          SDL_WINDOWEVENT_MOVED,
   1.282                                                          wmevent->pos.x,
   1.283                                                          wmevent->pos.y);
   1.284 +
   1.285 +                                    /* Check if this window uses OpenGL ES */
   1.286 +                                    if (wdata->uses_gles == SDL_TRUE) {
   1.287 +                                        /* If so, recreate surface with new dimensions */
   1.288 +                                        photon_gl_recreatesurface(_this, window, wmevent->size.w, wmevent->size.h);
   1.289 +                                    }
   1.290 +
   1.291                                      /* Set new window size after resize */
   1.292                                      SDL_SendWindowEvent(window->id,
   1.293                                                          SDL_WINDOWEVENT_RESIZED,
     2.1 --- a/src/video/photon/SDL_photon.h	Wed Jun 10 18:32:42 2009 +0000
     2.2 +++ b/src/video/photon/SDL_photon.h	Thu Jun 11 05:57:32 2009 +0000
     2.3 @@ -55,7 +55,9 @@
     2.4      EGLDisplay egldisplay;      /* OpenGL ES display connection         */
     2.5      uint32_t egl_refcount;      /* OpenGL ES reference count            */
     2.6      uint32_t swapinterval;      /* OpenGL ES default swap interval      */
     2.7 -#endif                          /* SDL_VIDEO_OPENGL_ES */
     2.8 +    EGLContext lgles_context;   /* Last used OpenGL ES context          */
     2.9 +    EGLSurface lgles_surface;   /* Last used OpenGL ES target surface   */
    2.10 +#endif /* SDL_VIDEO_OPENGL_ES */
    2.11  } SDL_VideoData;
    2.12  
    2.13  /* This is hardcoded value in photon/Pg.h */
    2.14 @@ -68,18 +70,18 @@
    2.15  typedef struct SDL_DisplayData
    2.16  {
    2.17      uint32_t device_id;
    2.18 -    uint32_t custom_refresh;    /* Custom refresh rate for all modes  */
    2.19 +    uint32_t custom_refresh;            /* Custom refresh rate for all modes  */
    2.20      SDL_DisplayMode current_mode;       /* Current video mode                 */
    2.21      uint8_t description[SDL_VIDEO_PHOTON_DEVICENAME_MAX];
    2.22 -    /* Device description                 */
    2.23 -    uint32_t caps;              /* Device capabilities                */
    2.24 -    PhCursorDef_t *cursor;      /* Global cursor settings             */
    2.25 -    SDL_bool cursor_visible;    /* SDL_TRUE if cursor visible         */
    2.26 -    uint32_t cursor_size;       /* Cursor size in memory w/ structure */
    2.27 +    /* Device description */
    2.28 +    uint32_t caps;                      /* Device capabilities                */
    2.29 +    PhCursorDef_t *cursor;              /* Global cursor settings             */
    2.30 +    SDL_bool cursor_visible;            /* SDL_TRUE if cursor visible         */
    2.31 +    uint32_t cursor_size;               /* Cursor size in memory w/ structure */
    2.32  #if defined(SDL_VIDEO_OPENGL_ES)
    2.33 -    gf_display_t display;       /* GF display handle                  */
    2.34 +    gf_display_t display;               /* GF display handle                  */
    2.35      gf_display_info_t display_info;     /* GF display information             */
    2.36 -#endif                          /* SDL_VIDEO_OPENGL_ES */
    2.37 +#endif /* SDL_VIDEO_OPENGL_ES */
    2.38  } SDL_DisplayData;
    2.39  
    2.40  /* Maximum amount of OpenGL ES framebuffer configurations */
    2.41 @@ -88,17 +90,17 @@
    2.42  typedef struct SDL_WindowData
    2.43  {
    2.44      SDL_bool uses_gles;         /* if true window must support OpenGL ES */
    2.45 -    PtWidget_t *window;         /* window handle                        */
    2.46 +    PtWidget_t *window;         /* window handle                         */
    2.47  #if defined(SDL_VIDEO_OPENGL_ES)
    2.48      EGLConfig gles_configs[SDL_VIDEO_GF_OPENGLES_CONFS];
    2.49 -    /* OpenGL ES framebuffer confs        */
    2.50 -    EGLint gles_config;         /* OpenGL ES configuration index      */
    2.51 -    EGLContext gles_context;    /* OpenGL ES context                  */
    2.52 +    /* OpenGL ES framebuffer confs */
    2.53 +    EGLint gles_config;                 /* OpenGL ES configuration index      */
    2.54 +    EGLContext gles_context;            /* OpenGL ES context                  */
    2.55      EGLint gles_attributes[256];        /* OpenGL ES attributes for context   */
    2.56 -    EGLSurface gles_surface;    /* OpenGL ES target rendering surface */
    2.57 -    gf_surface_t gfsurface;     /* OpenGL ES GF's surface             */
    2.58 +    EGLSurface gles_surface;            /* OpenGL ES target rendering surface */
    2.59 +    gf_surface_t gfsurface;             /* OpenGL ES GF's surface             */
    2.60      PdOffscreenContext_t *phsurface;    /* OpenGL ES Photon's surface         */
    2.61 -#endif                          /* SDL_VIDEO_OPENGL_ES */
    2.62 +#endif /* SDL_VIDEO_OPENGL_ES */
    2.63  } SDL_WindowData;
    2.64  
    2.65  /****************************************************************************/
    2.66 @@ -158,6 +160,9 @@
    2.67  void photon_gl_swapwindow(_THIS, SDL_Window * window);
    2.68  void photon_gl_deletecontext(_THIS, SDL_GLContext context);
    2.69  
    2.70 +/* Helper function, which re-creates surface, not an API */
    2.71 +int photon_gl_recreatesurface(_THIS, SDL_Window * window, uint32_t width, uint32_t height);
    2.72 +
    2.73  /* Event handling function */
    2.74  void photon_pumpevents(_THIS);
    2.75