shithub: dav1d

Download patch

ref: e4a4c8c60b21d226f24cc315af30cb7f1591b29b
parent: 7f50fc37199b4581d606ffbdf665b8141939b1f9
author: Marvin Scholz <[email protected]>
date: Fri May 15 07:57:02 EDT 2020

Dav1dPlay: Split placebo renderer into two

This allows selecting at runtime if placebo should use OpenGL
or Vulkan for rendering.

--- a/examples/dav1dplay.c
+++ b/examples/dav1dplay.c
@@ -155,15 +155,9 @@
                 break;
             case ARG_HIGH_QUALITY:
                 settings->highquality = true;
-#ifndef HAVE_RENDERER_PLACEBO
-                fprintf(stderr, "warning: --highquality requires libplacebo\n");
-#endif
                 break;
             case 'z':
                 settings->zerocopy = true;
-#ifndef HAVE_RENDERER_PLACEBO
-                fprintf(stderr, "warning: --zerocopy requires libplacebo\n");
-#endif
                 break;
             case 'r':
                 settings->renderer_name = optarg;
@@ -209,7 +203,7 @@
  * \note  The Dav1dPlayRenderContext must be destroyed
  *        again by using dp_rd_ctx_destroy.
  */
-static Dav1dPlayRenderContext *dp_rd_ctx_create(void *rd_data, int argc, char **argv)
+static Dav1dPlayRenderContext *dp_rd_ctx_create(int argc, char **argv)
 {
     Dav1dPlayRenderContext *rd_ctx;
 
@@ -258,7 +252,7 @@
         printf("Using %s renderer\n", renderer_info->name);
     }
 
-    rd_ctx->rd_priv = (renderer_info) ? renderer_info->create_renderer(rd_data) : NULL;
+    rd_ctx->rd_priv = (renderer_info) ? renderer_info->create_renderer() : NULL;
     if (rd_ctx->rd_priv == NULL) {
         SDL_DestroyMutex(rd_ctx->lock);
         dp_fifo_destroy(rd_ctx->fifo);
@@ -500,7 +494,6 @@
 int main(int argc, char **argv)
 {
     SDL_Thread *decoder_thread;
-    SDL_Window *win = NULL;
 
     // Check for version mismatch between library and tool
     const char *version = dav1d_version();
@@ -514,22 +507,8 @@
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
         return 10;
 
-    // Create Window and Renderer
-    int window_flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
-#if defined(HAVE_PLACEBO_VULKAN)
-    window_flags |= SDL_WINDOW_VULKAN;
-#elif defined(HAVE_PLACEBO_OPENGL)
-# ifndef NDEBUG
-    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
-# endif
-    window_flags |= SDL_WINDOW_OPENGL;
-#endif
-    win = SDL_CreateWindow("Dav1dPlay", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
-        WINDOW_WIDTH, WINDOW_HEIGHT, window_flags);
-    SDL_SetWindowResizable(win, SDL_TRUE);
-
     // Create render context
-    Dav1dPlayRenderContext *rd_ctx = dp_rd_ctx_create(win, argc, argv);
+    Dav1dPlayRenderContext *rd_ctx = dp_rd_ctx_create(argc, argv);
     if (rd_ctx == NULL) {
         fprintf(stderr, "Failed creating render context\n");
         return 5;
@@ -586,7 +565,6 @@
     SDL_WaitThread(decoder_thread, &decoder_ret);
 
     dp_rd_ctx_destroy(rd_ctx);
-    SDL_DestroyWindow(win);
 
     return decoder_ret;
 }
--- a/examples/dp_renderer.h
+++ b/examples/dp_renderer.h
@@ -29,7 +29,7 @@
 
 #include "dav1d/dav1d.h"
 
-#include <SDL_config.h>
+#include <SDL.h>
 #ifdef HAVE_PLACEBO
 # include <libplacebo/config.h>
 #endif
@@ -78,7 +78,7 @@
     // Cookie passed to the renderer implementation callbacks
     void *cookie;
     // Callback to create the renderer
-    void* (*create_renderer)(void *data);
+    void* (*create_renderer)();
     // Callback to destroy the renderer
     void (*destroy_renderer)(void *cookie);
     // Callback to the render function that renders a prevously sent frame
@@ -91,12 +91,14 @@
     void (*release_pic)(Dav1dPicture *pic, void *cookie);
 } Dav1dPlayRenderInfo;
 
-extern const Dav1dPlayRenderInfo rdr_placebo;
+extern const Dav1dPlayRenderInfo rdr_placebo_vk;
+extern const Dav1dPlayRenderInfo rdr_placebo_gl;
 extern const Dav1dPlayRenderInfo rdr_sdl;
 
 // Available renderes ordered by priority
 static const Dav1dPlayRenderInfo* const dp_renderers[] = {
-    &rdr_placebo,
+    &rdr_placebo_vk,
+    &rdr_placebo_gl,
     &rdr_sdl,
 };
 
@@ -112,4 +114,16 @@
         }
     }
     return NULL;
+}
+
+static inline SDL_Window *dp_create_sdl_window(int window_flags)
+{
+    SDL_Window *win;
+    window_flags |= SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
+
+    win = SDL_CreateWindow("Dav1dPlay", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+        WINDOW_WIDTH, WINDOW_HEIGHT, window_flags);
+    SDL_SetWindowResizable(win, SDL_TRUE);
+
+    return win;
 }
--- a/examples/dp_renderer_placebo.c
+++ b/examples/dp_renderer_placebo.c
@@ -29,19 +29,16 @@
 #ifdef HAVE_RENDERER_PLACEBO
 #include <assert.h>
 
-#include <SDL.h>
-
 #include <libplacebo/renderer.h>
 #include <libplacebo/utils/upload.h>
 
-#if defined(HAVE_PLACEBO_VULKAN)
+#ifdef HAVE_PLACEBO_VULKAN
 # include <libplacebo/vulkan.h>
 # include <SDL_vulkan.h>
-#elif defined(HAVE_PLACEBO_OPENGL)
+#endif
+#ifdef HAVE_PLACEBO_OPENGL
 # include <libplacebo/opengl.h>
 # include <SDL_opengl.h>
-#else
-# error Placebo rendering only implemented for Vulkan or OpenGL!
 #endif
 
 
@@ -50,11 +47,13 @@
  */
 typedef struct renderer_priv_ctx
 {
+    // SDL window
+    SDL_Window *win;
     // Placebo context
     struct pl_context *ctx;
     // Placebo renderer
     struct pl_renderer *renderer;
-#if defined(HAVE_PLACEBO_VULKAN)
+#ifdef HAVE_PLACEBO_VULKAN
     // Placebo Vulkan handle
     const struct pl_vulkan *vk;
     // Placebo Vulkan instance
@@ -61,7 +60,8 @@
     const struct pl_vk_inst *vk_inst;
     // Vulkan surface
     VkSurfaceKHR surf;
-#elif defined(HAVE_PLACEBO_OPENGL)
+#endif
+#ifdef HAVE_PLACEBO_OPENGL
     // Placebo OpenGL handle
     const struct pl_opengl *gl;
 #endif
@@ -81,13 +81,20 @@
     const struct pl_tex *v_tex;
 } Dav1dPlayRendererPrivateContext;
 
