# HG changeset patch # User Mike Gorchak # Date 1244699852 0 # Node ID 64e4442676a6ecd2c21ab136b6792e7b175329d2 # Parent ec126b077b962532797405957de5337a024f2a44 Fixed problems with OpenGL ES window resizing. diff -r ec126b077b96 -r 64e4442676a6 src/video/photon/SDL_photon.c --- a/src/video/photon/SDL_photon.c Wed Jun 10 18:32:42 2009 +0000 +++ b/src/video/photon/SDL_photon.c Thu Jun 11 05:57:32 2009 +0000 @@ -385,42 +385,42 @@ status = PgGetGraphicsHWCaps(&hwcaps); if (status != 0) { PhRect_t extent; - PdOffscreenContext_t *curctx; + PdOffscreenContext_t* curctx; /* If error happens, this also could mean, that photon is working */ /* under custom (not listed by photon) video mode */ - status = PhWindowQueryVisible(Ph_QUERY_GRAPHICS, 0, 0, &extent); + status=PhWindowQueryVisible(Ph_QUERY_GRAPHICS, 0, 0, &extent); if (status != 0) { SDL_SetError("Photon: Can't get graphics driver region"); SDL_free(didata->cursor); SDL_free(didata); return -1; } - modeinfo.width = extent.lr.x + 1; - modeinfo.height = extent.lr.y + 1; + modeinfo.width=extent.lr.x+1; + modeinfo.height=extent.lr.y+1; /* Hardcode 60Hz, as the base refresh rate frequency */ - hwcaps.current_rrate = 60; + hwcaps.current_rrate=60; /* Clear current video driver name, no way to get it somehow */ - hwcaps.chip_name[0] = 0x00; + hwcaps.chip_name[0]=0x00; /* Create offscreen context from video memory, which is currently */ /* displayed on the screen */ - curctx = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY); - if (curctx == NULL) { + curctx=PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY); + if (curctx==NULL) + { SDL_SetError("Photon: Can't get display area capabilities"); SDL_free(didata->cursor); SDL_free(didata); return -1; } /* Retrieve current bpp */ - modeinfo.type = curctx->format; + modeinfo.type=curctx->format; PhDCRelease(curctx); } else { /* Get current video mode details */ status = PgGetVideoModeInfo(hwcaps.current_video_mode, &modeinfo); if (status != 0) { - SDL_SetError - ("Photon: Can't get current video mode information"); + SDL_SetError("Photon: Can't get current video mode information"); SDL_free(didata->cursor); SDL_free(didata); return -1; @@ -1243,6 +1243,12 @@ #if defined(SDL_VIDEO_OPENGL_ES) if (phdata->gfinitialized == SDL_TRUE) { + /* Destroy photon handle to GF surface */ + if (wdata->phsurface != NULL) { + PhDCRelease(wdata->phsurface); + wdata->phsurface=NULL; + } + /* Destroy OpenGL ES surface if it was created */ if (wdata->gles_surface != EGL_NO_SURFACE) { eglDestroySurface(phdata->egldisplay, wdata->gles_surface); @@ -1670,13 +1676,22 @@ return NULL; } + /* Store last used context and surface */ + phdata->lgles_surface=wdata->gles_surface; + phdata->lgles_context=wdata->gles_context; + /* Make just created context current */ status = eglMakeCurrent(phdata->egldisplay, wdata->gles_surface, wdata->gles_surface, wdata->gles_context); if (status != EGL_TRUE) { + /* Reset last used context and surface */ + phdata->lgles_surface=EGL_NO_SURFACE; + phdata->lgles_context=EGL_NO_CONTEXT; + /* Destroy OpenGL ES surface */ eglDestroySurface(phdata->egldisplay, wdata->gles_surface); + wdata->gles_surface=EGL_NO_SURFACE; gf_surface_free(wdata->gfsurface); eglDestroyContext(phdata->egldisplay, wdata->gles_context); wdata->gles_context = EGL_NO_CONTEXT; @@ -1739,6 +1754,7 @@ if (status != 0) { /* Destroy OpenGL ES surface */ eglDestroySurface(phdata->egldisplay, wdata->gles_surface); + wdata->gles_surface=EGL_NO_SURFACE; gf_surface_free(wdata->gfsurface); eglDestroyContext(phdata->egldisplay, wdata->gles_context); wdata->gles_context = EGL_NO_CONTEXT; @@ -1752,6 +1768,7 @@ if (wdata->phsurface == NULL) { /* Destroy OpenGL ES surface */ eglDestroySurface(phdata->egldisplay, wdata->gles_surface); + wdata->gles_surface=EGL_NO_SURFACE; gf_surface_free(wdata->gfsurface); eglDestroyContext(phdata->egldisplay, wdata->gles_context); wdata->gles_context = EGL_NO_CONTEXT; @@ -1782,12 +1799,17 @@ } if ((window == NULL) && (context == NULL)) { + /* Reset last used context and surface */ + phdata->lgles_surface=EGL_NO_SURFACE; + phdata->lgles_context=EGL_NO_CONTEXT; + + /* Unset current context */ status = eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (status != EGL_TRUE) { /* Failed to set current GL ES context */ - SDL_SetError("Photon: Can't set OpenGL ES context"); + SDL_SetError("Photon: Can't empty current OpenGL ES context"); return -1; } } else { @@ -1807,10 +1829,19 @@ ("Photon: OpenGL ES context is not belong to this window"); return -1; } + + /* Store last set surface and context */ + phdata->lgles_surface=wdata->gles_surface; + phdata->lgles_context=wdata->gles_context; + + /* Set new current context */ status = eglMakeCurrent(phdata->egldisplay, wdata->gles_surface, wdata->gles_surface, wdata->gles_context); if (status != EGL_TRUE) { + /* Reset last used context and surface */ + phdata->lgles_surface=EGL_NO_SURFACE; + phdata->lgles_context=EGL_NO_CONTEXT; /* Failed to set current GL ES context */ SDL_SetError("Photon: Can't set OpenGL ES context"); return -1; @@ -1894,6 +1925,12 @@ return; } + if (wdata->phsurface==NULL) { + SDL_SetError + ("Photon: Photon OpenGL ES surface is not initialized"); + return; + } + /* Many applications do not uses glFinish(), so we call it for them */ glFinish(); @@ -1945,6 +1982,13 @@ /* Check if OpenGL ES connection has been initialized */ if (phdata->egldisplay != EGL_NO_DISPLAY) { if (context != EGL_NO_CONTEXT) { + /* Check if we are destroying current active context */ + if (phdata->lgles_context==context) { + /* Release current context */ + eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + phdata->lgles_context=EGL_NO_CONTEXT; + phdata->lgles_surface=EGL_NO_SURFACE; + } status = eglDestroyContext(phdata->egldisplay, context); if (status != EGL_TRUE) { /* Error during OpenGL ES context destroying */ @@ -1961,6 +2005,104 @@ #endif /* SDL_VIDEO_OPENGL_ES */ } +/* Helper function, which re-creates surface, not an API */ +int photon_gl_recreatesurface(_THIS, SDL_Window * window, uint32_t width, uint32_t height) +{ +#if defined(SDL_VIDEO_OPENGL_ES) + SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata; + SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata; + SDL_DisplayData *didata = + (SDL_DisplayData *) SDL_CurrentDisplay.driverdata; + SDL_bool makecurrent=SDL_FALSE; + int32_t gfstatus; + + /* Check if context has been initialized */ + if (wdata->gles_context == EGL_NO_CONTEXT) { + /* If no, abort surface re-creating */ + return -1; + } + + /* Check if last used surface the same as one which must be re-created */ + if (phdata->lgles_surface == wdata->gles_surface) { + makecurrent=SDL_TRUE; + /* Flush all current drawings */ + glFinish(); + /* Wait until OpenGL ES rendering is completed */ + eglWaitGL(); + /* Release current context */ + eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + phdata->lgles_surface=EGL_NO_SURFACE; + } + + /* Check if we need to destroy previous surface */ + if (wdata->gles_surface != EGL_NO_SURFACE) { + /* Destroy photon handle to GF surface */ + if (wdata->phsurface != NULL) { + PhDCRelease(wdata->phsurface); + wdata->phsurface=NULL; + } + + /* Destroy previous surface */ + eglDestroySurface(phdata->egldisplay, wdata->gles_surface); + + /* Set surface to uninitialized */ + wdata->gles_surface = EGL_NO_SURFACE; + + if (wdata->gfsurface!=NULL) { + gf_surface_free(wdata->gfsurface); + wdata->gfsurface=NULL; + } + } + + /* Create new GF surface */ + gfstatus = + gf_surface_create(&wdata->gfsurface, phdata->gfdev, width, + height, + qnxgf_sdl_to_gf_pixelformat(didata->current_mode. + format), NULL, + GF_SURFACE_CREATE_2D_ACCESSIBLE | + GF_SURFACE_CREATE_3D_ACCESSIBLE | + GF_SURFACE_CREATE_SHAREABLE); + if (gfstatus != GF_ERR_OK) { + SDL_SetError("Photon: Can't create GF 3D surface (%08X)", gfstatus); + return -1; + } + + /* Create new pixmap 3D target surface */ + wdata->gles_surface = + eglCreatePixmapSurface(phdata->egldisplay, + wdata->gles_configs[wdata->gles_config], + wdata->gfsurface, NULL); + if (wdata->gles_surface == EGL_NO_SURFACE) { + gf_surface_free(wdata->gfsurface); + wdata->gfsurface=NULL; + SDL_SetError("Photon: Can't create EGL pixmap surface"); + return -1; + } + + wdata->phsurface = PdCreateOffscreenContextGF(wdata->gfsurface); + if (wdata->phsurface == NULL) { + /* Destroy OpenGL ES surface */ + eglDestroySurface(phdata->egldisplay, wdata->gles_surface); + wdata->gles_surface=EGL_NO_SURFACE; + gf_surface_free(wdata->gfsurface); + wdata->gfsurface=NULL; + SDL_SetError("Photon: Can't bind GF surface to Photon\n"); + return -1; + } + + /* Check if we need to set this surface and context as current */ + if (makecurrent == SDL_TRUE) { + return photon_gl_makecurrent(_this, window, wdata->gles_context); + } else { + return 0; + } +#else + /* Do nothing, if OpenGL ES support is not compiled in */ + return 0; +#endif /* SDL_VIDEO_OPENGL_ES */ +} + /*****************************************************************************/ /* SDL Event handling function */ /*****************************************************************************/ @@ -2519,6 +2661,13 @@ SDL_WINDOWEVENT_MOVED, wmevent->pos.x, wmevent->pos.y); + + /* Check if this window uses OpenGL ES */ + if (wdata->uses_gles == SDL_TRUE) { + /* If so, recreate surface with new dimensions */ + photon_gl_recreatesurface(_this, window, wmevent->size.w, wmevent->size.h); + } + /* Set new window size after resize */ SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_RESIZED, diff -r ec126b077b96 -r 64e4442676a6 src/video/photon/SDL_photon.h --- a/src/video/photon/SDL_photon.h Wed Jun 10 18:32:42 2009 +0000 +++ b/src/video/photon/SDL_photon.h Thu Jun 11 05:57:32 2009 +0000 @@ -55,7 +55,9 @@ EGLDisplay egldisplay; /* OpenGL ES display connection */ uint32_t egl_refcount; /* OpenGL ES reference count */ uint32_t swapinterval; /* OpenGL ES default swap interval */ -#endif /* SDL_VIDEO_OPENGL_ES */ + EGLContext lgles_context; /* Last used OpenGL ES context */ + EGLSurface lgles_surface; /* Last used OpenGL ES target surface */ +#endif /* SDL_VIDEO_OPENGL_ES */ } SDL_VideoData; /* This is hardcoded value in photon/Pg.h */ @@ -68,18 +70,18 @@ typedef struct SDL_DisplayData { uint32_t device_id; - uint32_t custom_refresh; /* Custom refresh rate for all modes */ + uint32_t custom_refresh; /* Custom refresh rate for all modes */ SDL_DisplayMode current_mode; /* Current video mode */ uint8_t description[SDL_VIDEO_PHOTON_DEVICENAME_MAX]; - /* Device description */ - uint32_t caps; /* Device capabilities */ - PhCursorDef_t *cursor; /* Global cursor settings */ - SDL_bool cursor_visible; /* SDL_TRUE if cursor visible */ - uint32_t cursor_size; /* Cursor size in memory w/ structure */ + /* Device description */ + uint32_t caps; /* Device capabilities */ + PhCursorDef_t *cursor; /* Global cursor settings */ + SDL_bool cursor_visible; /* SDL_TRUE if cursor visible */ + uint32_t cursor_size; /* Cursor size in memory w/ structure */ #if defined(SDL_VIDEO_OPENGL_ES) - gf_display_t display; /* GF display handle */ + gf_display_t display; /* GF display handle */ gf_display_info_t display_info; /* GF display information */ -#endif /* SDL_VIDEO_OPENGL_ES */ +#endif /* SDL_VIDEO_OPENGL_ES */ } SDL_DisplayData; /* Maximum amount of OpenGL ES framebuffer configurations */ @@ -88,17 +90,17 @@ typedef struct SDL_WindowData { SDL_bool uses_gles; /* if true window must support OpenGL ES */ - PtWidget_t *window; /* window handle */ + PtWidget_t *window; /* window handle */ #if defined(SDL_VIDEO_OPENGL_ES) EGLConfig gles_configs[SDL_VIDEO_GF_OPENGLES_CONFS]; - /* OpenGL ES framebuffer confs */ - EGLint gles_config; /* OpenGL ES configuration index */ - EGLContext gles_context; /* OpenGL ES context */ + /* OpenGL ES framebuffer confs */ + EGLint gles_config; /* OpenGL ES configuration index */ + EGLContext gles_context; /* OpenGL ES context */ EGLint gles_attributes[256]; /* OpenGL ES attributes for context */ - EGLSurface gles_surface; /* OpenGL ES target rendering surface */ - gf_surface_t gfsurface; /* OpenGL ES GF's surface */ + EGLSurface gles_surface; /* OpenGL ES target rendering surface */ + gf_surface_t gfsurface; /* OpenGL ES GF's surface */ PdOffscreenContext_t *phsurface; /* OpenGL ES Photon's surface */ -#endif /* SDL_VIDEO_OPENGL_ES */ +#endif /* SDL_VIDEO_OPENGL_ES */ } SDL_WindowData; /****************************************************************************/ @@ -158,6 +160,9 @@ void photon_gl_swapwindow(_THIS, SDL_Window * window); void photon_gl_deletecontext(_THIS, SDL_GLContext context); +/* Helper function, which re-creates surface, not an API */ +int photon_gl_recreatesurface(_THIS, SDL_Window * window, uint32_t width, uint32_t height); + /* Event handling function */ void photon_pumpevents(_THIS);