[251/906] Properly clean OpenGL contexts

This commit is contained in:
Julien Isorce 2008-10-25 02:03:16 +02:00 committed by Matthew Waters
parent c330210648
commit 2c9bb405a0
7 changed files with 52 additions and 91 deletions

View file

@ -108,8 +108,6 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
display->gl_thread = NULL;
display->gl_window = NULL;
display->winId = 0;
display->win_xpos = 0;
display->win_ypos = 0;
display->visible = FALSE;
display->isAlive = TRUE;
display->texture_pool = g_hash_table_new (g_direct_hash, g_direct_equal);
@ -355,8 +353,9 @@ gst_gl_display_finalize (GObject* object)
if (display->gl_thread)
{
g_thread_join (display->gl_thread);
gpointer ret = g_thread_join (display->gl_thread);
GST_INFO ("gl thread joined");
g_assert (ret == NULL);
display->gl_thread = NULL;
}
@ -389,10 +388,6 @@ gst_gl_display_finalize (GObject* object)
//------------------ BEGIN GL THREAD ACTIONS -----------------
//------------------------------------------------------------
//The following functions are thread safe because
//called by the "gst_gl_display_thread_dispatch_action"
//in a lock/unlock scope.
/* Called in the gl thread */
gpointer
gst_gl_display_thread_create_context (GstGLDisplay *display)
@ -401,9 +396,15 @@ gst_gl_display_thread_create_context (GstGLDisplay *display)
display->gl_window = gst_gl_window_new (display->upload_width, display->upload_height);
GST_INFO ("gl window created");
if (!display->gl_window)
{
display->isAlive = FALSE;
GST_ERROR_OBJECT (display, "Failed to create gl window");
g_cond_signal (display->cond_create_context);
return NULL;
}
gst_gl_window_visible (display->gl_window, display->visible);
GST_INFO ("gl window created");
//Init glew
err = glewInit();
@ -1580,19 +1581,14 @@ gst_gl_display_new (void)
* Called by the first gl element of a video/x-raw-gl flow */
void
gst_gl_display_create_context (GstGLDisplay *display,
GLint x, GLint y,
GLint width, GLint height,
gulong winId,
gboolean visible)
gulong winId)
{
gst_gl_display_lock (display);
display->winId = winId;
display->win_xpos = x;
display->win_ypos = y;
display->upload_width = width;
display->upload_height = height;
display->visible = visible;
display->gl_thread = g_thread_create (
(GThreadFunc) gst_gl_display_thread_create_context, display, TRUE, NULL);

View file

@ -56,39 +56,6 @@ typedef enum {
GST_GL_DISPLAY_PROJECTION_PERSPECIVE
} GstGLDisplayProjection;
//Message type
typedef enum {
GST_GL_DISPLAY_ACTION_CREATE_CONTEXT,
GST_GL_DISPLAY_ACTION_DESTROY_CONTEXT,
GST_GL_DISPLAY_ACTION_CHANGE_CONTEXT,
GST_GL_DISPLAY_ACTION_VISIBLE_CONTEXT,
GST_GL_DISPLAY_ACTION_RESIZE_CONTEXT,
GST_GL_DISPLAY_ACTION_REDISPLAY_CONTEXT,
GST_GL_DISPLAY_ACTION_GENERIC,
GST_GL_DISPLAY_ACTION_GEN_TEXTURE,
GST_GL_DISPLAY_ACTION_DEL_TEXTURE,
GST_GL_DISPLAY_ACTION_INIT_UPLOAD,
GST_GL_DISPLAY_ACTION_DO_UPLOAD,
GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD,
GST_GL_DISPLAY_ACTION_DO_DOWNLOAD,
GST_GL_DISPLAY_ACTION_GEN_FBO,
GST_GL_DISPLAY_ACTION_USE_FBO,
GST_GL_DISPLAY_ACTION_DEL_FBO,
GST_GL_DISPLAY_ACTION_GEN_SHADER,
GST_GL_DISPLAY_ACTION_DEL_SHADER
} GstGLDisplayAction;
//Message to communicate with the gl thread
typedef struct _GstGLDisplayMsg {
GstGLDisplayAction action;
gint glutWinId;
GstGLDisplay* display;
} GstGLDisplayMsg;
//Texture pool elements
typedef struct _GstGLDisplayTex {
GLuint texture;
@ -114,8 +81,6 @@ struct _GstGLDisplay {
GThread* gl_thread;
GstGLWindow* gl_window;
gulong winId;
gint win_xpos;
gint win_ypos;
gboolean visible;
gboolean isAlive;
GHashTable* texture_pool;
@ -248,10 +213,8 @@ GType gst_gl_display_get_type (void);
GstGLDisplay* gst_gl_display_new (void);
void gst_gl_display_create_context (GstGLDisplay* display,
GLint x, GLint y,
GLint width, GLint height,
gulong winId,
gboolean visible);
gulong winId);
void gst_gl_display_set_visible_context (GstGLDisplay* display, gboolean visible);
void gst_gl_display_resize_context (GstGLDisplay* display, gint width, gint height);
gboolean gst_gl_display_redisplay (GstGLDisplay* display, GLuint texture, gint width, gint height);

View file

@ -96,7 +96,7 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
obj_class->finalize = gst_gl_window_finalize;
GetClassInfo ((HINSTANCE)klass->instance, "GSTGL", &wc);
atom = GetClassInfo ((HINSTANCE)klass->instance, "GSTGL", &wc);
ZeroMemory (&wc, sizeof(WNDCLASS));
@ -107,15 +107,11 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;
wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "GSTGL";
atom = RegisterClass (&wc);
g_assert (atom);
g_debug ("GSTGL window class registered\n");
}
static void
@ -138,9 +134,10 @@ gst_gl_window_new (gint width, gint height)
GstGLWindowPrivate *priv = window->priv;
GstGLWindowClass* klass = GST_GL_WINDOW_GET_CLASS (window);
static gint x = 50;
static gint x = 0;
static gint y = 0;
y = 50 + height * y++;
x += 20;
y += 20;
priv->internal_win_id = 0;
priv->external_win_id = 0;
@ -180,9 +177,13 @@ gst_gl_window_new (gint width, gint height)
UpdateWindow (priv->internal_win_id);
ShowCursor (TRUE);
wglMakeCurrent (priv->device, priv->gl_context);
return window;
if (wglMakeCurrent (priv->device, priv->gl_context))
return window;
else
{
g_debug ("Failed to make opengl context current");
return NULL;
}
}
GQuark
@ -324,7 +325,7 @@ gst_gl_window_draw (GstGLWindow *window)
BeginPaint (priv->external_win_id, &ps);
priv->draw_cb (priv->draw_data); //FIXME: wrong thread caller
//glFlush();
glFlush();
SwapBuffers (priv->device);
EndPaint (priv->external_win_id, &ps);
}
@ -386,6 +387,7 @@ gst_gl_window_quit_loop (GstGLWindow *window)
GstGLWindowPrivate *priv = window->priv;
LRESULT res = PostMessage(priv->internal_win_id, WM_CLOSE, 0, 0);
g_assert (SUCCEEDED (res));
g_debug ("end loop requested\n");
}
}
@ -451,8 +453,6 @@ gst_gl_window_set_pixel_format (GstGLWindow *window)
LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static gboolean created = FALSE;
if (uMsg == WM_CREATE) {
GstGLWindow *window = (GstGLWindow *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
@ -468,14 +468,17 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
priv->device = GetDC (hWnd);
gst_gl_window_set_pixel_format (window);
priv->gl_context = wglCreateContext (priv->device);
if (priv->gl_context)
g_debug ("gl context created: %d\n", priv->gl_context);
else
g_debug ("failed to create glcontext %d\n", hWnd);
g_assert (priv->gl_context);
ReleaseDC (hWnd, priv->device);
}
created = TRUE;
return 0;
}
else if (created) {
else if (GetWindowLongPtr(hWnd, GWLP_USERDATA)) {
GstGLWindow *window = (GstGLWindow *) (guint64) GetWindowLongPtr(hWnd, GWLP_USERDATA);
GstGLWindowPrivate *priv = NULL;
@ -486,6 +489,8 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
g_assert (priv);
g_assert (priv->internal_win_id == hWnd);
switch ( uMsg ) {
case WM_SIZE:
@ -513,14 +518,16 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
g_debug ("WM_CLOSE\n");
if (priv->close_cb)
priv->close_cb (priv->close_data);
DestroyWindow(hWnd);
break;
}
wglMakeCurrent (NULL, NULL);
case WM_DESTROY:
{
g_debug ("WM_DESTROY\n");
created = FALSE;
if (priv->gl_context)
wglDeleteContext (priv->gl_context);
if (priv->internal_win_id)
DestroyWindow(priv->internal_win_id);
SetWindowLongPtr (hWnd, GWLP_USERDATA, 0);
DestroyWindow(hWnd);
PostQuitMessage (0);
break;
}
@ -540,6 +547,9 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
break;
}
case WM_ERASEBKGND:
return TRUE;
default:
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

View file

@ -395,7 +395,6 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps,
{
GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt);
gboolean ret = FALSE;
static gint y_pos = 0;
GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps);
@ -415,9 +414,8 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps,
//init unvisible opengl context
gst_gl_display_create_context (colorscale->display,
50, y_pos++ * (colorscale->output_video_height+50) + 50,
colorscale->output_video_width, colorscale->output_video_height,
0, FALSE);
0);
//blocking call, init colorspace conversion if needed
gst_gl_display_init_upload (colorscale->display, colorscale->input_video_format,

View file

@ -519,18 +519,13 @@ gst_glimage_sink_render (GstBaseSink* bsink, GstBuffer* buf)
//if glimagesink has not the display yet
if (glimage_sink->display == NULL)
{
//do not stack when multiple windows
static gint y_pos = 0;
//create a display
glimage_sink->display = gst_gl_display_new ();
//init opengl context
gst_gl_display_create_context (glimage_sink->display,
50, y_pos++ * (glimage_sink->height+50) + 50,
glimage_sink->width, glimage_sink->height,
glimage_sink->window_id, TRUE);
glimage_sink->window_id);
//init colorspace conversion if needed
gst_gl_display_init_upload (glimage_sink->display, glimage_sink->format,
@ -544,6 +539,8 @@ gst_glimage_sink_render (GstBaseSink* bsink, GstBuffer* buf)
glimage_sink->clientDrawCallback);
gst_gl_display_resize_context (glimage_sink->display, glimage_sink->width, glimage_sink->height);
gst_gl_display_set_visible_context (glimage_sink->display, TRUE);
}
//blocking call

