|
|
@@ -188,6 +188,8 @@ typedef struct OpenGLContext { |
|
|
|
|
|
|
|
/* Current OpenGL configuration */ |
|
|
|
GLuint program; ///< Shader program |
|
|
|
GLuint vertex_shader; ///< Vertex shader |
|
|
|
GLuint fragment_shader; ///< Fragment shader for current pix_pmt |
|
|
|
GLuint texture_name[4]; ///< Textures' IDs |
|
|
|
GLuint index_buffer; ///< Index buffer |
|
|
|
GLuint vertex_buffer; ///< Vertex buffer |
|
|
@@ -270,6 +272,32 @@ static av_cold int opengl_prepare_vertex(AVFormatContext *s); |
|
|
|
static int opengl_draw(AVFormatContext *h, AVPacket *pkt, int repaint); |
|
|
|
static av_cold int opengl_init_context(OpenGLContext *opengl); |
|
|
|
|
|
|
|
static av_cold void opengl_deinit_context(OpenGLContext *opengl) |
|
|
|
{ |
|
|
|
glDeleteTextures(4, opengl->texture_name); |
|
|
|
opengl->texture_name[0] = opengl->texture_name[1] = |
|
|
|
opengl->texture_name[2] = opengl->texture_name[3] = 0; |
|
|
|
if (opengl->glprocs.glUseProgram) |
|
|
|
opengl->glprocs.glUseProgram(0); |
|
|
|
if (opengl->glprocs.glDeleteProgram) { |
|
|
|
opengl->glprocs.glDeleteProgram(opengl->program); |
|
|
|
opengl->program = 0; |
|
|
|
} |
|
|
|
if (opengl->glprocs.glDeleteShader) { |
|
|
|
opengl->glprocs.glDeleteShader(opengl->vertex_shader); |
|
|
|
opengl->glprocs.glDeleteShader(opengl->fragment_shader); |
|
|
|
opengl->vertex_shader = opengl->fragment_shader = 0; |
|
|
|
} |
|
|
|
if (opengl->glprocs.glBindBuffer) { |
|
|
|
opengl->glprocs.glBindBuffer(FF_GL_ARRAY_BUFFER, 0); |
|
|
|
opengl->glprocs.glBindBuffer(FF_GL_ELEMENT_ARRAY_BUFFER, 0); |
|
|
|
} |
|
|
|
if (opengl->glprocs.glDeleteBuffers) { |
|
|
|
opengl->glprocs.glDeleteBuffers(2, &opengl->index_buffer); |
|
|
|
opengl->vertex_buffer = opengl->index_buffer = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static int opengl_resize(AVFormatContext *h, int width, int height) |
|
|
|
{ |
|
|
|
int ret = 0; |
|
|
@@ -349,8 +377,7 @@ static int opengl_sdl_process_events(AVFormatContext *h) |
|
|
|
SDL_VideoDriverName(buffer, sizeof(buffer)); |
|
|
|
reinit = !av_strncasecmp(buffer, "quartz", sizeof(buffer)); |
|
|
|
if (reinit) { |
|
|
|
glDeleteTextures(4, opengl->texture_name); |
|
|
|
opengl->glprocs.glDeleteBuffers(2, &opengl->index_buffer); |
|
|
|
opengl_deinit_context(opengl); |
|
|
|
} |
|
|
|
if ((ret = opengl_sdl_recreate_window(opengl, event.resize.w, event.resize.h)) < 0) |
|
|
|
return ret; |
|
|
@@ -731,7 +758,6 @@ static av_cold GLuint opengl_load_shader(OpenGLContext *opengl, GLenum type, con |
|
|
|
|
|
|
|
static av_cold int opengl_compile_shaders(OpenGLContext *opengl, enum AVPixelFormat pix_fmt) |
|
|
|
{ |
|
|
|
GLuint vertex_shader = 0, fragment_shader = 0; |
|
|
|
GLint result; |
|
|
|
const char *fragment_shader_code = opengl_get_fragment_shader_code(pix_fmt); |
|
|
|
|
|
|
@@ -741,15 +767,15 @@ static av_cold int opengl_compile_shaders(OpenGLContext *opengl, enum AVPixelFor |
|
|
|
return AVERROR(EINVAL); |
|
|
|
} |
|
|
|
|
|
|
|
vertex_shader = opengl_load_shader(opengl, FF_GL_VERTEX_SHADER, |
|
|
|
FF_OPENGL_VERTEX_SHADER); |
|
|
|
if (!vertex_shader) { |
|
|
|
opengl->vertex_shader = opengl_load_shader(opengl, FF_GL_VERTEX_SHADER, |
|
|
|
FF_OPENGL_VERTEX_SHADER); |
|
|
|
if (!opengl->vertex_shader) { |
|
|
|
av_log(opengl, AV_LOG_ERROR, "Vertex shader loading failed.\n"); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
fragment_shader = opengl_load_shader(opengl, FF_GL_FRAGMENT_SHADER, |
|
|
|
fragment_shader_code); |
|
|
|
if (!fragment_shader) { |
|
|
|
opengl->fragment_shader = opengl_load_shader(opengl, FF_GL_FRAGMENT_SHADER, |
|
|
|
fragment_shader_code); |
|
|
|
if (!opengl->fragment_shader) { |
|
|
|
av_log(opengl, AV_LOG_ERROR, "Fragment shader loading failed.\n"); |
|
|
|
goto fail; |
|
|
|
} |
|
|
@@ -758,8 +784,8 @@ static av_cold int opengl_compile_shaders(OpenGLContext *opengl, enum AVPixelFor |
|
|
|
if (!opengl->program) |
|
|
|
goto fail; |
|
|
|
|
|
|
|
opengl->glprocs.glAttachShader(opengl->program, vertex_shader); |
|
|
|
opengl->glprocs.glAttachShader(opengl->program, fragment_shader); |
|
|
|
opengl->glprocs.glAttachShader(opengl->program, opengl->vertex_shader); |
|
|
|
opengl->glprocs.glAttachShader(opengl->program, opengl->fragment_shader); |
|
|
|
opengl->glprocs.glLinkProgram(opengl->program); |
|
|
|
|
|
|
|
opengl->glprocs.glGetProgramiv(opengl->program, FF_GL_LINK_STATUS, &result); |
|
|
@@ -792,10 +818,10 @@ static av_cold int opengl_compile_shaders(OpenGLContext *opengl, enum AVPixelFor |
|
|
|
OPENGL_ERROR_CHECK(opengl); |
|
|
|
return 0; |
|
|
|
fail: |
|
|
|
opengl->glprocs.glDeleteShader(vertex_shader); |
|
|
|
opengl->glprocs.glDeleteShader(fragment_shader); |
|
|
|
opengl->glprocs.glDeleteShader(opengl->vertex_shader); |
|
|
|
opengl->glprocs.glDeleteShader(opengl->fragment_shader); |
|
|
|
opengl->glprocs.glDeleteProgram(opengl->program); |
|
|
|
opengl->program = 0; |
|
|
|
opengl->fragment_shader = opengl->vertex_shader = opengl->program = 0; |
|
|
|
return AVERROR_EXTERNAL; |
|
|
|
} |
|
|
|
|
|
|
@@ -940,10 +966,7 @@ static av_cold int opengl_write_trailer(AVFormatContext *h) |
|
|
|
avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER, NULL , 0) < 0) |
|
|
|
av_log(opengl, AV_LOG_ERROR, "Application failed to prepare window buffer.\n"); |
|
|
|
|
|
|
|
glDeleteTextures(4, opengl->texture_name); |
|
|
|
if (opengl && opengl->glprocs.glDeleteBuffers) |
|
|
|
opengl->glprocs.glDeleteBuffers(2, &opengl->index_buffer); |
|
|
|
|
|
|
|
opengl_deinit_context(opengl); |
|
|
|
opengl_release_window(h); |
|
|
|
|
|
|
|
return 0; |
|
|
|