/* * This file is part of mpv. * * Parts based on the MPlayer VA-API patch (see vo_vaapi.c). * * mpv is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with mpv. If not, see . */ #include #include #include #include #include "x11_common.h" #include "gl_hwdec.h" #include "video/vaapi.h" struct priv { struct mp_log *log; struct mp_vaapi_ctx *ctx; VADisplay *display; GLuint gl_texture; void *vaglx_surface; }; static void destroy_texture(struct gl_hwdec *hw) { struct priv *p = hw->priv; GL *gl = hw->gl; VAStatus status; if (p->vaglx_surface) { va_lock(p->ctx); status = vaDestroySurfaceGLX(p->display, p->vaglx_surface); va_unlock(p->ctx); CHECK_VA_STATUS(p, "vaDestroySurfaceGLX()"); p->vaglx_surface = NULL; } gl->DeleteTextures(1, &p->gl_texture); p->gl_texture = 0; } static void destroy(struct gl_hwdec *hw) { struct priv *p = hw->priv; destroy_texture(hw); va_destroy(p->ctx); } static int create(struct gl_hwdec *hw) { if (hw->hwctx) return -1; Display *x11disp = glXGetCurrentDisplay(); if (!x11disp) return -1; struct priv *p = talloc_zero(hw, struct priv); hw->priv = p; p->log = hw->log; p->display = vaGetDisplayGLX(x11disp); if (!p->display) return -1; p->ctx = va_initialize(p->display, p->log); if (!p->ctx) { vaTerminate(p->display); return -1; } if (hw->reject_emulated && va_guess_if_emulated(p->ctx)) { destroy(hw); return -1; } hw->hwctx = &p->ctx->hwctx; hw->converted_imgfmt = IMGFMT_RGB0; return 0; } static int reinit(struct gl_hwdec *hw, struct mp_image_params *params) { struct priv *p = hw->priv; GL *gl = hw->gl; VAStatus status; destroy_texture(hw); params->imgfmt = hw->driver->imgfmt; gl->GenTextures(1, &p->gl_texture); gl->BindTexture(GL_TEXTURE_2D, p->gl_texture); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, params->w, params->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); gl->BindTexture(GL_TEXTURE_2D, 0); va_lock(p->ctx); status = vaCreateSurfaceGLX(p->display, GL_TEXTURE_2D, p->gl_texture, &p->vaglx_surface); va_unlock(p->ctx); return CHECK_VA_STATUS(p, "vaCreateSurfaceGLX()") ? 0 : -1; } static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image, GLuint *out_textures) { struct priv *p = hw->priv; VAStatus status; if (!p->vaglx_surface) return -1; va_lock(p->ctx); status = vaCopySurfaceGLX(p->display, p->vaglx_surface, va_surface_id(hw_image), va_get_colorspace_flag(hw_image->params.colorspace)); va_unlock(p->ctx); if (!CHECK_VA_STATUS(p, "vaCopySurfaceGLX()")) return -1; out_textures[0] = p->gl_texture; return 0; } static void unmap_image(struct gl_hwdec *hw) { } const struct gl_hwdec_driver gl_hwdec_vaglx = { .api_name = "vaapi", .imgfmt = IMGFMT_VAAPI, .create = create, .reinit = reinit, .map_image = map_image, .unmap_image = unmap_image, .destroy = destroy, };