LINUX.ORG.RU

Подскажите аналог GLUT, но без проблем с потоками

 , ,


0

1

Замучился я уже извращениями страдать: т.к. glutMainLoop() можно вызывать только из основного потока, приходится все с ног на голову переворачивать, да еще и какие-нибудь глобальные флаги использовать, чтобы окна создавать/уничтожать из вычисляющего потока, а не отображающего.

Нашел такую штуку — предлагают сделать свою обертку, которая будет вести себя правильно. Но это же придется таскать еще и целую библиотеку вместе со своим велосипедом.

Вопрос: есть ли что-нибудь OpenGL'ное вроде GLUT'а, что позволит элементарно создавать окна, рисовать менюшки и обрабатывать события клавы/мыши?

☆☆☆☆☆

Большинство тулкитов - однопоточные в том плане, что UI-поток - один и все UI-функции должны быть вызваны из него.

приходится все с ног на голову переворачивать, да еще и какие-нибудь глобальные флаги использовать, чтобы окна создавать/уничтожать из вычисляющего потока, а не отображающего.

Вычисляющему потоку же вычислять надо, зачем ему ещё и с окнами возиться? Тут надо архитектуру пересматривать, а не тулкит искать.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

Дык, я хочу так сделать: основной поток что-то считает, а если нужно выводить — создает окно, в котором крутится glutMainLoop(). Если окон 100, то и glutMainLoop()'ов 100.

А приходится делать по-извращенски: в main() открывать запускать основные функции в потоке, затем создавать окно и делать glutMainLoop(), причем это окно убивать ни в коем разе нельзя!

Хочется же, чтобы можно было создавать/уничтожать окна в любой момент (может, мне окно вывести только под конец вычислений надо будет?).

О, меня осенило! Вместо того, чтобы в каждом окне писать glutIdleFunc(Redraw);:

void Redraw(){
	forEachWindow(redisplay);
	usleep(10000);
}
можно это написать один раз при инициализации (перед glutMainLoop()), а внутри Redraw() принимать запросы на создание новых окон!

И сказать глуту

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
чтобы оно не дохло даже без окон.

Ща буду пробовать.

Eddy_Em ☆☆☆☆☆
() автор топика

Почти сделал на фриглуте. Там, оказывается, есть возможность не вызывать основной цикл, а делать самостоятельные разовые вызовы.

Eddy_Em ☆☆☆☆☆
() автор топика

GLFW (glfwWaitEvents();) и очередь сообщений. Когда хочешь слить инфу — отправляешь сообщение и будишь основной (GUI) поток (glfwPostEmptyEvent();). Тот вычитывает сообщения и создаёт окна, кладёт полученные от юзера данные в очередь сообщений для потока...

exhu
()
Ответ на: комментарий от Eddy_Em

Дык, я хочу так сделать: основной поток что-то считает, а если нужно выводить — создает окно, в котором крутится glutMainLoop(). Если окон 100, то и glutMainLoop()'ов 100.

Ты делаешь неправильно. Пусть основной поток рисует окошки и взаимодействует с пользователем. И там же будет glutMainLoop(). А для вычислений уже создавай отдельный поток.

Chaser_Andrey ★★★★★
()
Ответ на: комментарий от Chaser_Andrey

Да я уже сегодня почти добил. При инициализации запускается вот этот поток:

void *Redraw(_U_ void *arg){
    while(1){
        pthread_mutex_lock(&winini_mutex);
        if(!initialized) return NULL;
        if(wannacreate){ // someone asks to create window
            DBG("call for window creating, id: %d", wininiptr->ID);
            createWindow(wininiptr);
            DBG("done!");
            wininiptr = NULL;
            wannacreate = 0;
        }
        forEachWindow(redisplay);
        pthread_mutex_unlock(&winini_mutex);
        if(totWindows) glutMainLoopEvent(); // process actions if there are windows
        usleep(10000);
    }
    return NULL;
}
// во, кстати, косяк заметил: перед return надо мьютекс разблокировать, а то повиснет при следующем вызове. Хоть и не может быть такого варианта, чтобы не было initialized при залоченном мьютексе, но и палка один раз да стреляет!

