[vlc-commits] [Git][videolan/vlc][master] 5 commits: opengl: subrenderer: handle GL orientation

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Tue Aug 22 20:29:35 UTC 2023



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
3a61a2a0 by Alexandre Janniaux at 2023-08-22T19:38:18+00:00
opengl: subrenderer: handle GL orientation

The OpenGL surface can expose an orientation, which is used by the
renderer.c code, but it wasn't used by the sub_renderer yet. This commit
specify how to transform the vertex coordinates, and for simplicity the
texture coordinates, whatever the orientation is.

- - - - -
6c039292 by Alexandre Janniaux at 2023-08-22T19:38:18+00:00
test/opengl: sub_renderer: add test for orientation

The test draws a 2x2 subpicture region on top of a 4x4 framebuffer. Each
pixel is different on the subpicture, which allows to check the
orientation and position of the subpicture according to the surface
orientation.

libplacebo is linked into the tests for now, since it seems the tests
need it transitively, but it should not be needed in the long run. See
the link error below:

    /usr/bin/ld: ../modules/video_output/opengl/test_modules_video_output_opengl_sub_renderer-sub_renderer.o:(.data.rel.ro+0x8): undefined reference to `pl_filter_spline16'
    /usr/bin/ld: ../modules/video_output/opengl/test_modules_video_output_opengl_sub_renderer-sub_renderer.o:(.data.rel.ro+0x10): undefined reference to `pl_filter_spline36'
    /usr/bin/ld: ../modules/video_output/opengl/test_modules_video_output_opengl_sub_renderer-sub_renderer.o:(.data.rel.ro+0x18): undefined reference to `pl_filter_spline64'
    /usr/bin/ld: ../modules/video_output/opengl/test_modules_video_output_opengl_sub_renderer-sub_renderer.o:(.data.rel.ro+0x20): undefined reference to `pl_filter_mitchell'
    /usr/bin/ld: ../modules/video_output/opengl/test_modules_video_output_opengl_sub_renderer-sub_renderer.o:(.data.rel.ro+0x28): undefined reference to `pl_filter_bicubic'
    ...

- - - - -
e0e9be23 by Alexandre Janniaux at 2023-08-22T19:38:18+00:00
test/opengl: filters: fix file header

The file was renamed to filters.c since it was specifically designed to
test the code from opengl/filters.c, but I forgot to change the header.

- - - - -
51ef2467 by Alexandre Janniaux at 2023-08-22T19:38:18+00:00
opengl: sub_renderer: remove vout_helper.h

The header was not used anymore.

- - - - -
e3ee5645 by Alexandre Janniaux at 2023-08-22T19:38:18+00:00
opengl: sub_renderer: use vlc_opengl_interop.h

...instead of the private interop include. The interop.h include also
contains functions to create interop objects, that we don't use in the
sub_renderer, whereas vlc_opengl_interop.h contains every public
structure and functions.

- - - - -


4 changed files:

- modules/video_output/opengl/sub_renderer.c
- test/Makefile.am
- test/modules/video_output/opengl/filters.c
- + test/modules/video_output/opengl/sub_renderer.c


Changes:

=====================================
modules/video_output/opengl/sub_renderer.c
=====================================
@@ -37,10 +37,9 @@
 #include <vlc_arrays.h>
 #include <vlc_es.h>
 #include <vlc_subpicture.h>
+#include <vlc_opengl_interop.h>
 
 #include "gl_util.h"
-#include "interop.h"
-#include "vout_helper.h"
 
 typedef struct {
     GLuint   texture;
@@ -344,26 +343,102 @@ vlc_gl_sub_renderer_Draw(struct vlc_gl_sub_renderer *sr)
     vt->ActiveTexture(GL_TEXTURE0 + 0);
     for (unsigned i = 0; i < sr->region_count; i++) {
         gl_region_t *glr = &sr->regions[i];
-        const GLfloat vertexCoord[] = {
-            glr->left,  glr->top,
-            glr->left,  glr->bottom,
-            glr->right, glr->top,
-            glr->right, glr->bottom,
-        };
-        const GLfloat textureCoord[] = {
+
+        GLfloat textureCoordNormal[] = {
             0.0, 0.0,
             0.0, glr->tex_height,
             glr->tex_width, 0.0,
             glr->tex_width, glr->tex_height,
         };
 
-        assert(glr->texture != 0);
+        const GLfloat textureCoord90[] = {
+            0.0, glr->tex_height,
+            glr->tex_width, glr->tex_height,
+            0.0, 0.0,
+            glr->tex_width, 0.0,
+        };
+
+        GLfloat left, right, top, bottom;
+        const GLfloat *textureCoord;
+        switch (sr->gl->orientation)
+        {
+            case ORIENT_TOP_LEFT:
+            case ORIENT_TOP_RIGHT:
+                left = glr->left;
+                right = glr->right;
+                top = glr->top;
+                bottom = glr->bottom;
+                textureCoord = textureCoordNormal;
+                break;
+
+            case ORIENT_LEFT_TOP:
+            case ORIENT_LEFT_BOTTOM:
+                left = glr->bottom;
+                right = glr->top;
+                top = -glr->left;
+                bottom = -glr->right;
+                textureCoord = textureCoord90;
+                break;
+
+            case ORIENT_BOTTOM_LEFT:
+            case ORIENT_BOTTOM_RIGHT:
+                left = -glr->left;
+                right = -glr->right;
+                top = -glr->top;
+                bottom = -glr->bottom;
+                textureCoord = textureCoordNormal;
+                break;
+
+            case ORIENT_RIGHT_TOP:
+            case ORIENT_RIGHT_BOTTOM:
+                left = - glr->bottom;
+                right = - glr->top;
+                top = glr->left;
+                bottom = glr->right;
+                textureCoord = textureCoord90;
+                break;
+            default:
+                vlc_assert_unreachable();
+        }
+
+        if (ORIENT_IS_MIRROR(sr->gl->orientation))
+        {
+            switch (sr->gl->orientation)
+            {
+                case ORIENT_TOP_RIGHT:
+                case ORIENT_BOTTOM_LEFT:
+                    left  = -left;
+                    right = -right;
+                    break;
+
+                case ORIENT_LEFT_TOP:
+                case ORIENT_RIGHT_BOTTOM:
+                    top    = -top;
+                    bottom = -bottom;
+                    break;
+
+                default:
+                    vlc_assert_unreachable();
+            }
+        }
+
+
+        const GLfloat vertexCoord[] = {
+            left,  top,
+            left,  bottom,
+            right, top,
+            right, bottom,
+        };
+
+                assert(glr->texture != 0);
         vt->BindTexture(interop->tex_target, glr->texture);
 
         vt->Uniform1f(sr->uloc.alpha, glr->alpha);
 
         vt->BindBuffer(GL_ARRAY_BUFFER, sr->buffer_objects[2 * i]);
-        vt->BufferData(GL_ARRAY_BUFFER, sizeof(textureCoord), textureCoord, GL_STATIC_DRAW);
+        static_assert(sizeof(textureCoordNormal) == sizeof(textureCoord90),
+                      "textureCoordNormal != textureCoord90");
+        vt->BufferData(GL_ARRAY_BUFFER, sizeof(textureCoordNormal), textureCoord, GL_STATIC_DRAW);
         vt->EnableVertexAttribArray(sr->aloc.tex_coords_in);
         vt->VertexAttribPointer(sr->aloc.tex_coords_in, 2, GL_FLOAT, 0, 0, 0);
 


=====================================
test/Makefile.am
=====================================
@@ -56,11 +56,15 @@ check_PROGRAMS = \
 	$(NULL)
 
 if HAVE_GL
-check_PROGRAMS += test_modules_video_output_opengl_filters
+check_PROGRAMS += \
+	test_modules_video_output_opengl_filters \
+	test_modules_video_output_opengl_sub_renderer
 endif
 
 if HAVE_GLES2
-check_PROGRAMS += test_modules_video_output_opengl_es2_filters
+check_PROGRAMS += \
+	test_modules_video_output_opengl_es2_filters \
+	test_modules_video_output_opengl_es2_sub_renderer
 endif
 
 if HAVE_DARWIN
@@ -248,6 +252,23 @@ test_modules_video_output_opengl_es2_filters_SOURCES = $(test_modules_video_outp
 test_modules_video_output_opengl_es2_filters_LDADD = $(LIBVLCCORE) $(LIBVLC)
 test_modules_video_output_opengl_es2_filters_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_TEST_OPENGL_API=VLC_OPENGL_ES2
 
+test_modules_video_output_opengl_sub_renderer_SOURCES = \
+	modules/video_output/opengl/sub_renderer.c \
+	../modules/video_output/opengl/sub_renderer.c \
+	../modules/video_output/opengl/sub_renderer.h \
+	../modules/video_output/opengl/filter.c \
+	../modules/video_output/opengl/gl_api.c \
+	../modules/video_output/opengl/gl_api.h \
+	../modules/video_output/opengl/gl_util.c \
+	../modules/video_output/opengl/gl_util.h \
+	../modules/video_output/opengl/interop.c \
+	../modules/video_output/opengl/interop.h
+test_modules_video_output_opengl_sub_renderer_LDADD = $(LIBVLCCORE) $(LIBVLC) $(LIBPLACEBO_LIBS)
+test_modules_video_output_opengl_sub_renderer_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_TEST_OPENGL_API=VLC_OPENGL
+test_modules_video_output_opengl_es2_sub_renderer_SOURCES = $(test_modules_video_output_opengl_sub_renderer_SOURCES)
+test_modules_video_output_opengl_es2_sub_renderer_LDADD = $(LIBVLCCORE) $(LIBVLC) $(LIBPLACEBO_LIBS)
+test_modules_video_output_opengl_es2_sub_renderer_CPPFLAGS = $(AM_CPPFLAGS) -DVLC_TEST_OPENGL_API=VLC_OPENGL_ES2
+
 test_modules_stream_out_transcode_SOURCES = \
 	modules/stream_out/transcode.c \
 	modules/stream_out/transcode.h \


=====================================
test/modules/video_output/opengl/filters.c
=====================================
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * opengl.c: test for the OpenGL client code
+ * filters.c: test for the OpenGL filter client code
  *****************************************************************************
  * Copyright (C) 2023 VideoLabs
  *


=====================================
test/modules/video_output/opengl/sub_renderer.c
=====================================
@@ -0,0 +1,386 @@
+/*****************************************************************************
+ * sub_renderer.c: test for the OpenGL subrenderer code
+ *****************************************************************************
+ * Copyright (C) 2023 VideoLabs
+ *
+ * Authors: Alexandre Janniaux <ajanni at videolabs.io>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifndef VLC_TEST_OPENGL_API
+# error "Define VLC_TEST_OPENGL_API to the VLC_OPENGL API to use"
+#endif
+
+/* Define a builtin module for mocked parts */
+#define MODULE_NAME test_opengl
+#undef VLC_DYNAMIC_PLUGIN
+
+#include "../../../libvlc/test.h"
+#include "../../../../lib/libvlc_internal.h"
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_opengl.h>
+#include <vlc_filter.h>
+#include <vlc_modules.h>
+#include <vlc_vout_display.h>
+#include <vlc_subpicture.h>
+
+#include "../../../../modules/video_output/opengl/sub_renderer.h"
+#include "../../../../modules/video_output/opengl/gl_api.h"
+#include "../../../../modules/video_output/opengl/interop.h"
+
+static_assert(
+    VLC_TEST_OPENGL_API == VLC_OPENGL ||
+    VLC_TEST_OPENGL_API == VLC_OPENGL_ES2,
+    "VLC_TEST_OPENGL_API must be assigned to VLC_OPENGL or VLC_OPENGL_ES2");
+
+const char vlc_module_name[] = MODULE_STRING;
+static const uint8_t red[]   = { 0xff, 0x00, 0x00, 0xff };
+static const uint8_t green[] = { 0x00, 0xff, 0x00, 0xff };
+static const uint8_t blue[]  = { 0x00, 0x00, 0xff, 0xff };
+static const uint8_t white[] = { 0xff, 0xff, 0xff, 0xff };
+static const uint8_t black[] = { 0x00, 0x00, 0x00, 0xff };
+
+struct test_point
+{
+    int x, y;
+    const uint8_t *color;
+};
+
+static const char *OrientToString(video_orientation_t orient)
+{
+    switch (orient)
+    {
+        case ORIENT_TOP_LEFT:       return "normal";
+        case ORIENT_TOP_RIGHT:      return "hflip";
+        case ORIENT_BOTTOM_RIGHT:   return "rot180";
+        case ORIENT_BOTTOM_LEFT:    return "vflip";
+        case ORIENT_LEFT_BOTTOM:    return "rot270";
+        case ORIENT_LEFT_TOP:       return "transposed";
+        case ORIENT_RIGHT_TOP:      return "rot90";
+        case ORIENT_RIGHT_BOTTOM:   return "antitransposed";
+        default: vlc_assert_unreachable();
+    }
+}
+
+static void test_opengl_offscreen(
+        vlc_object_t *root,
+        video_orientation_t orientation,
+        struct test_point *points,
+        size_t points_count
+){
+    fprintf(stderr, " * Checking orientation %s:\n", OrientToString(orientation));
+    struct vlc_decoder_device *device =
+        vlc_decoder_device_Create(root, NULL);
+    vlc_gl_t *gl = vlc_gl_CreateOffscreen(
+            root, device, 4, 4, VLC_TEST_OPENGL_API, NULL, NULL);
+    assert(gl != NULL);
+    if (device != NULL)
+        vlc_decoder_device_Release(device);
+
+    /* HACK: we cannot pass an orientation to the subrenderer right now. */
+    gl->orientation = orientation;
+
+    int ret = vlc_gl_MakeCurrent(gl);
+    assert(ret == VLC_SUCCESS);
+
+    struct vlc_gl_api api;
+    ret = vlc_gl_api_Init(&api, gl);
+    assert(ret == VLC_SUCCESS);
+
+    GLuint out_tex;
+    api.vt.GenTextures(1, &out_tex);
+    api.vt.BindTexture(GL_TEXTURE_2D, out_tex);
+    api.vt.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    api.vt.BindTexture(GL_TEXTURE_2D, 0);
+
+    GLuint out_fb;
+    api.vt.GenFramebuffers(1, &out_fb);
+    api.vt.BindFramebuffer(GL_FRAMEBUFFER, out_fb);
+    api.vt.BindFramebuffer(GL_READ_FRAMEBUFFER, out_fb);
+    api.vt.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                GL_TEXTURE_2D, out_tex, 0);
+
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    api.vt.ClearColor(0.f, 0.f, 0.f, 1.f);
+    api.vt.Clear(GL_COLOR_BUFFER_BIT);
+    api.vt.Viewport(0, 0, 4, 4);
+
+    video_format_t fmt;
+    video_format_Init(&fmt, VLC_CODEC_RGBA);
+    video_format_Setup(&fmt, VLC_CODEC_RGBA, 2, 2, 2, 2, 1, 1);
+    fmt.primaries = COLOR_PRIMARIES_UNDEF;
+    fmt.space = COLOR_SPACE_UNDEF;
+    fmt.transfer = TRANSFER_FUNC_UNDEF;
+    fmt.projection_mode = PROJECTION_MODE_RECTANGULAR;
+
+    struct vlc_gl_interop *interop =
+        vlc_gl_interop_NewForSubpictures(gl);
+    assert(interop != NULL);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    GLint fbo_binding;
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+
+    struct vlc_gl_sub_renderer *sr = vlc_gl_sub_renderer_New(gl, &api, interop);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+    assert(api.vt.CheckFramebufferStatus(GL_FRAMEBUFFER)
+            == GL_FRAMEBUFFER_COMPLETE);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    picture_t *picture = picture_NewFromFormat(&fmt);
+    assert(picture != NULL);
+
+    size_t size = picture->p[0].i_lines * picture->p[0].i_pitch / picture->p[0].i_pixel_pitch;
+    for (size_t i=0; i < size; ++i)
+        memcpy(&picture->p[0].p_pixels[i * 4], green, sizeof(green));
+
+    /* The subpicture region will be the following:
+     *     +-----+
+     *     | R G |
+     *     | B W |
+     *     +-----+
+     * */
+    memcpy(&picture->p[0].p_pixels[0 * 4], red, sizeof(red));
+    memcpy(&picture->p[0].p_pixels[1 * 4], green, sizeof(green));
+    memcpy(&picture->p[0].p_pixels[0 * 4 + picture->p[0].i_pitch], blue, sizeof(blue));
+    memcpy(&picture->p[0].p_pixels[1 * 4 + picture->p[0].i_pitch], white, sizeof(white));
+
+    subpicture_t *subpicture = subpicture_New(NULL);
+    assert(subpicture != NULL);
+    subpicture->i_original_picture_width = 4;
+    subpicture->i_original_picture_height = 4;
+
+    subpicture->p_region = subpicture_region_ForPicture(&fmt, picture);
+    assert(subpicture->p_region != NULL);
+
+    ret = vlc_gl_sub_renderer_Prepare(sr, subpicture);
+    assert(ret == VLC_SUCCESS);
+    GL_ASSERT_NOERROR(&api.vt);
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+
+    ret = vlc_gl_sub_renderer_Draw(sr);
+    assert(ret == VLC_SUCCESS);
+    GL_ASSERT_NOERROR(&api.vt);
+    api.vt.GetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo_binding);
+    assert((GLuint)fbo_binding == out_fb);
+
+    api.vt.Finish();
+    GL_ASSERT_NOERROR(&api.vt);
+
+    /* Disable pixel packing to use glReadPixels. */
+    api.vt.BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    uint8_t pixel[4];
+
+    fprintf(stderr, "Results:\n");
+    for (size_t i = 0; i < 4; ++i)
+    {
+        for (size_t j = 0; j < 4; ++j)
+        {
+            api.vt.ReadPixels(j, 3 - i, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+            fprintf(stderr, "    %u:%u:%u:%u", pixel[0], pixel[1], pixel[2], pixel[3]);
+        }
+        fprintf(stderr, "\n");
+    }
+
+    for (size_t i = 0; i < points_count; ++i)
+    {
+        api.vt.ReadPixels(points[i].y, 3 - points[i].x, 1, 1, GL_RGBA,
+                          GL_UNSIGNED_BYTE, &pixel);
+        GL_ASSERT_NOERROR(&api.vt);
+        fprintf(stderr, " %s: Checking point %dx%d, need %d:%d:%d, got %d:%d:%d\n",
+                 OrientToString(orientation), points[i].x, points[i].y,
+                 points[i].color[0], points[i].color[1], points[i].color[2],
+                 pixel[0], pixel[1], pixel[2]);
+        assert(memcmp(pixel, points[i].color, sizeof(pixel)) == 0);
+    }
+
+    vlc_gl_sub_renderer_Delete(sr);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    vlc_gl_interop_Delete(interop);
+    GL_ASSERT_NOERROR(&api.vt);
+
+    vlc_gl_ReleaseCurrent(gl);
+    vlc_gl_Delete(gl);
+
+    picture_Release(picture);
+}
+
+int main( int argc, char **argv )
+{
+    (void)argc; (void)argv;
+    test_init();
+
+    const char * const vlc_argv[] = {
+        "-vvv", "--aout=dummy", "--text-renderer=dummy",
+    };
+
+    libvlc_instance_t *vlc = libvlc_new(ARRAY_SIZE(vlc_argv), vlc_argv);
+    vlc_object_t *root = &vlc->p_libvlc_int->obj;
+
+    const char *cap =
+        (VLC_TEST_OPENGL_API == VLC_OPENGL)     ? "opengl offscreen" :
+        (VLC_TEST_OPENGL_API == VLC_OPENGL_ES2) ? "opengl es2 offscreen" :
+        NULL;
+    assert(cap != NULL);
+
+    fprintf(stderr, "Looking for cap %s\n", cap);
+
+    module_t **providers;
+    size_t strict_matches;
+    ssize_t provider_available = vlc_module_match(
+            cap, NULL, false, &providers, &strict_matches);
+    (void)strict_matches;
+    free(providers);
+
+    if (provider_available <= 0)
+    {
+        libvlc_release(vlc);
+        return 77;
+    }
+
+    struct vlc_decoder_device *device =
+        vlc_decoder_device_Create(root, NULL);
+    vlc_gl_t *gl = vlc_gl_CreateOffscreen(
+            root, device, 3, 3, VLC_TEST_OPENGL_API, NULL, NULL);
+    if (device != NULL)
+        vlc_decoder_device_Release(device);
+
+    if (gl == NULL)
+    {
+        libvlc_release(vlc);
+        return 77;
+    }
+    vlc_gl_Delete(gl);
+
+    struct test_point points_normal[] = {
+        { 0, 0, red },
+        { 0, 1, green },
+        { 1, 0, blue },
+        { 1, 1, white },
+        { 1, 2, black },
+        { 2, 1, black },
+        { 2, 2, black },
+    };
+    test_opengl_offscreen(root, ORIENT_NORMAL, 
+                          points_normal, ARRAY_SIZE(points_normal));
+
+    struct test_point points_rotated_90[] = {
+        { 3, 0, red },
+        { 2, 0, green },
+        { 3, 1, blue },
+        { 2, 1, white },
+        { 1, 0, black },
+        { 2, 2, black },
+        { 3, 3, black },
+    };
+    test_opengl_offscreen(root, ORIENT_ROTATED_90,
+                          points_rotated_90, ARRAY_SIZE(points_rotated_90));
+
+    struct test_point points_rotated_180[] = {
+        { 3, 3, red },
+        { 3, 2, green },
+        { 2, 3, blue },
+        { 2, 2, white },
+        { 2, 1, black },
+        { 1, 2, black },
+        { 1, 1, black },
+    };
+    test_opengl_offscreen(root, ORIENT_ROTATED_180,
+                          points_rotated_180, ARRAY_SIZE(points_rotated_180));
+
+    struct test_point points_rotated_270[] = {
+        { 0, 3, red },
+        { 1, 3, green },
+        { 0, 2, blue },
+        { 1, 2, white },
+        { 2, 3, black },
+        { 1, 1, black },
+        { 0, 0, black },
+    };
+    test_opengl_offscreen(root, ORIENT_ROTATED_270,
+                          points_rotated_270, ARRAY_SIZE(points_rotated_270));
+
+    struct test_point points_hflip[] = {
+        { 0, 3, red },
+        { 0, 2, green },
+        { 1, 3, blue },
+        { 1, 2, white },
+        { 1, 1, black },
+        { 2, 2, black },
+        { 2, 1, black },
+
+    };
+    test_opengl_offscreen(root, ORIENT_HFLIPPED,
+                          points_hflip, ARRAY_SIZE(points_hflip));
+
+    struct test_point points_vflip[] = {
+        { 3, 0, red },
+        { 3, 1, green },
+        { 2, 0, blue },
+        { 2, 1, white },
+        { 2, 2, black },
+        { 1, 1, black },
+        { 1, 2, black },
+    };
+    test_opengl_offscreen(root, ORIENT_VFLIPPED,
+                          points_vflip, ARRAY_SIZE(points_vflip));
+
+    struct test_point points_transposed[] = {
+        { 3, 3, red },
+        { 2, 3, green },
+        { 3, 2, blue },
+        { 2, 2, white },
+        { 1, 3, black },
+        { 2, 1, black },
+        { 3, 0, black },
+    };
+    test_opengl_offscreen(root, ORIENT_TRANSPOSED,
+                          points_transposed, ARRAY_SIZE(points_transposed));
+
+    struct test_point points_antitransposed[] = {
+        { 0, 0, red },
+        { 1, 0, green },
+        { 0, 1, blue },
+        { 1, 1, white },
+        { 2, 0, black },
+        { 1, 2, black },
+        { 0, 3, black },
+    };
+    test_opengl_offscreen(root, ORIENT_ANTI_TRANSPOSED,
+                          points_antitransposed, ARRAY_SIZE(points_antitransposed));
+
+    libvlc_release(vlc);
+    return 0;
+}



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/deeeadaf2301cba690b55742799516b06b92c1dd...e3ee564576d64ef219172548dbceb2bcba596ccf

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/deeeadaf2301cba690b55742799516b06b92c1dd...e3ee564576d64ef219172548dbceb2bcba596ccf
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