37 #include <OpenGL/gl3.h>
44 #if HAVE_GLXGETPROCADDRESS
75 #define FF_GL_RED_COMPONENT GL_RED
76 #elif defined(GL_LUMINANCE)
77 #define FF_GL_RED_COMPONENT GL_LUMINANCE
79 #define FF_GL_RED_COMPONENT 0x1903; //GL_RED
83 #define FF_GL_UNSIGNED_BYTE_3_3_2 0x8032
84 #define FF_GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
85 #define FF_GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
86 #define FF_GL_UNPACK_ROW_LENGTH 0x0CF2
89 #define FF_GL_ARRAY_BUFFER 0x8892
90 #define FF_GL_ELEMENT_ARRAY_BUFFER 0x8893
91 #define FF_GL_STATIC_DRAW 0x88E4
92 #define FF_GL_FRAGMENT_SHADER 0x8B30
93 #define FF_GL_VERTEX_SHADER 0x8B31
94 #define FF_GL_COMPILE_STATUS 0x8B81
95 #define FF_GL_LINK_STATUS 0x8B82
96 #define FF_GL_INFO_LOG_LENGTH 0x8B84
97 typedef void (
APIENTRY *FF_PFNGLACTIVETEXTUREPROC) (GLenum texture);
151 #define OPENGL_ERROR_CHECK(ctx) \
154 if ((err_code = glGetError()) != GL_NO_ERROR) { \
155 av_log(ctx, AV_LOG_ERROR, "OpenGL error occurred in '%s', line %d: %d\n", __FUNCTION__, __LINE__, err_code); \
177 SDL_Surface *surface;
346 opengl->surface = SDL_SetVideoMode(width, height,
347 32, SDL_OPENGL | SDL_RESIZABLE);
348 if (!opengl->surface) {
352 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
353 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
354 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
355 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
356 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
366 while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_ALLEVENTS) > 0) {
367 switch (event.type) {
371 switch (event.key.keysym.sym) {
377 case SDL_VIDEORESIZE: {
382 SDL_VideoDriverName(buffer,
sizeof(buffer));
387 if ((ret = opengl_sdl_recreate_window(opengl, event.resize.w, event.resize.h)) < 0)
391 message.
width = opengl->surface->w;
392 message.
height = opengl->surface->h;
406 if (SDL_Init(SDL_INIT_VIDEO)) {
410 if ((ret = opengl_sdl_recreate_window(opengl, opengl->
window_width,
413 av_log(opengl,
AV_LOG_INFO,
"SDL driver: '%s'.\n", SDL_VideoDriverName(buffer,
sizeof(buffer)));
414 message.
width = opengl->surface->w;
415 message.
height = opengl->surface->h;
425 #define LOAD_OPENGL_FUN(name, type) \
426 procs->name = (type)SDL_GL_GetProcAddress(#name); \
427 if (!procs->name) { \
428 av_log(opengl, AV_LOG_ERROR, "Cannot load OpenGL function: '%s'\n", #name); \
429 return AVERROR(ENOSYS); \
433 LOAD_OPENGL_FUN(glGenBuffers, FF_PFNGLGENBUFFERSPROC)
434 LOAD_OPENGL_FUN(glDeleteBuffers, FF_PFNGLDELETEBUFFERSPROC)
435 LOAD_OPENGL_FUN(glBufferData, FF_PFNGLBUFFERDATAPROC)
436 LOAD_OPENGL_FUN(glBindBuffer, FF_PFNGLBINDBUFFERPROC)
437 LOAD_OPENGL_FUN(glGetAttribLocation, FF_PFNGLGETATTRIBLOCATIONPROC)
438 LOAD_OPENGL_FUN(glGetUniformLocation, FF_PFNGLGETUNIFORMLOCATIONPROC)
439 LOAD_OPENGL_FUN(glUniform1f, FF_PFNGLUNIFORM1FPROC)
440 LOAD_OPENGL_FUN(glUniform1i, FF_PFNGLUNIFORM1IPROC)
441 LOAD_OPENGL_FUN(glUniformMatrix4fv, FF_PFNGLUNIFORMMATRIX4FVPROC)
442 LOAD_OPENGL_FUN(glCreateProgram, FF_PFNGLCREATEPROGRAMPROC)
443 LOAD_OPENGL_FUN(glDeleteProgram, FF_PFNGLDELETEPROGRAMPROC)
444 LOAD_OPENGL_FUN(glUseProgram, FF_PFNGLUSEPROGRAMPROC)
445 LOAD_OPENGL_FUN(glLinkProgram, FF_PFNGLLINKPROGRAMPROC)
446 LOAD_OPENGL_FUN(glGetProgramiv, FF_PFNGLGETPROGRAMIVPROC)
447 LOAD_OPENGL_FUN(glGetProgramInfoLog, FF_PFNGLGETPROGRAMINFOLOGPROC)
448 LOAD_OPENGL_FUN(glAttachShader, FF_PFNGLATTACHSHADERPROC)
449 LOAD_OPENGL_FUN(glCreateShader, FF_PFNGLCREATESHADERPROC)
450 LOAD_OPENGL_FUN(glDeleteShader, FF_PFNGLDELETESHADERPROC)
451 LOAD_OPENGL_FUN(glCompileShader, FF_PFNGLCOMPILESHADERPROC)
452 LOAD_OPENGL_FUN(glShaderSource, FF_PFNGLSHADERSOURCEPROC)
453 LOAD_OPENGL_FUN(glGetShaderiv, FF_PFNGLGETSHADERIVPROC)
454 LOAD_OPENGL_FUN(glGetShaderInfoLog, FF_PFNGLGETSHADERINFOLOGPROC)
455 LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
456 LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
460 #undef LOAD_OPENGL_FUN
464 #if defined(__APPLE__)
471 return opengl_sdl_load_procedures(opengl);
506 #if HAVE_GLXGETPROCADDRESS
507 #define SelectedGetProcAddress glXGetProcAddress
508 #elif HAVE_WGLGETPROCADDRESS
509 #define SelectedGetProcAddress wglGetProcAddress
512 #define LOAD_OPENGL_FUN(name, type) \
513 procs->name = (type)SelectedGetProcAddress(#name); \
514 if (!procs->name) { \
515 av_log(opengl, AV_LOG_ERROR, "Cannot load OpenGL function: '%s'\n", #name); \
516 return AVERROR(ENOSYS); \
521 return opengl_sdl_load_procedures(opengl);
547 LOAD_OPENGL_FUN(glEnableVertexAttribArray, FF_PFNGLENABLEVERTEXATTRIBARRAYPROC)
548 LOAD_OPENGL_FUN(glVertexAttribPointer, FF_PFNGLVERTEXATTRIBPOINTERPROC)
552 #undef SelectedGetProcAddress
553 #undef LOAD_OPENGL_FUN
559 memset(matrix, 0, 16 *
sizeof(
float));
560 matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f;
564 float bottom,
float top,
float nearZ,
float farZ)
566 float ral = right + left;
567 float rsl = right - left;
568 float tab = top + bottom;
569 float tsb = top - bottom;
570 float fan = farZ + nearZ;
571 float fsn = farZ - nearZ;
573 memset(matrix, 0, 16 *
sizeof(
float));
574 matrix[0] = 2.0f / rsl;
575 matrix[5] = 2.0f / tsb;
576 matrix[10] = -2.0f / fsn;
577 matrix[12] = -ral / rsl;
578 matrix[13] = -tab / tsb;
579 matrix[14] = -fan / fsn;
586 const char *extension;
589 } required_extensions[] = {
590 {
"GL_ARB_multitexture", 1, 3 },
591 {
"GL_ARB_vertex_buffer_object", 1, 5 },
592 {
"GL_ARB_vertex_shader", 2, 0 },
593 {
"GL_ARB_fragment_shader", 2, 0 },
594 {
"GL_ARB_shader_objects", 2, 0 },
598 const char *extensions, *
version;
600 version = glGetString(GL_VERSION);
601 extensions = glGetString(GL_EXTENSIONS);
604 sscanf(version,
"%d.%d", &major, &minor);
606 for (i = 0; required_extensions[i].extension; i++) {
607 if (major < required_extensions[i].major &&
608 (major == required_extensions[i].major && minor < required_extensions[i].minor) &&
609 !strstr(extensions, required_extensions[i].extension)) {
611 required_extensions[i].extension);
618 opengl->
non_pow_2_textures = major >= 2 || strstr(extensions,
"GL_ARB_texture_non_power_of_two");
619 #if defined(GL_ES_VERSION_2_0)
620 opengl->
unpack_subimage = !!strstr(extensions,
"GL_EXT_unpack_subimage");
650 case GL_UNSIGNED_SHORT:
652 case GL_UNSIGNED_SHORT_5_6_5:
654 case GL_UNSIGNED_BYTE:
700 int *out_width,
int *out_height)
703 *out_width = in_width;
704 *out_height = in_height;
707 unsigned power_of_2 = 1;
708 while (power_of_2 < max)
710 *out_height = power_of_2;
711 *out_width = power_of_2;
713 in_width, in_height, *out_width, *out_height);
734 #define FILL_COMPONENT(i) { \
735 shift = desc->comp[i].depth_minus1 >> 3; \
736 opengl->color_map[(i << 2) + ((desc->comp[i].offset_plus1 - 1) >> shift)] = 1.0; \
746 #undef FILL_COMPONENT
785 if (!fragment_shader_code) {
798 fragment_shader_code);
850 GLsizei width, GLsizei height)
855 glBindTexture(GL_TEXTURE_2D, texture);
856 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
857 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
858 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
860 glTexImage2D(GL_TEXTURE_2D, 0, opengl->
format, new_width, new_height, 0,
920 for (i = 0; i < 4; i++)
946 if ((ret = opengl_sdl_create_window(h)) < 0) {
951 av_log(opengl,
AV_LOG_ERROR,
"FFmpeg is compiled without SDL. Cannot create default window.\n");
956 message.
x = message.
y = 0;
960 &message ,
sizeof(message))) < 0) {
1031 for (i = 1; i < num_planes; i++)
1047 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1050 (
float)opengl->
background[2] / 255.0f, 1.0f);
1109 glClear(GL_COLOR_BUFFER_BIT);
1113 SDL_GL_SwapBuffers();
1139 int plane = desc->
comp[comp_index].
plane;
1145 data += opengl->
width * opengl->
height * wordsize;
1148 data += opengl->
width * opengl->
height * wordsize;
1149 data += width_chroma * height_chroma * wordsize;
1152 data += opengl->
width * opengl->
height * wordsize;
1153 data += 2 * width_chroma * height_chroma * wordsize;
1161 #define LOAD_TEXTURE_DATA(comp_index, sub) \
1163 int width = sub ? FF_CEIL_RSHIFT(opengl->width, desc->log2_chroma_w) : opengl->width; \
1164 int height = sub ? FF_CEIL_RSHIFT(opengl->height, desc->log2_chroma_h): opengl->height; \
1166 int plane = desc->comp[comp_index].plane; \
1168 glBindTexture(GL_TEXTURE_2D, opengl->texture_name[comp_index]); \
1170 GLint length = ((AVFrame *)input)->linesize[plane]; \
1171 int bytes_per_pixel = opengl_type_size(opengl->type); \
1172 if (!(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) \
1173 bytes_per_pixel *= desc->nb_components; \
1174 data = ((AVFrame *)input)->data[plane]; \
1175 if (!(length % bytes_per_pixel) && \
1176 (opengl->unpack_subimage || ((length / bytes_per_pixel) == width))) { \
1177 length /= bytes_per_pixel; \
1178 if (length != width) \
1179 glPixelStorei(FF_GL_UNPACK_ROW_LENGTH, length); \
1180 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, \
1181 opengl->format, opengl->type, data); \
1182 if (length != width) \
1183 glPixelStorei(FF_GL_UNPACK_ROW_LENGTH, 0); \
1186 for (h = 0; h < height; h++) { \
1187 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, h, width, 1, \
1188 opengl->format, opengl->type, data); \
1193 data = opengl_get_plane_pointer(opengl, input, comp_index, desc); \
1194 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, \
1195 opengl->format, opengl->type, data); \
1207 if (!opengl->
no_window && (ret = opengl_sdl_process_events(h)) < 0)
1216 glClear(GL_COLOR_BUFFER_BIT);
1220 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1249 SDL_GL_SwapBuffers();
1275 #define OFFSET(x) offsetof(OpenGLContext, x)
1276 #define ENC AV_OPT_FLAG_ENCODING_PARAM
1305 .priv_class = &opengl_class,