-static void *placebo_renderer_create(void *data)
+static Dav1dPlayRendererPrivateContext*
+    placebo_renderer_create_common(int window_flags)
 {
+    // Create Window
+    SDL_Window *sdlwin = dp_create_sdl_window(window_flags);
+    if (sdlwin == NULL)
+        return NULL;
+
     // Alloc
     Dav1dPlayRendererPrivateContext *rd_priv_ctx = malloc(sizeof(Dav1dPlayRendererPrivateContext));
     if (rd_priv_ctx == NULL) {
         return NULL;
     }
+    rd_priv_ctx->win = sdlwin;
 
     // Init libplacebo
     rd_priv_ctx->ctx = pl_context_create(PL_API_VER, &(struct pl_context_params) {
@@ -112,13 +119,95 @@
         return NULL;
     }
 
+    rd_priv_ctx->y_tex = NULL;
+    rd_priv_ctx->u_tex = NULL;
+    rd_priv_ctx->v_tex = NULL;
 
-#if defined(HAVE_PLACEBO_VULKAN)
+    rd_priv_ctx->renderer = NULL;
+
+#ifdef HAVE_PLACEBO_OPENGL
+    rd_priv_ctx->gl = NULL;
+#endif
+#ifdef HAVE_PLACEBO_VULKAN
+    rd_priv_ctx->vk = NULL;
+#endif
+
+    return rd_priv_ctx;
+}
+
+#ifdef HAVE_PLACEBO_OPENGL
+static void *placebo_renderer_create_gl()
+{
+    SDL_Window *sdlwin = NULL;
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
+
+    // Common init
+    Dav1dPlayRendererPrivateContext *rd_priv_ctx =
+        placebo_renderer_create_common(SDL_WINDOW_OPENGL);
+
+    if (rd_priv_ctx == NULL)
+        return NULL;
+    sdlwin = rd_priv_ctx->win;
+
+    // Init OpenGL
+    struct pl_opengl_params params = pl_opengl_default_params;
+# ifndef NDEBUG
+    params.debug = true;
+# endif
+
+    SDL_GLContext glcontext = SDL_GL_CreateContext(sdlwin);
+    SDL_GL_MakeCurrent(sdlwin, glcontext);
+
+    rd_priv_ctx->gl = pl_opengl_create(rd_priv_ctx->ctx, &params);
+    if (!rd_priv_ctx->gl) {
+        fprintf(stderr, "Failed creating opengl device!\n");
+        exit(2);
+    }
+
+    rd_priv_ctx->swapchain = pl_opengl_create_swapchain(rd_priv_ctx->gl,
+        &(struct pl_opengl_swapchain_params) {
+            .swap_buffers = (void (*)(void *)) SDL_GL_SwapWindow,
+            .priv = sdlwin,
+        });
+
+    if (!rd_priv_ctx->swapchain) {
+        fprintf(stderr, "Failed creating opengl swapchain!\n");
+        exit(2);
+    }
+
+    int w = WINDOW_WIDTH, h = WINDOW_HEIGHT;
+    SDL_GL_GetDrawableSize(sdlwin, &w, &h);
+
+    if (!pl_swapchain_resize(rd_priv_ctx->swapchain, &w, &h)) {
+        fprintf(stderr, "Failed resizing vulkan swapchain!\n");
+        exit(2);
+    }
+
+    rd_priv_ctx->gpu = rd_priv_ctx->gl->gpu;
+
+    if (w != WINDOW_WIDTH || h != WINDOW_HEIGHT)
+        printf("Note: window dimensions differ (got %dx%d)\n", w, h);
+
+    return rd_priv_ctx;
+}
+#endif
+
+#ifdef HAVE_PLACEBO_VULKAN
+static void *placebo_renderer_create_vk()
+{
+    SDL_Window *sdlwin = NULL;
+
+    // Common init
+    Dav1dPlayRendererPrivateContext *rd_priv_ctx =
+        placebo_renderer_create_common(SDL_WINDOW_VULKAN);
+
+    if (rd_priv_ctx == NULL)
+        return NULL;
+    sdlwin = rd_priv_ctx->win;
+
     // Init Vulkan
     struct pl_vk_inst_params iparams = pl_vk_inst_default_params;
 
-    SDL_Window *sdlwin = data;
-
     unsigned num = 0;
     if (!SDL_Vulkan_GetInstanceExtensions(sdlwin, &num, NULL)) {
         fprintf(stderr, "Failed enumerating Vulkan extensions: %s\n", SDL_GetError());
@@ -183,56 +272,13 @@
     }
 
     rd_priv_ctx->gpu = rd_priv_ctx->vk->gpu;
-#elif defined(HAVE_PLACEBO_OPENGL)
-    // Init OpenGL
-    struct pl_opengl_params params = pl_opengl_default_params;
-# ifndef NDEBUG
-    params.debug = true;
-# endif
 
-    SDL_Window *sdlwin = data;
-    SDL_GLContext glcontext = SDL_GL_CreateContext(sdlwin);
-    SDL_GL_MakeCurrent(sdlwin, glcontext);
-
-    rd_priv_ctx->gl = pl_opengl_create(rd_priv_ctx->ctx, &params);
-    if (!rd_priv_ctx->gl) {
-        fprintf(stderr, "Failed creating opengl device!\n");
-        exit(2);
-    }
-
-    rd_priv_ctx->swapchain = pl_opengl_create_swapchain(rd_priv_ctx->gl,
-        &(struct pl_opengl_swapchain_params) {
-            .swap_buffers = (void (*)(void *)) SDL_GL_SwapWindow,
-            .priv = sdlwin,
-        });
-
-    if (!rd_priv_ctx->swapchain) {
-        fprintf(stderr, "Failed creating opengl swapchain!\n");
-        exit(2);
-    }
-
-    int w = WINDOW_WIDTH, h = WINDOW_HEIGHT;
-    SDL_GL_GetDrawableSize(sdlwin, &w, &h);
-
-    if (!pl_swapchain_resize(rd_priv_ctx->swapchain, &w, &h)) {
-        fprintf(stderr, "Failed resizing vulkan swapchain!\n");
-        exit(2);
-    }
-
-    rd_priv_ctx->gpu = rd_priv_ctx->gl->gpu;
-#endif
-
     if (w != WINDOW_WIDTH || h != WINDOW_HEIGHT)
         printf("Note: window dimensions differ (got %dx%d)\n", w, h);
 
-    rd_priv_ctx->y_tex = NULL;
-    rd_priv_ctx->u_tex = NULL;
-    rd_priv_ctx->v_tex = NULL;
-
-    rd_priv_ctx->renderer = NULL;
-
     return rd_priv_ctx;
 }
+#endif
 
 static void placebo_renderer_destroy(void *cookie)
 {
@@ -245,14 +291,20 @@
     pl_tex_destroy(rd_priv_ctx->gpu, &(rd_priv_ctx->v_tex));
     pl_swapchain_destroy(&(rd_priv_ctx->swapchain));
 
-#if defined(HAVE_PLACEBO_VULKAN)
-    pl_vulkan_destroy(&(rd_priv_ctx->vk));
-    vkDestroySurfaceKHR(rd_priv_ctx->vk_inst->instance, rd_priv_ctx->surf, NULL);
-    pl_vk_inst_destroy(&(rd_priv_ctx->vk_inst));
-#elif defined(HAVE_PLACEBO_OPENGL)
-    pl_opengl_destroy(&(rd_priv_ctx->gl));
+#ifdef HAVE_PLACEBO_VULKAN
+    if (rd_priv_ctx->vk) {
+        pl_vulkan_destroy(&(rd_priv_ctx->vk));
+        vkDestroySurfaceKHR(rd_priv_ctx->vk_inst->instance, rd_priv_ctx->surf, NULL);
+        pl_vk_inst_destroy(&(rd_priv_ctx->vk_inst));
+    }
 #endif
+#ifdef HAVE_PLACEBO_OPENGL
+    if (rd_priv_ctx->gl)
+        pl_opengl_destroy(&(rd_priv_ctx->gl));
+#endif
 
+    SDL_DestroyWindow(rd_priv_ctx->win);
+
     pl_context_destroy(&(rd_priv_ctx->ctx));
 }
 
@@ -492,9 +544,10 @@
     SDL_UnlockMutex(rd_priv_ctx->lock);
 }
 
