[vlc-commits] [Git][videolan/vlc][master] 10 commits: opengl: expose orientation instead of vflip
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Jun 20 08:14:12 UTC 2023
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
a64afdae by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
opengl: expose orientation instead of vflip
Like in the D3D11 implementation, any OpenGL implementation and
especially those coming from the user might ask a specific rendering
orientation to remove the need to rotate the image after it has been
done by the renderer.
In particular, the libvlc output callback allows any orientation to be
supplied by the user, but was currently ignored in release and was
asserting in debug because it didn't support that.
This commit changes the definition and usage of the opengl (offscreen)
providers to expose a format instead. It is now also exposed for
on-screen implementations also.
- - - - -
65f7d23b by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
viewpoint: add vlc_viewpoint_from_orientation
Add a function to initialize the viewpoint from the given orientation,
allowing to transform it into a 4x4 orientation matrix afterwards.
- - - - -
a7ad2897 by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
vlc_opengl_filter: add orientation to filter meta
The orientation represent a property of the display, ie. how the display
has been rotated and flipped. Forwarding this property to the filters
will allow them to rotate the frames in the opposite direction to ensure
the rendering intent is respected in the end.
- - - - -
679e734e by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
opengl: filters: forward orientation from gl
Copy the surface orientation property from the vlc_gl_t provider and
store it inside the opengl filters object at initialization. The
parameter is then forwarded only for the last filter into the rendering
metadatas, allowing this filter to enforce the final rendering of the
frame with the correct orientation.
- - - - -
92424de6 by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
opengl: display: handle surface orientation
Refactor the picture place function into a separate function, and
manipulate the format when the orientation is different from
ORIENT_NORMAL to place the picture correctly.
- - - - -
ec5dcb2c by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
opengl: renderer: handle orientation in shader
Use the orientation parameter from the rendering metadatas to generate
an orientation matrix and supply it to the shader. The orientation will
be applied after everything.
- - - - -
c3bdc43d by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
vgl: forward orientation to vlc_gl_t
Now that the whole OpenGL pipeline supports orientation, we can accept
orientation direction that are not ORIENT_NORMAL, making the assertion
obsolete.
- - - - -
15e0923f by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
vgl: provide sane defaults as configuration
Provide a sane configuration by default, in particular so that it
doesn't assert when the vgl update callback is failing.
- - - - -
6cdf61b6 by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
vgl: handle updateCb() failure during Open()
When updateCb() fails, the result was ignored and vgl continued to
Open() as normal in release mode, and was even asserting on debug
before.
This split the Resize() function (which cannot return errors) into
a different ResizeInternal() function with an error return value, to be
called from the Open() instead of the .resize() callback.
- - - - -
1d17c9b5 by Alexandre Janniaux at 2023-06-20T07:56:02+00:00
video_filter: opengl: early exit
- - - - -
16 changed files:
- include/vlc_es.h
- include/vlc_opengl.h
- include/vlc_opengl_filter.h
- modules/video_filter/egl_pbuffer.c
- modules/video_filter/opengl.c
- modules/video_output/apple/VLCCVOpenGLProvider.m
- modules/video_output/opengl/display.c
- modules/video_output/opengl/filters.c
- modules/video_output/opengl/filters.h
- modules/video_output/opengl/renderer.c
- modules/video_output/opengl/renderer.h
- modules/video_output/opengl/vout_helper.c
- modules/video_output/vgl.c
- src/libvlccore.sym
- src/misc/viewpoint.c
- src/video_output/opengl.c
Changes:
=====================================
include/vlc_es.h
=====================================
@@ -211,6 +211,9 @@ typedef enum video_orientation_t
/** Applies 180 degree rotation to an orientation */
#define ORIENT_ROTATE_180(orient) ((orient) ^ 3)
+VLC_API void
+vlc_viewpoint_from_orientation(vlc_viewpoint_t *vp, video_orientation_t orient);
+
typedef enum video_transform_t
{
TRANSFORM_IDENTITY = ORIENT_NORMAL,
=====================================
include/vlc_opengl.h
=====================================
@@ -24,6 +24,8 @@
#ifndef VLC_GL_H
#define VLC_GL_H 1
+#include <vlc_es.h>
+
# ifdef __cplusplus
extern "C" {
# endif
@@ -108,12 +110,13 @@ struct vlc_gl_t
struct { /* off-screen */
vlc_fourcc_t offscreen_chroma_out;
struct vlc_video_context *offscreen_vctx_out;
- /* Flag to indicate if the OpenGL implementation produces upside-down
- * pictures */
- bool offscreen_vflip;
};
};
+ /* Orientation that signals how the content should be generated by
+ * the client of the OpenGL provider. */
+ video_orientation_t orientation;
+
/* Defined by the core for libvlc_opengl API loading. */
enum vlc_gl_api_type api_type;
=====================================
include/vlc_opengl_filter.h
=====================================
@@ -45,6 +45,7 @@ struct vlc_gl_input_meta {
vlc_tick_t pts;
unsigned plane;
const vlc_video_dovi_metadata_t *dovi_rpu;
+ video_orientation_t orientation;
};
typedef int
=====================================
modules/video_filter/egl_pbuffer.c
=====================================
@@ -437,7 +437,7 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned height,
.close = Close,
};
gl->ops = &gl_ops;
- gl->offscreen_vflip = true;
+ gl->orientation = ORIENT_VFLIPPED;
eglMakeCurrent(sys->display, sys->surface, sys->surface,
sys->context);
=====================================
modules/video_filter/opengl.c
=====================================
@@ -127,20 +127,20 @@ LoadFilters(filter_sys_t *sys, const char *glfilters_config)
next_module = leftover;
string = next_module; /* const view of next_module */
- if (name)
- {
- struct vlc_gl_filter *filter =
- vlc_gl_filters_Append(filters, name, config);
- config_ChainDestroy(config);
- if (!filter)
- {
- msg_Err(sys->gl, "Could not load GL filter: %s", name);
- free(name);
- return VLC_EGENERIC;
- }
+ if (name == NULL)
+ continue;
+ struct vlc_gl_filter *filter =
+ vlc_gl_filters_Append(filters, name, config);
+ config_ChainDestroy(config);
+ if (!filter)
+ {
+ msg_Err(sys->gl, "Could not load GL filter: %s", name);
free(name);
+ return VLC_EGENERIC;
}
+
+ free(name);
} while (string);
return VLC_SUCCESS;
@@ -229,7 +229,7 @@ static int Open( vlc_object_t *obj )
}
- sys->filters = vlc_gl_filters_New(sys->gl, api, sys->interop);
+ sys->filters = vlc_gl_filters_New(sys->gl, api, sys->interop, ORIENT_NORMAL);
if (!sys->filters)
{
msg_Err(obj, "Could not create filters");
@@ -248,7 +248,7 @@ static int Open( vlc_object_t *obj )
}
free(glfilters_config);
- if (sys->gl->offscreen_vflip)
+ if (sys->gl->orientation == ORIENT_VFLIPPED)
{
/* OpenGL renders upside-down, add a filter to get the pixels in the
* normal orientation */
=====================================
modules/video_output/apple/VLCCVOpenGLProvider.m
=====================================
@@ -355,7 +355,7 @@ static void FreeCVBuffer(picture_t *picture)
.close = Close,
};
gl->ops = &gl_ops;
- gl->offscreen_vflip = true;
+ gl->orientation = ORIENT_VFLIPPED;
gl->offscreen_vctx_out = _vctx_out;
gl->offscreen_chroma_out = VLC_CODEC_CVPX_BGRA;
=====================================
modules/video_output/opengl/display.c
=====================================
@@ -146,6 +146,42 @@ FlipVerticalAlign(struct vout_display_placement *dp)
dp->align.vertical = VLC_VIDEO_ALIGN_TOP;
}
+static void PlacePicture(vout_display_t *vd, vout_display_place_t *place,
+ struct vout_display_placement dp)
+{
+ vout_display_sys_t *sys = vd->sys;
+
+ /* Copy the initial source, sine we might rotate it to fake a rotated
+ * display also. */
+ video_format_t source;
+ video_format_Init(&source, 0);
+ video_format_Copy(&source, vd->source);
+
+ video_transform_t transform = (video_transform_t)sys->gl->orientation;
+ video_format_TransformBy(&source, transform_Inverse(transform));
+
+ if (ORIENT_IS_SWAP(transform)) {
+ unsigned width = dp.width;
+ dp.width = dp.height;
+ dp.height = width;
+ }
+
+ FlipVerticalAlign(&dp);
+
+ vout_display_PlacePicture(place, &source, &dp);
+
+ if (ORIENT_IS_SWAP(transform))
+ {
+ *place = (vout_display_place_t){
+ .x = place->y,
+ .y = place->x,
+ .width = place->height,
+ .height = place->width,
+ };
+ }
+ sys->place_changed = true;
+}
+
/**
* Allocates a surface and an OpenGL context for video output.
*/
@@ -190,10 +226,10 @@ static int Open(vout_display_t *vd,
free(gl_name);
if (sys->gl == NULL)
goto error;
+ vd->sys = sys;
- struct vout_display_placement flipped_dp = vd->cfg->display;
- FlipVerticalAlign(&flipped_dp);
- vout_display_PlacePicture(&sys->place, vd->source, &flipped_dp);
+ struct vout_display_placement dp = vd->cfg->display;
+ PlacePicture(vd, &sys->place, dp);
sys->place_changed = true;
vlc_gl_Resize (sys->gl, vd->cfg->display.width, vd->cfg->display.height);
@@ -219,7 +255,6 @@ static int Open(vout_display_t *vd,
vlc_viewpoint_init(&sys->viewpoint);
- vd->sys = sys;
vd->info.subpicture_chromas = spu_chromas;
vd->ops = &ops;
return VLC_SUCCESS;
@@ -228,6 +263,7 @@ error:
if (sys->gl != NULL)
vlc_gl_Delete(sys->gl);
free (sys);
+ vd->sys = NULL;
return VLC_EGENERIC;
}
@@ -295,9 +331,7 @@ static int Control (vout_display_t *vd, int query)
{
struct vout_display_placement dp = vd->cfg->display;
- FlipVerticalAlign(&dp);
-
- vout_display_PlacePicture(&sys->place, vd->source, &dp);
+ PlacePicture(vd, &sys->place, dp);
sys->place_changed = true;
vlc_gl_Resize (sys->gl, dp.width, dp.height);
return VLC_SUCCESS;
@@ -308,9 +342,7 @@ static int Control (vout_display_t *vd, int query)
{
struct vout_display_placement dp = vd->cfg->display;
- FlipVerticalAlign(&dp);
-
- vout_display_PlacePicture(&sys->place, vd->source, &dp);
+ PlacePicture(vd, &sys->place, dp);
sys->place_changed = true;
return VLC_SUCCESS;
}
=====================================
modules/video_output/opengl/filters.c
=====================================
@@ -145,11 +145,13 @@ struct vlc_gl_filters {
bool can_blit;
GLenum draw_framebuffer_target;
+ video_orientation_t orientation;
};
struct vlc_gl_filters *
vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
- struct vlc_gl_interop *interop)
+ struct vlc_gl_interop *interop,
+ video_orientation_t orientation)
{
struct vlc_gl_filters *filters = malloc(sizeof(*filters));
if (!filters)
@@ -165,6 +167,7 @@ vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
filters->gl = gl;
filters->api = api;
filters->interop = interop;
+ filters->orientation = orientation;
vlc_list_init(&filters->list);
memset(&filters->viewport, 0, sizeof(filters->viewport));
@@ -502,6 +505,10 @@ vlc_gl_filters_Draw(struct vlc_gl_filters *filters)
vt->Viewport(0, 0, priv->tex_widths[0], priv->tex_heights[0]);
meta.plane = 0;
+ meta.orientation = ORIENT_NORMAL;
+ if (vlc_list_is_last(&priv->node, &filters->list))
+ meta.orientation = filters->orientation;
+
int ret = filter->ops->draw(filter, pic, &meta);
if (ret != VLC_SUCCESS)
return ret;
=====================================
modules/video_output/opengl/filters.h
=====================================
@@ -43,7 +43,8 @@ struct vlc_gl_filter;
*/
struct vlc_gl_filters *
vlc_gl_filters_New(struct vlc_gl_t *gl, const struct vlc_gl_api *api,
- struct vlc_gl_interop *interop);
+ struct vlc_gl_interop *interop,
+ video_orientation_t orientation);
/**
* Delete the OpenGL filter chain
=====================================
modules/video_output/opengl/renderer.c
=====================================
@@ -186,9 +186,10 @@ opengl_link_program(struct vlc_gl_filter *filter)
"uniform mat4 ProjectionMatrix;\n"
"uniform mat4 ZoomMatrix;\n"
"uniform mat4 ViewMatrix;\n"
+ "uniform mat4 OrientationMatrix;\n"
"void main() {\n"
" PicCoords = (StereoMatrix * vec3(PicCoordsIn, 1.0)).st;\n"
- " gl_Position = ProjectionMatrix * ZoomMatrix * ViewMatrix\n"
+ " gl_Position = OrientationMatrix * ProjectionMatrix * ZoomMatrix * ViewMatrix\n"
" * vec4(VertexPosition, 1.0);\n"
"}\n";
@@ -267,6 +268,7 @@ opengl_link_program(struct vlc_gl_filter *filter)
GET_ULOC(ProjectionMatrix, "ProjectionMatrix");
GET_ULOC(ViewMatrix, "ViewMatrix");
GET_ULOC(ZoomMatrix, "ZoomMatrix");
+ GET_ULOC(OrientationMatrix, "OrientationMatrix");
GET_ALOC(PicCoordsIn, "PicCoordsIn");
GET_ALOC(VertexPosition, "VertexPosition");
@@ -733,6 +735,15 @@ Draw(struct vlc_gl_filter *filter, const struct vlc_gl_picture *pic,
renderer->valid_coords = true;
}
+ float orientation_matrix[ARRAY_SIZE(MATRIX4_IDENTITY)];
+ if (meta->orientation != ORIENT_NORMAL)
+ {
+ vlc_viewpoint_t orient_vp;
+ vlc_viewpoint_from_orientation(&orient_vp, meta->orientation);
+ vlc_viewpoint_to_4x4(&orient_vp, orientation_matrix);
+ }
+ else memcpy(orientation_matrix, MATRIX4_IDENTITY, sizeof(MATRIX4_IDENTITY));
+
vt->BindBuffer(GL_ARRAY_BUFFER, renderer->texture_buffer_object);
assert(renderer->aloc.PicCoordsIn != -1);
vt->EnableVertexAttribArray(renderer->aloc.PicCoordsIn);
@@ -751,6 +762,8 @@ Draw(struct vlc_gl_filter *filter, const struct vlc_gl_picture *pic,
renderer->var.ViewMatrix);
vt->UniformMatrix4fv(renderer->uloc.ZoomMatrix, 1, GL_FALSE,
renderer->var.ZoomMatrix);
+ vt->UniformMatrix4fv(renderer->uloc.OrientationMatrix, 1, GL_FALSE,
+ orientation_matrix);
vt->DrawElements(GL_TRIANGLES, renderer->nb_indices, GL_UNSIGNED_SHORT, 0);
GL_ASSERT_NOERROR(vt);
=====================================
modules/video_output/opengl/renderer.h
=====================================
@@ -70,6 +70,7 @@ struct vlc_gl_renderer
GLint ProjectionMatrix;
GLint ViewMatrix;
GLint ZoomMatrix;
+ GLint OrientationMatrix;
} uloc;
struct {
=====================================
modules/video_output/opengl/vout_helper.c
=====================================
@@ -101,7 +101,7 @@ CreateFilters(vlc_gl_t *gl, const struct vlc_gl_api *api,
struct vlc_gl_interop *interop,
struct vlc_gl_renderer **out_renderer)
{
- struct vlc_gl_filters *filters = vlc_gl_filters_New(gl, api, interop);
+ struct vlc_gl_filters *filters = vlc_gl_filters_New(gl, api, interop, gl->orientation);
if (!filters)
{
msg_Err(gl, "Could not create filters");
=====================================
modules/video_output/vgl.c
=====================================
@@ -80,11 +80,11 @@ static void VglSwapBuffers(vlc_gl_t *gl)
ReleaseCurrent(gl);
}
-static void Resize(vlc_gl_t * gl, unsigned w, unsigned h)
+static int ResizeInternal(vlc_gl_t * gl, unsigned w, unsigned h)
{
vout_display_sys_t *sys = gl->sys;
if( sys->width == w && sys->height == h )
- return;
+ return VLC_SUCCESS;
MakeCurrent(gl);
libvlc_video_render_cfg_t output_cfg = {
@@ -92,17 +92,38 @@ static void Resize(vlc_gl_t * gl, unsigned w, unsigned h)
libvlc_video_colorspace_BT709, libvlc_video_primaries_BT709,
libvlc_video_transfer_func_SRGB, NULL,
};
- libvlc_video_output_cfg_t render_cfg;
- sys->resizeCb(sys->opaque, &output_cfg, &render_cfg);
+ libvlc_video_output_cfg_t render_cfg = {
+ .opengl_format = GL_RGBA,
+ .full_range = true,
+ .colorspace = libvlc_video_colorspace_BT709,
+ .primaries = libvlc_video_primaries_BT709,
+ .transfer = libvlc_video_transfer_func_SRGB,
+ .orientation = libvlc_video_orient_top_left,
+ };
+ bool ret = sys->resizeCb(sys->opaque, &output_cfg, &render_cfg);
ReleaseCurrent(gl);
+
+ if (!ret)
+ return VLC_EGENERIC;
+
assert(render_cfg.opengl_format == GL_RGBA);
assert(render_cfg.full_range == true);
assert(render_cfg.colorspace == libvlc_video_colorspace_BT709);
assert(render_cfg.primaries == libvlc_video_primaries_BT709);
assert(render_cfg.transfer == libvlc_video_transfer_func_SRGB);
- assert(render_cfg.orientation == libvlc_video_orient_top_left);
+
+ /* video_orientation_t enum is matching libvlc_video_orient_t. */
+ gl->orientation = (video_orientation_t)render_cfg.orientation;
+
sys->width = w;
sys->height = h;
+
+ return VLC_SUCCESS;
+}
+
+static void Resize(vlc_gl_t * gl, unsigned w, unsigned h)
+{
+ ResizeInternal(gl, w, h);
}
static void Close(vlc_gl_t *gl)
@@ -161,7 +182,12 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned height,
return VLC_EGENERIC;
}
}
- Resize(gl, width, height);
+ if (ResizeInternal(gl, width, height) != VLC_SUCCESS)
+ {
+ if( sys->cleanupCb )
+ sys->cleanupCb(sys->opaque);
+ return VLC_EGENERIC;
+ }
static const struct vlc_gl_operations gl_ops =
{
=====================================
src/libvlccore.sym
=====================================
@@ -1013,6 +1013,7 @@ vlc_media_tree_Find
vlc_media_tree_Preparse
vlc_media_tree_PreparseCancel
vlc_viewpoint_to_4x4
+vlc_viewpoint_from_orientation
vlc_video_context_Create
vlc_video_context_Release
vlc_video_context_GetType
=====================================
src/misc/viewpoint.c
=====================================
@@ -25,6 +25,7 @@
#endif
#include <vlc_viewpoint.h>
+#include <vlc_es.h>
void vlc_viewpoint_to_4x4( const vlc_viewpoint_t *vp, float *m )
{
@@ -69,3 +70,36 @@ void vlc_viewpoint_to_4x4( const vlc_viewpoint_t *vp, float *m )
for (int l=0; l<4; ++l)
m[4*i+l] += y_rot[i][j] * x_rot[j][k] * z_rot[k][l];
}
+
+void vlc_viewpoint_from_orientation(vlc_viewpoint_t *vp,
+ video_orientation_t orient)
+{
+ switch(orient)
+ {
+ default:
+ case ORIENT_NORMAL:
+ case ORIENT_HFLIPPED:
+ *vp = (vlc_viewpoint_t) { .fov = vp->fov };
+ break;
+
+ case ORIENT_ROTATED_90:
+ case ORIENT_ANTI_TRANSPOSED:
+ *vp = (vlc_viewpoint_t) {
+ .roll = -90.f, .fov = vp->fov
+ };
+ break;
+
+ case ORIENT_ROTATED_180:
+ case ORIENT_VFLIPPED:
+ *vp = (vlc_viewpoint_t) {
+ .roll = -180.f, .fov = vp->fov
+ };
+ break;
+ case ORIENT_ROTATED_270:
+ case ORIENT_TRANSPOSED:
+ *vp = (vlc_viewpoint_t) {
+ .roll = -270.f, .fov = vp->fov
+ };
+ break;
+ }
+}
=====================================
src/video_output/opengl.c
=====================================
@@ -89,6 +89,7 @@ vlc_gl_t *vlc_gl_Create(const struct vout_display_cfg *restrict cfg,
vlc_gl_t *gl = &glpriv->gl;
gl->api_type = api_type;
+ gl->orientation = ORIENT_NORMAL;
gl->surface = wnd;
gl->device = NULL;
@@ -144,9 +145,9 @@ vlc_gl_t *vlc_gl_CreateOffscreen(vlc_object_t *parent,
vlc_gl_t *gl = &glpriv->gl;
gl->api_type = api_type;
+ gl->orientation = ORIENT_NORMAL;
gl->offscreen_chroma_out = VLC_CODEC_UNKNOWN;
- gl->offscreen_vflip = false;
gl->offscreen_vctx_out = NULL;
gl->surface = NULL;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4b16a94d390f94ed60feec5ae2968824265f6cce...1d17c9b56b2d8c16d14dcec1e02e96d5234e9157
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4b16a94d390f94ed60feec5ae2968824265f6cce...1d17c9b56b2d8c16d14dcec1e02e96d5234e9157
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list