don't create new window_listener instances during registration

This commit is contained in:
Anthony Pesch 2016-07-08 00:00:55 -07:00
parent b54ac3be06
commit 0907a66cd5
8 changed files with 59 additions and 90 deletions

View File

@ -16,7 +16,7 @@ DEFINE_OPTION_STRING(flash, "dc_flash.bin", "Path to flash ROM");
struct emu { struct emu {
struct window *window; struct window *window;
struct window_listener *listener; struct window_listener listener;
struct dreamcast *dc; struct dreamcast *dc;
atomic_int running; atomic_int running;
int throttled; int throttled;
@ -225,20 +225,21 @@ void emu_run(struct emu *emu, const char *path) {
} }
struct emu *emu_create(struct window *window) { struct emu *emu_create(struct window *window) {
static const struct window_callbacks callbacks = {
&emu_paint, &emu_paint_debug_menu, &emu_keydown, NULL, NULL, &emu_close};
struct emu *emu = calloc(1, sizeof(struct emu)); struct emu *emu = calloc(1, sizeof(struct emu));
emu->window = window; emu->window = window;
emu->listener = win_add_listener(emu->window, &callbacks, emu); emu->listener = (struct window_listener){
emu, &emu_paint, &emu_paint_debug_menu, &emu_keydown, NULL, NULL,
&emu_close, {}};
emu->running = ATOMIC_VAR_INIT(0); emu->running = ATOMIC_VAR_INIT(0);
win_add_listener(emu->window, &emu->listener);
return emu; return emu;
} }
void emu_destroy(struct emu *emu) { void emu_destroy(struct emu *emu) {
win_remove_listener(emu->window, emu->listener); win_remove_listener(emu->window, &emu->listener);
if (emu->dc) { if (emu->dc) {
dc_destroy(emu->dc); dc_destroy(emu->dc);

View File

@ -66,7 +66,7 @@ struct tracer_texture_entry {
struct tracer { struct tracer {
struct window *window; struct window *window;
struct window_listener *listener; struct window_listener listener;
struct texture_provider provider; struct texture_provider provider;
struct rb *rb; struct rb *rb;
struct tr *tr; struct tr *tr;
@ -851,21 +851,22 @@ void tracer_run(struct tracer *tracer, const char *path) {
} }
struct tracer *tracer_create(struct window *window) { struct tracer *tracer_create(struct window *window) {
static const struct window_callbacks callbacks = {
&tracer_paint, NULL, &tracer_keydown, NULL, NULL, &tracer_close};
// ensure param / poly / vertex size LUTs are generated // ensure param / poly / vertex size LUTs are generated
ta_build_tables(); ta_build_tables();
struct tracer *tracer = calloc(1, sizeof(struct tracer)); struct tracer *tracer = calloc(1, sizeof(struct tracer));
tracer->window = window; tracer->window = window;
tracer->listener = win_add_listener(window, &callbacks, tracer); tracer->listener = (struct window_listener){
tracer, &tracer_paint, NULL, &tracer_keydown,
NULL, NULL, &tracer_close, {}};
tracer->provider = tracer->provider =
(struct texture_provider){tracer, &tracer_texture_provider_find_texture}; (struct texture_provider){tracer, &tracer_texture_provider_find_texture};
tracer->rb = window->rb; tracer->rb = window->rb;
tracer->tr = tr_create(tracer->rb, &tracer->provider); tracer->tr = tr_create(tracer->rb, &tracer->provider);
win_add_listener(tracer->window, &tracer->listener);
// setup tile context buffers // setup tile context buffers
tracer->ctx.params = tracer->params; tracer->ctx.params = tracer->params;
@ -902,7 +903,7 @@ void tracer_destroy(struct tracer *tracer) {
if (tracer->trace) { if (tracer->trace) {
trace_destroy(tracer->trace); trace_destroy(tracer->trace);
} }
win_remove_listener(tracer->window, tracer->listener); win_remove_listener(tracer->window, &tracer->listener);
tr_destroy(tracer->tr); tr_destroy(tracer->tr);
free(tracer); free(tracer);
} }

View File

@ -29,7 +29,7 @@ struct shader_program {
struct rb { struct rb {
struct window *window; struct window *window;
struct window_listener *listener; struct window_listener listener;
SDL_GLContext ctx; SDL_GLContext ctx;
int debug_wireframe; int debug_wireframe;
@ -698,12 +698,12 @@ void rb_destroy_texture(struct rb *rb, texture_handle_t handle) {
} }
struct rb *rb_create(struct window *window) { struct rb *rb_create(struct window *window) {
static const struct window_callbacks callbacks = {
NULL, &rb_paint_debug_menu, NULL, NULL, NULL, NULL};
struct rb *rb = (struct rb *)calloc(1, sizeof(struct rb)); struct rb *rb = (struct rb *)calloc(1, sizeof(struct rb));
rb->window = window; rb->window = window;
rb->listener = win_add_listener(rb->window, &callbacks, rb); rb->listener = (struct window_listener){
rb, NULL, &rb_paint_debug_menu, NULL, NULL, NULL, NULL, {}};
win_add_listener(rb->window, &rb->listener);
if (!rb_init_context(rb)) { if (!rb_init_context(rb)) {
rb_destroy(rb); rb_destroy(rb);
@ -723,6 +723,6 @@ void rb_destroy(struct rb *rb) {
rb_destroy_shaders(rb); rb_destroy_shaders(rb);
rb_destroy_textures(rb); rb_destroy_textures(rb);
rb_destroy_context(rb); rb_destroy_context(rb);
win_remove_listener(rb->window, rb->listener); win_remove_listener(rb->window, &rb->listener);
free(rb); free(rb);
} }

View File

@ -26,7 +26,7 @@ static const int MAX_2D_SURFACES = 256;
struct microprofile { struct microprofile {
struct window *window; struct window *window;
struct window_listener *listener; struct window_listener listener;
texture_handle_t font_texture; texture_handle_t font_texture;
struct surface2d surfs[MAX_2D_SURFACES]; struct surface2d surfs[MAX_2D_SURFACES];
int num_surfs; int num_surfs;
@ -259,14 +259,14 @@ void mp_end_frame(struct microprofile *mp) {
} }
struct microprofile *mp_create(struct window *window) { struct microprofile *mp_create(struct window *window) {
static const struct window_callbacks callbacks = {
NULL, NULL, &mp_keydown, NULL, &mp_mousemove, NULL};
struct microprofile *mp = reinterpret_cast<struct microprofile *>( struct microprofile *mp = reinterpret_cast<struct microprofile *>(
calloc(1, sizeof(struct microprofile))); calloc(1, sizeof(struct microprofile)));
mp->window = window; mp->window = window;
mp->listener = win_add_listener(mp->window, &callbacks, mp); mp->listener = (struct window_listener){
mp, NULL, NULL, &mp_keydown, NULL, &mp_mousemove, NULL, {}};
win_add_listener(mp->window, &mp->listener);
// init microprofile // init microprofile
struct rb *rb = mp->window->rb; struct rb *rb = mp->window->rb;
@ -294,7 +294,7 @@ struct microprofile *mp_create(struct window *window) {
void mp_destroy(struct microprofile *mp) { void mp_destroy(struct microprofile *mp) {
rb_destroy_texture(mp->window->rb, mp->font_texture); rb_destroy_texture(mp->window->rb, mp->font_texture);
win_remove_listener(mp->window, mp->listener); win_remove_listener(mp->window, &mp->listener);
free(mp); free(mp);
} }

View File

@ -129,12 +129,12 @@ void nk_end_frame(struct nuklear *nk) {
} }
struct nuklear *nk_create(struct window *window) { struct nuklear *nk_create(struct window *window) {
static const struct window_callbacks callbacks = {
NULL, NULL, &nk_keydown, &nk_textinput, &nk_mousemove, NULL};
struct nuklear *nk = calloc(1, sizeof(struct nuklear)); struct nuklear *nk = calloc(1, sizeof(struct nuklear));
nk->window = window; nk->window = window;
nk->listener = win_add_listener(nk->window, &callbacks, nk); nk->listener = (struct window_listener){
nk, NULL, NULL, &nk_keydown, &nk_textinput, &nk_mousemove, NULL, {}};
win_add_listener(nk->window, &nk->listener);
// create default font texture // create default font texture
nk_font_atlas_init_default(&nk->atlas); nk_font_atlas_init_default(&nk->atlas);
@ -162,7 +162,7 @@ void nk_destroy(struct nuklear *nk) {
rb_destroy_texture(nk->window->rb, nk->font_texture); rb_destroy_texture(nk->window->rb, nk->font_texture);
win_remove_listener(nk->window, nk->listener); win_remove_listener(nk->window, &nk->listener);
free(nk); free(nk);
} }

View File

@ -12,16 +12,14 @@
#include <nuklear.h> #include <nuklear.h>
#include "renderer/backend.h" #include "renderer/backend.h"
#include "ui/window.h"
struct window;
struct window_listener;
#define NK_MAX_VERTICES 4096 #define NK_MAX_VERTICES 4096
#define NK_MAX_ELEMENTS 16384 #define NK_MAX_ELEMENTS 16384
struct nuklear { struct nuklear {
struct window *window; struct window *window;
struct window_listener *listener; struct window_listener listener;
// //
struct nk_context ctx; struct nk_context ctx;

View File

@ -39,10 +39,9 @@ static void win_handle_paint(struct window *win) {
nk_begin_frame(win->nk); nk_begin_frame(win->nk);
mp_begin_frame(win->mp); mp_begin_frame(win->mp);
list_for_each_entry(listener, &win->live_listeners, struct window_listener, list_for_each_entry(listener, &win->listeners, struct window_listener, it) {
it) { if (listener->paint) {
if (listener->cb.paint) { listener->paint(listener->data);
listener->cb.paint(listener->data);
} }
} }
@ -54,10 +53,10 @@ static void win_handle_paint(struct window *win) {
if (nk_begin(ctx, &layout, "debug menu", bounds, if (nk_begin(ctx, &layout, "debug menu", bounds,
NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE |
NK_WINDOW_TITLE)) { NK_WINDOW_TITLE)) {
list_for_each_entry(listener, &win->live_listeners, list_for_each_entry(listener, &win->listeners, struct window_listener,
struct window_listener, it) { it) {
if (listener->cb.paint_debug_menu) { if (listener->paint_debug_menu) {
listener->cb.paint_debug_menu(listener->data, ctx); listener->paint_debug_menu(listener->data, ctx);
} }
} }
} }
@ -72,10 +71,9 @@ static void win_handle_paint(struct window *win) {
static void win_handle_keydown(struct window *win, enum keycode code, static void win_handle_keydown(struct window *win, enum keycode code,
int16_t value) { int16_t value) {
list_for_each_entry(listener, &win->live_listeners, struct window_listener, list_for_each_entry(listener, &win->listeners, struct window_listener, it) {
it) { if (listener->keydown) {
if (listener->cb.keydown) { listener->keydown(listener->data, code, value);
listener->cb.keydown(listener->data, code, value);
} }
} }
} }
@ -122,28 +120,25 @@ static void win_handle_hatdown(struct window *win, int hat, uint8_t state,
} }
static void win_handle_textinput(struct window *win, const char *text) { static void win_handle_textinput(struct window *win, const char *text) {
list_for_each_entry(listener, &win->live_listeners, struct window_listener, list_for_each_entry(listener, &win->listeners, struct window_listener, it) {
it) { if (listener->textinput) {
if (listener->cb.textinput) { listener->textinput(listener->data, text);
listener->cb.textinput(listener->data, text);
} }
} }
} }
static void win_handle_mousemove(struct window *win, int x, int y) { static void win_handle_mousemove(struct window *win, int x, int y) {
list_for_each_entry(listener, &win->live_listeners, struct window_listener, list_for_each_entry(listener, &win->listeners, struct window_listener, it) {
it) { if (listener->mousemove) {
if (listener->cb.mousemove) { listener->mousemove(listener->data, x, y);
listener->cb.mousemove(listener->data, x, y);
} }
} }
} }
static void win_handle_close(struct window *win) { static void win_handle_close(struct window *win) {
list_for_each_entry(listener, &win->live_listeners, struct window_listener, list_for_each_entry(listener, &win->listeners, struct window_listener, it) {
it) { if (listener->close) {
if (listener->cb.close) { listener->close(listener->data);
listener->cb.close(listener->data);
} }
} }
} }
@ -829,25 +824,12 @@ void win_pump_events(struct window *win) {
win_handle_paint(win); win_handle_paint(win);
} }
struct window_listener *win_add_listener(struct window *win, void win_add_listener(struct window *win, struct window_listener *listener) {
const struct window_callbacks *cb, list_add(&win->listeners, &listener->it);
void *data) {
struct window_listener *listener =
list_first_entry(&win->free_listeners, struct window_listener, it);
CHECK_NOTNULL(listener);
list_remove(&win->free_listeners, &listener->it);
listener->cb = *cb;
listener->data = data;
list_add(&win->live_listeners, &listener->it);
return listener;
} }
void win_remove_listener(struct window *win, struct window_listener *listener) { void win_remove_listener(struct window *win, struct window_listener *listener) {
list_remove(&win->live_listeners, &listener->it); list_remove(&win->listeners, &listener->it);
list_add(&win->free_listeners, &listener->it);
} }
struct window *win_create() { struct window *win_create() {
@ -856,11 +838,6 @@ struct window *win_create() {
win->width = DEFAULT_WIDTH; win->width = DEFAULT_WIDTH;
win->height = DEFAULT_HEIGHT; win->height = DEFAULT_HEIGHT;
for (int i = 0; i < MAX_WINDOW_LISTENERS; i++) {
struct window_listener *listener = &win->listeners[i];
list_add(&win->free_listeners, &listener->it);
}
// initialize window // initialize window
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
LOG_WARNING("SDL initialization failed: %s", SDL_GetError()); LOG_WARNING("SDL initialization failed: %s", SDL_GetError());

View File

@ -22,18 +22,14 @@ struct SDL_Window;
#define NUM_JOYSTICK_KEYS ((K_JOY31 - K_JOY0) + 1) #define NUM_JOYSTICK_KEYS ((K_JOY31 - K_JOY0) + 1)
#define NUM_JOYSTICK_HATS (((K_HAT15 - K_HAT0) + 1) / 4) /* 4 keys per hat */ #define NUM_JOYSTICK_HATS (((K_HAT15 - K_HAT0) + 1) / 4) /* 4 keys per hat */
struct window_callbacks { struct window_listener {
void *data;
void (*paint)(void *data); void (*paint)(void *data);
void (*paint_debug_menu)(void *data, struct nk_context *ctx); void (*paint_debug_menu)(void *data, struct nk_context *ctx);
void (*keydown)(void *data, enum keycode code, int16_t value); void (*keydown)(void *data, enum keycode code, int16_t value);
void (*textinput)(void *data, const char *text); void (*textinput)(void *data, const char *text);
void (*mousemove)(void *data, int x, int y); void (*mousemove)(void *data, int x, int y);
void (*close)(void *data); void (*close)(void *data);
};
struct window_listener {
struct window_callbacks cb;
void *data;
struct list_node it; struct list_node it;
}; };
@ -51,9 +47,7 @@ struct window {
bool text_input; bool text_input;
// private state // private state
struct window_listener listeners[MAX_WINDOW_LISTENERS]; struct list listeners;
struct list free_listeners;
struct list live_listeners;
struct _SDL_Joystick *joystick; struct _SDL_Joystick *joystick;
uint8_t hat_state[NUM_JOYSTICK_HATS]; uint8_t hat_state[NUM_JOYSTICK_HATS];
@ -62,9 +56,7 @@ struct window {
void win_enable_debug_menu(struct window *win, bool active); void win_enable_debug_menu(struct window *win, bool active);
void win_enable_text_input(struct window *win, bool active); void win_enable_text_input(struct window *win, bool active);
void win_pump_events(struct window *win); void win_pump_events(struct window *win);
struct window_listener *win_add_listener(struct window *win, void win_add_listener(struct window *win, struct window_listener *listener);
const struct window_callbacks *cb,
void *data);
void win_remove_listener(struct window *win, struct window_listener *listener); void win_remove_listener(struct window *win, struct window_listener *listener);
struct window *win_create(); struct window *win_create();
void win_destroy(struct window *win); void win_destroy(struct window *win);