-const Dav1dPlayRenderInfo rdr_placebo = {
-    .name = "placebo",
-    .create_renderer = placebo_renderer_create,
+#ifdef HAVE_PLACEBO_OPENGL
+const Dav1dPlayRenderInfo rdr_placebo_vk = {
+    .name = "placebo-vk",
+    .create_renderer = placebo_renderer_create_vk,
     .destroy_renderer = placebo_renderer_destroy,
     .render = placebo_render,
     .update_frame = placebo_upload_planes,
@@ -501,7 +554,25 @@
     .alloc_pic = placebo_alloc_pic,
     .release_pic = placebo_release_pic,
 };
+#else
+const Dav1dPlayRenderInfo rdr_placebo_vk = { NULL };
+#endif
 
+#ifdef HAVE_PLACEBO_VULKAN
+const Dav1dPlayRenderInfo rdr_placebo_gl = {
+    .name = "placebo-gl",
+    .create_renderer = placebo_renderer_create_gl,
+    .destroy_renderer = placebo_renderer_destroy,
+    .render = placebo_render,
+    .update_frame = placebo_upload_planes,
+    .alloc_pic = placebo_alloc_pic,
+    .release_pic = placebo_release_pic,
+};
 #else
-const Dav1dPlayRenderInfo rdr_placebo = { NULL };
+const Dav1dPlayRenderInfo rdr_placebo_gl = { NULL };
+#endif
+
+#else
+const Dav1dPlayRenderInfo rdr_placebo_vk = { NULL };
+const Dav1dPlayRenderInfo rdr_placebo_gl = { NULL };
 #endif
--- a/examples/dp_renderer_sdl.c
+++ b/examples/dp_renderer_sdl.c
@@ -28,13 +28,13 @@
 
 #include <assert.h>
 
-#include <SDL.h>
-
 /**
  * Renderer context for SDL
  */
 typedef struct renderer_priv_ctx
 {
+    // SDL window
+    SDL_Window *win;
     // SDL renderer
     SDL_Renderer *renderer;
     // Lock protecting access to the texture
@@ -43,9 +43,11 @@
     SDL_Texture *tex;
 } Dav1dPlayRendererPrivateContext;
 
-static void *sdl_renderer_create(void *data)
+static void *sdl_renderer_create()
 {
-    SDL_Window *win = data;
+    SDL_Window *win = dp_create_sdl_window(0);
+    if (win == NULL)
+        return NULL;
 
     // Alloc
     Dav1dPlayRendererPrivateContext *rd_priv_ctx = malloc(sizeof(Dav1dPlayRendererPrivateContext));
@@ -52,6 +54,7 @@
     if (rd_priv_ctx == NULL) {
         return NULL;
     }
+    rd_priv_ctx->win = win;
 
     // Create renderer
     rd_priv_ctx->renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);