glutMainLoopEvent позволяет не влезать в блокирующий glutMainLoop. А еще этот поток можно убить, если окна нафиг не нужны, а потом опять запустить, как только понадобятся.

Уже работают: перемещение картинки в окне (средней кнопкой мыши), масштабирование клавиатурой (еще добавлю скролл и масштабирование мышей). Еще с менюшкой надо разобраться... В общем, почти уже готов модуль для включения в программку, работающую с ПЗСкой.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от annulen

Прошу не лезть в кошерненькую тему со всякой дрянью! Ладно бы еще говнотыки посоветовал, но культи — это уж совсем извращение!

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от buddhist

Ничего подобного! С полтыщщи строчек заменять совершенно неохота!

Eddy_Em ☆☆☆☆☆
() автор топика

Подскажите аналог GLUT, но без проблем с потоками

У глюта и чего бы там ни было с потоками проблем нет :) Ты по ходу в опенгл не понял, а тогда получается проблема как обычно - между клавой и креслом.

slackwarrior ★★★★★
()
Ответ на: комментарий от slackwarrior

Да все я уже понял и почти дописал. Сегодня как мелкая ляжет спать, опять пойду на работу, дорихтую красоту и выложу в репу на гитхабе.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

Я и так уже слишком дофига накодил на опенгле, чтобы на SDL переключаться.

Ты либо путаешься в терминологии, либо не знаешь что такое сдл.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Те же яйца: от количества кода меня это не избавит!

Нафиг мне этот SDL, если GLUT то же самое делает и меньше ненужных прослоек?

Eddy_Em ☆☆☆☆☆
() автор топика

технически, на большинстве операционок, нативные тулкиты сами по себе однопоточные.

более того, на говноиде и osx они еще и привязаны к главному потоку процесса (вероятно, что и на венде тоже, не помню уже).

в иксах, можно что-то как-то делать из разных потоков (это ессно если у тебя не говнотыка и не культи, а скорее что-то вроде xcb), но это не портабельно.

короче говоря, то что ты пытаешься сделать — и есть извращение, по отношению к тому как работают графические системы в большинстве современных операционок. ищи проблему в себе.

waker ★★★★★
()
Ответ на: комментарий от waker

Мне не нравится, как работают графические системы в большинстве современных операционок! Черезжопность какая-то!

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

Забавный пример: чисто сишную погромулинку зачем-то компилят g++. Вот же извращенцы!!!

cout же ☺

PolarFox ★★★★★
()
Ответ на: комментарий от waker

Ну я конь! Потратил минут 20 на поиск, почему у меня иногда появляется зависание на pthread_join(GLUTthread, NULL), когда "убиваю контекст". А всему виной usleep: оказывается, в отличие от сигналов, посылаемых kill, сигнал от pthread_cancel не прекращает sleep! Вот такие пироги.

Сделал вот так:

/**
 * main freeGLUT loop
 * waits for global signals to create windows & make other actions
 */
void *Redraw(_U_ void *arg){
	struct timeval tv;
	while(1){
		pthread_mutex_lock(&winini_mutex);
		if(!initialized) return NULL;
		if(wannacreate){ // someone asks to create window
			DBG("call for window creating, id: %d", wininiptr->ID);
			createWindow(wininiptr);
			DBG("done!");
			wininiptr = NULL;
			wannacreate = 0;
		}
		forEachWindow(redisplay);
		pthread_mutex_unlock(&winini_mutex);
		if(totWindows) glutMainLoopEvent(); // process actions if there are windows
		tv.tv_sec = 0;
		tv.tv_usec = 10000;
		select(0, NULL, NULL, NULL, &tv);
	}
	return NULL;
}
теперь все ОК.

Ща все остальные слипы поищу.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

А вот фигушки! Все равно подвисает, собака!

Придется, наверное, pthread_cond_timedwait использовать. Но он, гад, абсолютное время хочет.. Правда, на БХ писали, что вроде как косяков особо не замечено...

Eddy_Em ☆☆☆☆☆
() автор топика

Вот же зараза! На "малинке" не работает при передаче на nVidia по сети.

Eddy_Em ☆☆☆☆☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.