mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
[251/906] Properly clean OpenGL contexts
This commit is contained in:
parent
c330210648
commit
2c9bb405a0
7 changed files with 52 additions and 91 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
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 );
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue