summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Burakov <mburakov@mailbox.org>2023-03-24 07:47:29 +0100
committerMikhail Burakov <mburakov@mailbox.org>2023-03-24 07:47:29 +0100
commitc26b6ef574fe2fdab1d1cd8cd4bce8fb1645e2f7 (patch)
tree6896754bcf3ed8da5eff65097a4eb3cdf38149ad
parent844143e0c6cc1efa90bd27c9aa0cade7f7dd7930 (diff)
Precreate window buffers on surfaces allocation
-rw-r--r--decode.c43
-rw-r--r--decode.h4
-rw-r--r--main.c17
-rw-r--r--window.c64
-rw-r--r--window.h5
5 files changed, 81 insertions, 52 deletions
diff --git a/decode.c b/decode.c
index c73cce3..6fc884f 100644
--- a/decode.c
+++ b/decode.c
@@ -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);
diff --git a/decode.h b/decode.h
index 6926091..b31b782 100644
--- a/decode.h
+++ b/decode.h
@@ -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_
diff --git a/main.c b/main.c
index fcc7511..2a5e7ff 100644
--- a/main.c
+++ b/main.c
@@ -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;
diff --git a/window.c b/window.c
index 610fe85..4c89c18 100644
--- a/window.c
+++ b/window.c
@@ -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)
diff --git a/window.h b/window.h
index 7ac3dbf..80562f3 100644
--- a/window.h
+++ b/window.h
@@ -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_