Commit 83ca32e5 authored by Mike Gorchak's avatar Mike Gorchak

Fixed problems with OpenGL ES window resizing.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403652
parent b099397c
...@@ -385,42 +385,42 @@ photon_videoinit(_THIS) ...@@ -385,42 +385,42 @@ photon_videoinit(_THIS)
status = PgGetGraphicsHWCaps(&hwcaps); status = PgGetGraphicsHWCaps(&hwcaps);
if (status != 0) { if (status != 0) {
PhRect_t extent; PhRect_t extent;
PdOffscreenContext_t *curctx; PdOffscreenContext_t* curctx;
/* If error happens, this also could mean, that photon is working */ /* If error happens, this also could mean, that photon is working */
/* under custom (not listed by photon) video mode */ /* 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) { if (status != 0) {
SDL_SetError("Photon: Can't get graphics driver region"); SDL_SetError("Photon: Can't get graphics driver region");
SDL_free(didata->cursor); SDL_free(didata->cursor);
SDL_free(didata); SDL_free(didata);
return -1; return -1;
} }
modeinfo.width = extent.lr.x + 1; modeinfo.width=extent.lr.x+1;
modeinfo.height = extent.lr.y + 1; modeinfo.height=extent.lr.y+1;
/* Hardcode 60Hz, as the base refresh rate frequency */ /* 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 */ /* 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 */ /* Create offscreen context from video memory, which is currently */
/* displayed on the screen */ /* displayed on the screen */
curctx = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY); curctx=PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY);
if (curctx == NULL) { if (curctx==NULL)
{
SDL_SetError("Photon: Can't get display area capabilities"); SDL_SetError("Photon: Can't get display area capabilities");
SDL_free(didata->cursor); SDL_free(didata->cursor);
SDL_free(didata); SDL_free(didata);
return -1; return -1;
} }
/* Retrieve current bpp */ /* Retrieve current bpp */
modeinfo.type = curctx->format; modeinfo.type=curctx->format;
PhDCRelease(curctx); PhDCRelease(curctx);
} else { } else {
/* Get current video mode details */ /* Get current video mode details */
status = PgGetVideoModeInfo(hwcaps.current_video_mode, &modeinfo); status = PgGetVideoModeInfo(hwcaps.current_video_mode, &modeinfo);
if (status != 0) { if (status != 0) {
SDL_SetError SDL_SetError("Photon: Can't get current video mode information");
("Photon: Can't get current video mode information");
SDL_free(didata->cursor); SDL_free(didata->cursor);
SDL_free(didata); SDL_free(didata);
return -1; return -1;
...@@ -1243,6 +1243,12 @@ photon_destroywindow(_THIS, SDL_Window * window) ...@@ -1243,6 +1243,12 @@ photon_destroywindow(_THIS, SDL_Window * window)
#if defined(SDL_VIDEO_OPENGL_ES) #if defined(SDL_VIDEO_OPENGL_ES)
if (phdata->gfinitialized == SDL_TRUE) { 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 */ /* Destroy OpenGL ES surface if it was created */
if (wdata->gles_surface != EGL_NO_SURFACE) { if (wdata->gles_surface != EGL_NO_SURFACE) {
eglDestroySurface(phdata->egldisplay, wdata->gles_surface); eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
...@@ -1670,13 +1676,22 @@ photon_gl_createcontext(_THIS, SDL_Window * window) ...@@ -1670,13 +1676,22 @@ photon_gl_createcontext(_THIS, SDL_Window * window)
return NULL; 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 */ /* Make just created context current */
status = status =
eglMakeCurrent(phdata->egldisplay, wdata->gles_surface, eglMakeCurrent(phdata->egldisplay, wdata->gles_surface,
wdata->gles_surface, wdata->gles_context); wdata->gles_surface, wdata->gles_context);
if (status != EGL_TRUE) { 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 */ /* Destroy OpenGL ES surface */
eglDestroySurface(phdata->egldisplay, wdata->gles_surface); eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
wdata->gles_surface=EGL_NO_SURFACE;
gf_surface_free(wdata->gfsurface); gf_surface_free(wdata->gfsurface);
eglDestroyContext(phdata->egldisplay, wdata->gles_context); eglDestroyContext(phdata->egldisplay, wdata->gles_context);
wdata->gles_context = EGL_NO_CONTEXT; wdata->gles_context = EGL_NO_CONTEXT;
...@@ -1739,6 +1754,7 @@ photon_gl_createcontext(_THIS, SDL_Window * window) ...@@ -1739,6 +1754,7 @@ photon_gl_createcontext(_THIS, SDL_Window * window)
if (status != 0) { if (status != 0) {
/* Destroy OpenGL ES surface */ /* Destroy OpenGL ES surface */
eglDestroySurface(phdata->egldisplay, wdata->gles_surface); eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
wdata->gles_surface=EGL_NO_SURFACE;
gf_surface_free(wdata->gfsurface); gf_surface_free(wdata->gfsurface);
eglDestroyContext(phdata->egldisplay, wdata->gles_context); eglDestroyContext(phdata->egldisplay, wdata->gles_context);
wdata->gles_context = EGL_NO_CONTEXT; wdata->gles_context = EGL_NO_CONTEXT;
...@@ -1752,6 +1768,7 @@ photon_gl_createcontext(_THIS, SDL_Window * window) ...@@ -1752,6 +1768,7 @@ photon_gl_createcontext(_THIS, SDL_Window * window)
if (wdata->phsurface == NULL) { if (wdata->phsurface == NULL) {
/* Destroy OpenGL ES surface */ /* Destroy OpenGL ES surface */
eglDestroySurface(phdata->egldisplay, wdata->gles_surface); eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
wdata->gles_surface=EGL_NO_SURFACE;
gf_surface_free(wdata->gfsurface); gf_surface_free(wdata->gfsurface);
eglDestroyContext(phdata->egldisplay, wdata->gles_context); eglDestroyContext(phdata->egldisplay, wdata->gles_context);
wdata->gles_context = EGL_NO_CONTEXT; wdata->gles_context = EGL_NO_CONTEXT;
...@@ -1782,12 +1799,17 @@ photon_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context) ...@@ -1782,12 +1799,17 @@ photon_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context)
} }
if ((window == NULL) && (context == NULL)) { 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 = status =
eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT); EGL_NO_CONTEXT);
if (status != EGL_TRUE) { if (status != EGL_TRUE) {
/* Failed to set current GL ES context */ /* 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; return -1;
} }
} else { } else {
...@@ -1807,10 +1829,19 @@ photon_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context) ...@@ -1807,10 +1829,19 @@ photon_gl_makecurrent(_THIS, SDL_Window * window, SDL_GLContext context)
("Photon: OpenGL ES context is not belong to this window"); ("Photon: OpenGL ES context is not belong to this window");
return -1; 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 = status =
eglMakeCurrent(phdata->egldisplay, wdata->gles_surface, eglMakeCurrent(phdata->egldisplay, wdata->gles_surface,
wdata->gles_surface, wdata->gles_context); wdata->gles_surface, wdata->gles_context);
if (status != EGL_TRUE) { 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 */ /* Failed to set current GL ES context */
SDL_SetError("Photon: Can't set OpenGL ES context"); SDL_SetError("Photon: Can't set OpenGL ES context");
return -1; return -1;
...@@ -1894,6 +1925,12 @@ photon_gl_swapwindow(_THIS, SDL_Window * window) ...@@ -1894,6 +1925,12 @@ photon_gl_swapwindow(_THIS, SDL_Window * window)
return; 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 */ /* Many applications do not uses glFinish(), so we call it for them */
glFinish(); glFinish();
...@@ -1945,6 +1982,13 @@ photon_gl_deletecontext(_THIS, SDL_GLContext context) ...@@ -1945,6 +1982,13 @@ photon_gl_deletecontext(_THIS, SDL_GLContext context)
/* Check if OpenGL ES connection has been initialized */ /* Check if OpenGL ES connection has been initialized */
if (phdata->egldisplay != EGL_NO_DISPLAY) { if (phdata->egldisplay != EGL_NO_DISPLAY) {
if (context != EGL_NO_CONTEXT) { 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); status = eglDestroyContext(phdata->egldisplay, context);
if (status != EGL_TRUE) { if (status != EGL_TRUE) {
/* Error during OpenGL ES context destroying */ /* Error during OpenGL ES context destroying */
...@@ -1961,6 +2005,104 @@ photon_gl_deletecontext(_THIS, SDL_GLContext context) ...@@ -1961,6 +2005,104 @@ photon_gl_deletecontext(_THIS, SDL_GLContext context)
#endif /* SDL_VIDEO_OPENGL_ES */ #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 */ /* SDL Event handling function */
/*****************************************************************************/ /*****************************************************************************/
...@@ -2519,6 +2661,13 @@ photon_pumpevents(_THIS) ...@@ -2519,6 +2661,13 @@ photon_pumpevents(_THIS)
SDL_WINDOWEVENT_MOVED, SDL_WINDOWEVENT_MOVED,
wmevent->pos.x, wmevent->pos.x,
wmevent->pos.y); 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 */ /* Set new window size after resize */
SDL_SendWindowEvent(window->id, SDL_SendWindowEvent(window->id,
SDL_WINDOWEVENT_RESIZED, SDL_WINDOWEVENT_RESIZED,
......
...@@ -55,7 +55,9 @@ typedef struct SDL_VideoData ...@@ -55,7 +55,9 @@ typedef struct SDL_VideoData
EGLDisplay egldisplay; /* OpenGL ES display connection */ EGLDisplay egldisplay; /* OpenGL ES display connection */
uint32_t egl_refcount; /* OpenGL ES reference count */ uint32_t egl_refcount; /* OpenGL ES reference count */
uint32_t swapinterval; /* OpenGL ES default swap interval */ 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; } SDL_VideoData;
/* This is hardcoded value in photon/Pg.h */ /* This is hardcoded value in photon/Pg.h */
...@@ -68,18 +70,18 @@ typedef struct SDL_VideoData ...@@ -68,18 +70,18 @@ typedef struct SDL_VideoData
typedef struct SDL_DisplayData typedef struct SDL_DisplayData
{ {
uint32_t device_id; 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 */ SDL_DisplayMode current_mode; /* Current video mode */
uint8_t description[SDL_VIDEO_PHOTON_DEVICENAME_MAX]; uint8_t description[SDL_VIDEO_PHOTON_DEVICENAME_MAX];
/* Device description */ /* Device description */
uint32_t caps; /* Device capabilities */ uint32_t caps; /* Device capabilities */
PhCursorDef_t *cursor; /* Global cursor settings */ PhCursorDef_t *cursor; /* Global cursor settings */
SDL_bool cursor_visible; /* SDL_TRUE if cursor visible */ SDL_bool cursor_visible; /* SDL_TRUE if cursor visible */
uint32_t cursor_size; /* Cursor size in memory w/ structure */ uint32_t cursor_size; /* Cursor size in memory w/ structure */
#if defined(SDL_VIDEO_OPENGL_ES) #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 */ gf_display_info_t display_info; /* GF display information */
#endif /* SDL_VIDEO_OPENGL_ES */ #endif /* SDL_VIDEO_OPENGL_ES */
} SDL_DisplayData; } SDL_DisplayData;
/* Maximum amount of OpenGL ES framebuffer configurations */ /* Maximum amount of OpenGL ES framebuffer configurations */
...@@ -88,17 +90,17 @@ typedef struct SDL_DisplayData ...@@ -88,17 +90,17 @@ typedef struct SDL_DisplayData
typedef struct SDL_WindowData typedef struct SDL_WindowData
{ {
SDL_bool uses_gles; /* if true window must support OpenGL ES */ 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) #if defined(SDL_VIDEO_OPENGL_ES)
EGLConfig gles_configs[SDL_VIDEO_GF_OPENGLES_CONFS]; EGLConfig gles_configs[SDL_VIDEO_GF_OPENGLES_CONFS];
/* OpenGL ES framebuffer confs */ /* OpenGL ES framebuffer confs */
EGLint gles_config; /* OpenGL ES configuration index */ EGLint gles_config; /* OpenGL ES configuration index */
EGLContext gles_context; /* OpenGL ES context */ EGLContext gles_context; /* OpenGL ES context */
EGLint gles_attributes[256]; /* OpenGL ES attributes for context */ EGLint gles_attributes[256]; /* OpenGL ES attributes for context */
EGLSurface gles_surface; /* OpenGL ES target rendering surface */ EGLSurface gles_surface; /* OpenGL ES target rendering surface */
gf_surface_t gfsurface; /* OpenGL ES GF's surface */ gf_surface_t gfsurface; /* OpenGL ES GF's surface */
PdOffscreenContext_t *phsurface; /* OpenGL ES Photon's surface */ PdOffscreenContext_t *phsurface; /* OpenGL ES Photon's surface */
#endif /* SDL_VIDEO_OPENGL_ES */ #endif /* SDL_VIDEO_OPENGL_ES */
} SDL_WindowData; } SDL_WindowData;
/****************************************************************************/ /****************************************************************************/
...@@ -158,6 +160,9 @@ int photon_gl_getswapinterval(_THIS); ...@@ -158,6 +160,9 @@ int photon_gl_getswapinterval(_THIS);
void photon_gl_swapwindow(_THIS, SDL_Window * window); void photon_gl_swapwindow(_THIS, SDL_Window * window);
void photon_gl_deletecontext(_THIS, SDL_GLContext context); 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 */ /* Event handling function */
void photon_pumpevents(_THIS); void photon_pumpevents(_THIS);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment