Skip to content

Commit c81fa43

Browse files
committed
add support for "unresolved" texture frames in texture registry
Up until now it was only allowed to push an OpenGL frame with it's name, format etc, which the engine will fetch from the external texture as soon as possible. Now, you can push an "unresolved" frame, which is basically a callback and an opaque `void*` pointer, which the engine texture registry will call when the engine wants to know the exact texture name, format, target etc, to fill in ("resolve") those details. Basically allows you to be a bit smarter. Maybe, in the time between `texture_push_frame_unresolved` and the actual execution of the resolve callback, a new frame has arrived in the video player, and you want to use that instead.
1 parent 0a4cc19 commit c81fa43

File tree

3 files changed

+100
-24
lines changed

3 files changed

+100
-24
lines changed

include/texture_registry.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ struct texture_frame {
3737
void *userdata;
3838
};
3939

40+
struct unresolved_texture_frame {
41+
int (*resolve)(size_t width, size_t height, void *userdata, struct texture_frame *frame_out);
42+
void (*destroy)(void *userdata);
43+
void *userdata;
44+
};
45+
4046
struct texture_registry *texture_registry_new(const struct texture_registry_interface *interface, void *userdata);
4147

4248
void texture_registry_destroy(struct texture_registry *reg);
@@ -54,6 +60,8 @@ int64_t texture_get_id(struct texture *texture);
5460

5561
int texture_push_frame(struct texture *texture, const struct texture_frame *frame);
5662

63+
int texture_push_unresolved_frame(struct texture *texture, const struct unresolved_texture_frame *frame);
64+
5765
void texture_destroy(struct texture *texture);
5866

5967
#endif

src/dmabuf_surface.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,24 @@ ATTR_MALLOC struct dmabuf_surface *dmabuf_surface_new(struct tracer *tracer, str
159159
return NULL;
160160
}
161161

