diff options
| author | Mikhail Burakov <mburakov@mailbox.org> | 2023-03-24 07:47:29 +0100 | 
|---|---|---|
| committer | Mikhail Burakov <mburakov@mailbox.org> | 2023-03-24 07:47:29 +0100 | 
| commit | c26b6ef574fe2fdab1d1cd8cd4bce8fb1645e2f7 (patch) | |
| tree | 6896754bcf3ed8da5eff65097a4eb3cdf38149ad | |
| parent | 844143e0c6cc1efa90bd27c9aa0cade7f7dd7930 (diff) | |
Precreate window buffers on surfaces allocation
| -rw-r--r-- | decode.c | 43 | ||||
| -rw-r--r-- | decode.h | 4 | ||||
| -rw-r--r-- | main.c | 17 | ||||
| -rw-r--r-- | window.c | 64 | ||||
| -rw-r--r-- | window.h | 5 | 
5 files changed, 81 insertions, 52 deletions
| @@ -33,6 +33,7 @@  #include "frame.h"  #include "util.h" +#include "window.h"  struct Surface {    VASurfaceID surface_id; @@ -48,6 +49,7 @@ struct TimingStats {  };  struct DecodeContext { +  struct Window* window;    int drm_fd;    VADisplay display;    mfxSession session; @@ -59,7 +61,6 @@ struct DecodeContext {    uint32_t packet_alloc;    uint32_t packet_offset;    struct Surface** sufaces; -  struct Frame* decoded;    unsigned long long recording_started;    unsigned long long frame_header_ts; @@ -189,6 +190,7 @@ static mfxStatus OnAllocatorAlloc(mfxHDL pthis, mfxFrameAllocRequest* request,    }    // mburakov: Separate loop for frames to ensure proper cleanup in destructor. +  struct Frame frames[request->NumFrameSuggested];    for (size_t i = 0; i < request->NumFrameSuggested; i++) {      surfaces[i]->frame =          ExportFrame(decode_context->display, surfaces[i]->surface_id); @@ -196,6 +198,12 @@ static mfxStatus OnAllocatorAlloc(mfxHDL pthis, mfxFrameAllocRequest* request,        LOG("Failed to export frame");        return MFX_ERR_MEMORY_ALLOC;      } +    frames[i] = *surfaces[i]->frame; +  } +  if (!WindowAssignFrames(decode_context->window, request->NumFrameSuggested, +                          frames)) { +    LOG("Failed to assign frames to window"); +    return MFX_ERR_MEMORY_ALLOC;    }    decode_context->sufaces = RELEASE(surfaces); @@ -228,7 +236,7 @@ static mfxStatus OnAllocatorFree(mfxHDL pthis,    return MFX_ERR_NONE;  } -struct DecodeContext* DecodeContextCreate(void) { +struct DecodeContext* DecodeContextCreate(struct Window* window) {    struct AUTO(DecodeContext)* decode_context =        malloc(sizeof(struct DecodeContext));    if (!decode_context) { @@ -236,6 +244,7 @@ struct DecodeContext* DecodeContextCreate(void) {      return NULL;    }    *decode_context = (struct DecodeContext){ +      .window = window,        .drm_fd = -1,        .allocator.pthis = decode_context,        .allocator.Alloc = OnAllocatorAlloc, @@ -377,15 +386,20 @@ static struct Surface* GetFreeSurface(struct DecodeContext* decode_context) {    return *psurface;  } -static void UnlockAllSurfaces(struct DecodeContext* decode_context, -                              const struct Surface* keep_locked) { -  struct Surface** psurface = decode_context->sufaces; -  for (; *psurface; psurface++) { -    if (*psurface != keep_locked) (*psurface)->locked = false; +static size_t UnlockAllSurfaces(struct DecodeContext* decode_context, +                                const struct Surface* keep_locked) { +  size_t result = 0; +  for (size_t i = 0; decode_context->sufaces[i]; i++) { +    if (decode_context->sufaces[i] != keep_locked) { +      decode_context->sufaces[i]->locked = false; +    } else { +      result = i; +    }    } +  return result;  } -void HandleTimingStats(struct DecodeContext* decode_context) { +static void HandleTimingStats(struct DecodeContext* decode_context) {    TimingStatsRecord(        &decode_context->receive,        decode_context->frame_received_ts - decode_context->frame_header_ts); @@ -481,9 +495,11 @@ bool DecodeContextDecode(struct DecodeContext* decode_context, int fd) {        return false;      } -    surface = surface_out->Data.MemId; -    decode_context->decoded = surface->frame; -    UnlockAllSurfaces(decode_context, surface); +    size_t locked = UnlockAllSurfaces(decode_context, surface_out->Data.MemId); +    if (!WindowShowFrame(decode_context->window, locked)) { +      LOG("Failed to show frame"); +      return false; +    }      decode_context->frame_decoded_ts = MicrosNow();      decode_context->frame_counter++; @@ -492,11 +508,6 @@ bool DecodeContextDecode(struct DecodeContext* decode_context, int fd) {    }  } -const struct Frame* DecodeContextGetFrame( -    struct DecodeContext* decode_context) { -  return decode_context->decoded; -} -  void DecodeContextDestroy(struct DecodeContext** decode_context) {    if (!decode_context || !*decode_context) return;    if ((*decode_context)->packet_data) free((*decode_context)->packet_data); @@ -23,10 +23,10 @@  struct DecodeContext;  struct Frame; +struct Window; -struct DecodeContext* DecodeContextCreate(void); +struct DecodeContext* DecodeContextCreate(struct Window* window);  bool DecodeContextDecode(struct DecodeContext* decode_context, int fd); -const struct Frame* DecodeContextGetFrame(struct DecodeContext* decode_context);  void DecodeContextDestroy(struct DecodeContext** decode_context);  #endif  // RECEIVER_DECODE_H_ @@ -35,18 +35,18 @@ int main(int argc, char* argv[]) {    (void)argc;    (void)argv; -  struct AUTO(DecodeContext)* decode_context = DecodeContextCreate(); -  if (!decode_context) { -    LOG("Failed to create decode context"); -    return EXIT_FAILURE; -  } -    struct AUTO(Window)* window = WindowCreate();    if (!window) {      LOG("Failed to create window");      return EXIT_FAILURE;    } +  struct AUTO(DecodeContext)* decode_context = DecodeContextCreate(window); +  if (!decode_context) { +    LOG("Failed to create decode context"); +    return EXIT_FAILURE; +  } +    int events_fd = WindowGetEventsFd(window);    if (events_fd == -1) {      LOG("Failed to get events fd"); @@ -84,11 +84,6 @@ int main(int argc, char* argv[]) {        LOG("Failed to process window events");        return EXIT_FAILURE;      } -    const struct Frame* frame = DecodeContextGetFrame(decode_context); -    if (frame && !WindowRenderFrame(window, frame)) { -      LOG("Failed to render frame"); -      return EXIT_FAILURE; -    }    }    return EXIT_SUCCESS; @@ -37,7 +37,7 @@ struct Window {    struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1;    struct xdg_surface* xdg_surface;    struct xdg_toplevel* xdg_toplevel; -  struct wl_buffer* wl_buffer; +  struct wl_buffer** wl_buffers;  };  static void wl_registryDestroy(struct wl_registry** wl_registry) { @@ -163,20 +163,11 @@ static void OnToplevelWmCapabilities(void* data,  }  struct Window* WindowCreate(void) { -  struct AUTO(Window)* window = malloc(sizeof(struct Window)); +  struct AUTO(Window)* window = calloc(1, sizeof(struct Window));    if (!window) {      LOG("Failed to allocate window (%s)", strerror(errno));      return NULL;    } -  *window = (struct Window){ -      .wl_display = NULL, -      .wl_surface = NULL, -      .xdg_wm_base = NULL, -      .zwp_linux_dmabuf_v1 = NULL, -      .xdg_surface = NULL, -      .xdg_toplevel = NULL, -      .wl_buffer = NULL, -  };    window->wl_display = wl_display_connect(NULL);    if (!window->wl_display) { @@ -272,12 +263,20 @@ static void OnZwpLinuxBufferParamsFailed(    (void)zwp_linux_buffer_params_v1;  } -bool WindowRenderFrame(struct Window* window, const struct Frame* frame) { +static void DestroyBuffers(struct Window* window) { +  if (!window->wl_buffers) return; +  for (size_t i = 0; window->wl_buffers[i]; i++) +    wl_buffer_destroy(window->wl_buffers[i]); +  free(RELEASE(window->wl_buffers)); +} + +static struct wl_buffer* CreateBuffer(struct Window* window, +                                      const struct Frame* frame) {    struct AUTO(zwp_linux_buffer_params_v1)* zwp_linux_buffer_params_v1 =        zwp_linux_dmabuf_v1_create_params(window->zwp_linux_dmabuf_v1);    if (!zwp_linux_buffer_params_v1) {      LOG("Failed to create wayland dmabuf params (%s)", strerror(errno)); -    return false; +    return NULL;    }    struct AUTO(wl_buffer)* wl_buffer = NULL; @@ -291,7 +290,7 @@ bool WindowRenderFrame(struct Window* window, const struct Frame* frame) {            &wl_buffer)) {      LOG("Failed to add buffer wayland dmabuf params listener (%s)",          strerror(errno)); -    return false; +    return NULL;    }    for (size_t i = 0; i < frame->nplanes; i++) { @@ -306,26 +305,47 @@ bool WindowRenderFrame(struct Window* window, const struct Frame* frame) {                                      frame->fourcc, 0);    if (wl_display_roundtrip(window->wl_display) == -1) {      LOG("Failed to roundtrip wayland display (%s)", strerror(errno)); -    return false; +    return NULL;    }    if (!wl_buffer) {      LOG("Failed to create wl_buffer"); -    return false; +    return NULL;    } -  SWAP(window->wl_buffer, wl_buffer); -  wl_surface_attach(window->wl_surface, window->wl_buffer, 0, 0); -  wl_surface_damage(window->wl_surface, 0, 0, INT32_MAX, INT32_MAX); -  wl_surface_commit(window->wl_surface); -  if (wl_display_roundtrip(window->wl_display) == -1) { -    LOG("Failed to roundtrip wayland display (%s)", strerror(errno)); +  return RELEASE(wl_buffer); +} + +bool WindowAssignFrames(struct Window* window, size_t nframes, +                        const struct Frame* frames) { +  DestroyBuffers(window); +  window->wl_buffers = calloc(nframes + 1, sizeof(struct wl_buffer*)); +  if (!window->wl_buffers) { +    LOG("Failed to alloc window buffers (%s)", strerror(errno));      return false;    } +  for (size_t i = 0; i < nframes; i++) { +    window->wl_buffers[i] = CreateBuffer(window, &frames[i]); +    if (!window->wl_buffers[i]) { +      LOG("Failed to create window buffer"); +      DestroyBuffers(window); +      return false; +    } +  }    return true;  } +bool WindowShowFrame(struct Window* window, size_t index) { +  wl_surface_attach(window->wl_surface, window->wl_buffers[index], 0, 0); +  wl_surface_damage(window->wl_surface, 0, 0, INT32_MAX, INT32_MAX); +  wl_surface_commit(window->wl_surface); +  bool result = wl_display_roundtrip(window->wl_display) != -1; +  if (!result) LOG("Failed to roundtrip wayland display (%s)", strerror(errno)); +  return result; +} +  void WindowDestroy(struct Window** window) {    if (!window || !*window) return; +  DestroyBuffers(*window);    if ((*window)->xdg_toplevel) xdg_toplevel_destroy((*window)->xdg_toplevel);    if ((*window)->xdg_surface) xdg_surface_destroy((*window)->xdg_surface);    if ((*window)->zwp_linux_dmabuf_v1) @@ -19,6 +19,7 @@  #define RECEIVER_WINDOW_H_  #include <stdbool.h> +#include <stddef.h>  struct Window;  struct Frame; @@ -26,7 +27,9 @@ struct Frame;  struct Window* WindowCreate(void);  int WindowGetEventsFd(const struct Window* window);  bool WindowProcessEvents(const struct Window* window); -bool WindowRenderFrame(struct Window* window, const struct Frame* frame); +bool WindowAssignFrames(struct Window* window, size_t nframes, +                        const struct Frame* frames); +bool WindowShowFrame(struct Window* window, size_t index);  void WindowDestroy(struct Window** window);  #endif  // RECEIVER_WINDOW_H_ | 