View file

@ -345,7 +345,6 @@ gst_gl_test_src_setcaps (GstBaseSrc* bsrc, GstCaps* caps)
gboolean res;
gint width, height, rate_denominator, rate_numerator;
GstGLTestSrc* gltestsrc;
static gint y_pos = 0;
gltestsrc = GST_GL_TEST_SRC (bsrc);
@ -369,8 +368,7 @@ gst_gl_test_src_setcaps (GstBaseSrc* bsrc, GstCaps* caps)
gltestsrc->display = gst_gl_display_new ();
gst_gl_display_create_context (gltestsrc->display,
50, y_pos++ * (gltestsrc->height+50) + 50,
gltestsrc->width, gltestsrc->height, 0, FALSE);
gltestsrc->width, gltestsrc->height, 0);
gst_gl_display_gen_fbo (gltestsrc->display, gltestsrc->width, gltestsrc->height,
&gltestsrc->fbo, &gltestsrc->depthbuffer);

View file

@ -446,8 +446,7 @@ gst_gl_upload_set_caps (GstBaseTransform* bt, GstCaps* incaps,
//init unvisible opengl context
gst_gl_display_create_context (upload->display,
50, y_pos++ * (upload->gl_height+50) + 50,
upload->gl_width, upload->gl_height, 0, FALSE);
upload->gl_width, upload->gl_height, 0);
//init colorspace conversion if needed
gst_gl_display_init_upload (upload->display, upload->video_format,