162+
int on_resolve_texture_frame(size_t width, size_t height, void *userdata, struct texture_frame *frame_out) {
163+
/// TODO: Implement
164+
(void) width;
165+
(void) height;
166+
(void) userdata;
167+
frame_out->gl.target = GL_TEXTURE_2D;
168+
frame_out->gl.name = 0;
169+
frame_out->gl.format = GL_RGBA8_OES;
170+
frame_out->gl.width = 0;
171+
frame_out->gl.height = 0;
172+
frame_out->userdata = NULL;
173+
frame_out->destroy = NULL;
174+
return 0;
175+
}
176+
162177
int dmabuf_surface_push_dmabuf(struct dmabuf_surface *s, const struct dmabuf *buf, dmabuf_release_cb_t release_cb) {
163178
struct refcounted_dmabuf *b;
179+
int ok;
164180

165181
DEBUG_ASSERT_NOT_NULL(s);
166182
DEBUG_ASSERT_NOT_NULL(buf);
@@ -177,18 +193,31 @@ int dmabuf_surface_push_dmabuf(struct dmabuf_surface *s, const struct dmabuf *bu
177193
return ENOMEM;
178194
}
179195

180-
b->n_refs = REFCOUNT_INIT_1;
196+
b->n_refs = REFCOUNT_INIT_0;
181197
b->buf = *buf;
182198
b->release_callback = release_cb;
183199
b->drmdev = NULL;
184200
b->drm_fb_id = DRM_ID_NONE;
185201

186202
surface_lock(CAST_SURFACE_UNCHECKED(s));
187-
188-
if (s->next_buf != NULL) {
189-
refcounted_dmabuf_unref(s->next_buf);
203+
204+
ok = texture_push_unresolved_frame(
205+
s->texture,
206+
&(const struct unresolved_texture_frame) {
207+
.resolve = on_resolve_texture_frame,
208+
.destroy = surface_unref_void,
209+
.userdata = surface_ref(CAST_SURFACE_UNCHECKED(s)),
210+
}
211+
);
212+
if (ok != 0) {
213+
LOG_ERROR("Couldn't post new frame to texture.\n");
214+
surface_unref(CAST_SURFACE_UNCHECKED(s));
215+
surface_unlock(CAST_SURFACE_UNCHECKED(s));
216+
free(b);
217+
return ok;
190218
}
191-
s->next_buf = b;
219+
220+
refcounted_dmabuf_swap_ptrs(&s->next_buf, b);
192221

193222
surface_unlock(CAST_SURFACE_UNCHECKED(s));
194223

@@ -200,11 +229,6 @@ ATTR_PURE int64_t dmabuf_surface_get_texture_id(struct dmabuf_surface *s) {
200229
return texture_get_id(s->texture);
201230
}
202231

203-
static void on_release_layer(void *userdata) {
204-
DEBUG_ASSERT_NOT_NULL(userdata);
205-
refcounted_dmabuf_unref((struct refcounted_dmabuf*) userdata);
206-
}
207-
208232
static int dmabuf_surface_present_kms(struct surface *_s, const struct fl_layer_props *props, struct kms_req_builder *builder) {
209233
struct dmabuf_surface *s;
210234
uint32_t fb_id;
@@ -265,7 +289,7 @@ static int dmabuf_surface_present_kms(struct surface *_s, const struct fl_layer_
265289
.has_rotation = false, .rotation = PLANE_TRANSFORM_ROTATE_0,
266290
.has_in_fence_fd = false, .in_fence_fd = 0,
267291
},
268-
on_release_layer,
292+
refcounted_dmabuf_unref_void,
269293
NULL,
270294
refcounted_dmabuf_ref(s->next_buf)
271295
);

src/texture_registry.c

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,24 @@ struct texture_registry {
2323

2424
struct counted_texture_frame {
2525
refcount_t n_refs;
26+
27+
bool is_resolved;
2628
struct texture_frame frame;
29+
30+
struct unresolved_texture_frame unresolved_frame;
2731
};
2832

2933
void counted_texture_frame_destroy(struct counted_texture_frame *frame) {
30-
frame->frame.destroy(
31-
&frame->frame,
32-
frame->frame.userdata
33-
);
34+
if (frame->is_resolved) {
35+
if (frame->frame.destroy != NULL) {
36+
frame->frame.destroy(
37+
&frame->frame,
38+
frame->frame.userdata
39+
);
40+
}
41+
} else if (frame->unresolved_frame.destroy != NULL){
42+
frame->unresolved_frame.destroy(frame->unresolved_frame.userdata);
43+
}
3444
free(frame);
3545
}
3646

@@ -203,26 +213,28 @@ int64_t texture_get_id(struct texture *texture) {
203213
return texture->id;
204214
}
205215

206-
int texture_push_frame(struct texture *texture, const struct texture_frame *frame) {
216+
static int push_frame(struct texture *texture, bool is_resolved, const struct texture_frame *frame, const struct unresolved_texture_frame *unresolved_frame) {
207217
struct counted_texture_frame *counted_frame;
208218
int ok;
209219

220+
// I know there's memdup, but let's just be explicit here.
210221
counted_frame = malloc(sizeof *counted_frame);
211222
if (counted_frame == NULL) {
212223
return ENOMEM;
213224
}
214225

215-
counted_frame->n_refs = REFCOUNT_INIT_1;
216-
counted_frame->frame = *frame;
226+
counted_frame->n_refs = REFCOUNT_INIT_0;
227+
counted_frame->is_resolved = is_resolved;
228+
if (frame != NULL) {
229+
counted_frame->frame = *frame;
230+
}
231+
if (unresolved_frame != NULL) {
232+
counted_frame->unresolved_frame = *unresolved_frame;
233+
}
217234

218235
texture_lock(texture);
219236

220-
if (texture->next_frame != NULL) {
221-
counted_texture_frame_unref(texture->next_frame);
222-
texture->next_frame = NULL;
223-
}
224-
225-
texture->next_frame = counted_frame;
237+
counted_texture_frame_swap_ptrs(&texture->next_frame, counted_frame);
226238

227239
if (texture->dirty == false) {
228240
ok = texture->registry->interface.mark_frame_available(texture->registry->userdata, texture->id);
@@ -242,6 +254,24 @@ int texture_push_frame(struct texture *texture, const struct texture_frame *fram
242254
return 0;
243255
}
244256

257+
int texture_push_frame(struct texture *texture, const struct texture_frame *frame) {
258+
return push_frame(
259+
texture,
260+
true,
261+
frame,
262+
NULL
263+
);
264+
}
265+
266+
int texture_push_unresolved_frame(struct texture *texture, const struct unresolved_texture_frame *frame) {
267+
return push_frame(
268+
texture,
269+
false,
270+
NULL,
271+
frame
272+
);
273+
}
274+
245275
void texture_destroy(struct texture *texture) {
246276
texture_registry_unregister_texture(texture->registry, texture);
247277
if (texture->next_frame != NULL) {
@@ -268,6 +298,7 @@ static bool texture_gl_external_texture_frame_callback(
268298
FlutterOpenGLTexture *texture_out
269299
) {
270300
struct counted_texture_frame *frame;
301+
int ok;
271302

272303
(void) width;
273304
(void) height;
@@ -288,6 +319,19 @@ static bool texture_gl_external_texture_frame_callback(
288319
/// flutter has now fetched the texture, so if we want to present a new frame
289320
/// we need to call @ref texture_registry_engine_notify_frame_available again.
290321
texture->dirty = false;
322+
323+
if (!frame->is_resolved) {
324+
// resolve the frame to an actual OpenGL frame.
325+
ok = frame->unresolved_frame.resolve(width, height, frame->unresolved_frame.userdata, &frame->frame);
326+
if (ok != 0) {
327+
LOG_ERROR("Couldn't resolve texture frame.\n");
328+
counted_texture_frame_unrefp(&frame);
329+
counted_texture_frame_unrefp(&texture->next_frame);
330+
}
331+
332+
frame->unresolved_frame.destroy(frame->unresolved_frame.userdata);
333+
frame->is_resolved = true;
334+
}
291335

292336
texture_unlock(texture);
293337

0 commit comments

Comments
 (0)