Exemplo n.º 1
0
Task* taskmgr_submit(TaskManager *mgr, TaskParams params) {
	assert(params.callback != NULL);

	Task *task = calloc(1, sizeof(Task));
	task->callback = params.callback;
	task->userdata_free_callback = params.userdata_free_callback;
	task->userdata = params.userdata;
	task->prio = params.prio;
	task->status = TASK_PENDING;

	if(!(task->mutex = SDL_CreateMutex())) {
		log_sdl_error(LOG_WARN, "SDL_CreateMutex");
		goto fail;
	}

	if(!(task->cond = SDL_CreateCond())) {
		log_sdl_error(LOG_WARN, "SDL_CreateCond");
		goto fail;
	}

	SDL_LockMutex(mgr->mutex);

	if(params.topmost) {
		alist_insert_at_priority_head(&mgr->queue, task, task->prio, task_prio_func);
	} else {
		alist_insert_at_priority_tail(&mgr->queue, task, task->prio, task_prio_func);
	}

	task->in_queue = true;
	SDL_AtomicIncRef(&mgr->numtasks);
	SDL_CondSignal(mgr->cond);
	SDL_UnlockMutex(mgr->mutex);

	return task;

fail:
	task_free(task);
	return NULL;
}
Exemplo n.º 2
0
void gamepad_init(void) {
	if(!config_get_int(CONFIG_GAMEPAD_ENABLED) || gamepad.initialized) {
		return;
	}

	if(SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
		log_sdl_error(LOG_ERROR, "SDL_InitSubSystem");
		return;
	}

	gamepad.initialized = true;
	gamepad.axes = calloc(GAMEPAD_AXIS_MAX, sizeof(GamepadAxisState));
	gamepad.buttons = calloc(GAMEPAD_BUTTON_MAX + GAMEPAD_EMULATED_BUTTON_MAX, sizeof(GamepadButtonState));
	gamepad.active_dev_num = GAMEPAD_DEVNUM_INVALID;
	gamepad_load_all_mappings();

	events_register_handler(&(EventHandler){
		.proc = gamepad_event_handler,
		.priority = EPRIO_TRANSLATION,
	});
Exemplo n.º 3
0
static bool gamepad_update_device_list(void) {
	int cnt = SDL_NumJoysticks();
	log_info("Updating gamepad devices list");

	if(gamepad.num_devices > 0) {
		assume(gamepad.devices != NULL);

		for(uint i = 0; i < gamepad.num_devices; ++i) {
			SDL_GameControllerClose(gamepad.devices[i].controller);
		}
	}

	gamepad.num_devices = 0;

	if(!cnt) {
		free(gamepad.devices);
		gamepad.devices = NULL;
		gamepad.num_devices_allocated = 0;
		log_info("No joysticks attached");
		return false;
	}

	if(gamepad.num_devices_allocated != cnt) {
		free(gamepad.devices);
		gamepad.devices = calloc(cnt, sizeof(GamepadDevice));
		gamepad.num_devices_allocated = cnt;
	}

	GamepadDevice *dev = gamepad.devices;

	for(int i = 0; i < cnt; ++i) {
		SDL_JoystickGUID guid = SDL_JoystickGetDeviceGUID(i);
		char guid_str[33] = { 0 };
		SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));

		if(!*guid_str) {
			log_warn("Failed to read GUID of joystick at index %i: %s", i, SDL_GetError());
			continue;
		}

		if(!SDL_IsGameController(i)) {
			log_warn("Joystick at index %i (name: \"%s\"; guid: %s) is not recognized as a game controller by SDL. "
					 "Most likely it just doesn't have a mapping. See https://git.io/vdvdV for solutions",
				i, SDL_JoystickNameForIndex(i), guid_str);
			continue;
		}

		dev->sdl_id = i;
		dev->controller = SDL_GameControllerOpen(i);

		if(dev->controller == NULL) {
			log_sdl_error(LOG_WARN, "SDL_GameControllerOpen");
			continue;
		}

		dev->joy_instance = SDL_JoystickGetDeviceInstanceID(i);

		if(dev->joy_instance < 0) {
			log_sdl_error(LOG_WARN, "SDL_JoystickGetDeviceInstanceID");
			continue;
		}

		log_info("Found device '%s' (#%i): %s", guid_str, DEVNUM(dev), gamepad_device_name_unmapped(i));

		++gamepad.num_devices;
		++dev;
	}

	if(!gamepad.num_devices) {
		log_info("No usable devices");
		return false;
	}

	return true;
}
Exemplo n.º 4
0
static int taskmgr_thread(void *arg) {
	TaskManager *mgr = arg;
	attr_unused SDL_threadID tid = SDL_ThreadID();

	if(SDL_SetThreadPriority(mgr->thread_prio) < 0) {
		log_sdl_error(LOG_WARN, "SDL_SetThreadPriority");
	}

	bool running;
	bool aborted;

	do {
		SDL_LockMutex(mgr->mutex);

		running = mgr->running;
		aborted = mgr->aborted;

		if(!running && !aborted) {
			SDL_CondWait(mgr->cond, mgr->mutex);
		}

		SDL_UnlockMutex(mgr->mutex);
	} while(!running && !aborted);

	while(running && !aborted) {
		SDL_LockMutex(mgr->mutex);
		Task *task = alist_pop(&mgr->queue);

		running = mgr->running;
		aborted = mgr->aborted;

		if(running && task == NULL && !aborted) {
			SDL_CondWait(mgr->cond, mgr->mutex);
		}

		SDL_UnlockMutex(mgr->mutex);

		if(task != NULL) {
			SDL_LockMutex(task->mutex);

			bool task_disowned = task->disowned;

			if(aborted && task->status == TASK_PENDING) {
				task->status = TASK_CANCELLED;
			}

			if(task->status == TASK_PENDING) {
				task->status = TASK_RUNNING;

				SDL_UnlockMutex(task->mutex);
				task->result = task->callback(task->userdata);
				SDL_LockMutex(task->mutex);

				assert(task->in_queue);
				task->in_queue = false;
				(void)SDL_AtomicDecRef(&mgr->numtasks);

				if((task_disowned = task->disowned)) {
					SDL_UnlockMutex(task->mutex);
					task_free(task);
				} else {
					task->status = TASK_FINISHED;
					SDL_CondBroadcast(task->cond);
					SDL_UnlockMutex(task->mutex);
				}
			} else if(task->status == TASK_CANCELLED) {
				assert(task->in_queue);
				task->in_queue = false;
				(void)SDL_AtomicDecRef(&mgr->numtasks);
				SDL_UnlockMutex(task->mutex);

				if(task_disowned) {
					task_free(task);
				}
			} else {
				UNREACHABLE;
			}
		}
	}

	return 0;
}
Exemplo n.º 5
0
TaskManager* taskmgr_create(uint numthreads, SDL_ThreadPriority prio, const char *name) {
	int numcores = SDL_GetCPUCount();
	uint maxthreads = numcores * 8;

	if(numcores < 1) {
		log_warn("SDL_GetCPUCount() returned %i, assuming 1", numcores);
		numcores = 1;
	}

	if(numthreads == 0) {
		numthreads = numcores * 4;
	} else if(numthreads > maxthreads) {
		log_warn("Number of threads capped to %i (%i requested)", maxthreads, numthreads);
		numthreads = maxthreads;
	}

	TaskManager *mgr = calloc(1, sizeof(TaskManager) + numthreads * sizeof(SDL_Thread*));

	if(!(mgr->mutex = SDL_CreateMutex())) {
		log_sdl_error(LOG_WARN, "SDL_CreateMutex");
		goto fail;
	}

	if(!(mgr->cond = SDL_CreateCond())) {
		log_sdl_error(LOG_WARN, "SDL_CreateCond");
		goto fail;
	}

	mgr->numthreads = numthreads;
	mgr->thread_prio = prio;

	for(uint i = 0; i < numthreads; ++i) {
		int digits = i ? log10(i) + 1 : 0;
		static const char *const prefix = "taskmgr";
		char threadname[sizeof(prefix) + strlen(name) + digits + 2];
		snprintf(threadname, sizeof(threadname), "%s:%s/%i", prefix, name, i);

		if(!(mgr->threads[i] = SDL_CreateThread(taskmgr_thread, threadname, mgr))) {
			log_sdl_error(LOG_WARN, "SDL_CreateThread");

			for(uint j = 0; j < i; ++j) {
				SDL_DetachThread(mgr->threads[j]);
				mgr->threads[j] = NULL;
			}

			SDL_LockMutex(mgr->mutex);
			mgr->aborted = true;
			SDL_CondBroadcast(mgr->cond);
			SDL_UnlockMutex(mgr->mutex);
			goto fail;
		}
	}

	SDL_LockMutex(mgr->mutex);
	mgr->running = true;
	SDL_CondBroadcast(mgr->cond);
	SDL_UnlockMutex(mgr->mutex);

	log_debug(
		"Created task manager %s (%p) with %u threads at priority %i",
		name,
		(void*)mgr,
		mgr->numthreads,
		prio
	);

	return mgr;

fail:
	taskmgr_free(mgr);
	return NULL;
}
Exemplo n.º 6
0
void FPS::increment(SDL_Renderer * renderer) {
    unsigned int time_now = SDL_GetTicks();
    unsigned int delta_time = time_now - fps_start_time;
        
    // increment the number of frames rendered
    current_frame_count += 1;

    // if it's time to update the fps count then 
    if (delta_time > FRAME_RATE_PERIOD) {

        // change the current_fps 
        current_fps = current_frame_count / FRAME_RATE_PERIOD;

        // FIXME: remove this!
        //std::cout << "fps: " << get_fps() << std::endl;


        // FIXME WE NEED 
        //   method to blat dynamic floats (digits to texture then render).
        //   method to blat static strings (to texture then render)
        // 

        // FIXME: this is slow.. 
        // render on the GPU by making textures for each digit and displaying them 
        fps_text_surface = TTF_RenderText_Solid(
            fps_font, 
            // This doesn't work because of a bug in the current version of mingw/gcc!!
            // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52015
            // std::to_string(current_frame_count).c_str(), 
            "FIX THE FPS STUFF!!!", 
            fps_font_color);

        if (!fps_text_surface) {
            // handle error here, perhaps print TTF_GetError at least
            log_ttf_error("Problem displaying fps text!");
        } 
        else {

            fps_text_texture = SDL_CreateTextureFromSurface(renderer, fps_text_surface);
            if (!fps_text_texture) {
                log_sdl_error("SDL_CreateTextureFromSurface: ");
                //return 4;
            }        
            else {
                std::cout << "Draw FPS XXXX" << std::endl;
            }
                
            // draw the title
            SDL_Rect src = { 0, 0, fps_text_surface->w, fps_text_surface->h };
            SDL_Rect dest = { 30, 30, fps_text_surface->w, fps_text_surface->h};
            SDL_RenderCopy(renderer, fps_text_texture, &src, &dest);

            // perhaps we can reuse it, but I assume not for simplicity.
            SDL_FreeSurface(fps_text_surface);
            SDL_DestroyTexture(fps_text_texture);
        }
        


        // and reset the fps counters            
        current_frame_count = 0;
        fps_start_time = time_now;
    }
}