2 июн. 2011 г.

Про SELinux

Если скрипт под апачем не может открыть файл и/или каталог (в особенности в /home), а тот же скрипт запущенный из консоли от пользователя, от которого работает апач, работает нормально - проверяй настройки доступа SELinux.

9 мар. 2011 г.

Про imageshack.us и прямые ссылки

Imageshack с недавних пор решил разрешать копировать прямые ссылки, если заливать картинки по одной:



Ничто не мешает, однако, достать ссылку из исходников страницы, но процесс муторный. После двух повторений, был написан Greasemonkey скрипт, который размещает ссылку на залитую картинку наверху страницы сразу под меню:



Работает в опере, и, надеюсь, в firefox с плагином Greasemonkey, быть может заработает и в Хроме.

19 дек. 2010 г.

Про страхование

Страховые компании - это такие казино, которым разрешено действовать на территории всей страны, в отличие от "обычных" казино. Это казино, где вы ставите на то, что с вами произойдет "беда". Мат. ожидание изменения количества ваших средств в результате заключения договора со страховой компанией отрицательно (иначе страховые компании давно бы разорились).

4 дек. 2010 г.

Про опенгл 3

Пост является вольным пересказом Getting started и Creating an OpenGL Context с OpenGL wiki с упоминанием граблей, на которые я наступил.


Пока я на работе ковыряюсь с девайсами, с опенглоподобным API, в котором нет никаких шейдеров (а в самом девайсе поддержка чисел с плавающей запятой исключительно программная), прогресс не стоит на месте и наличествуют уже аж спецификация OpenGL 4.1.


Надо наверстывать упущенное, и разобраться хотя бы с третьим опенглом, хотя бы потому, что OpenGL extension viewer говорит, что моя видеокарта не поддерживает даже OpenGL 4.0.


В третьем опенгле Khronos group решили выкинуть нафиг Fixed function pipeline. В спецификации 3.0 функции, относящиеся к FFP были помечены как deprecated, в 3.1 они были убраны совсем.


Кроме того, микрософту с его DirectX на опенгл плевать и .h файлы поставляемые с Windows SDK были заморожены где-то в районе спецификации 1.1. Что означает, что функции, появившиеся в более поздних версиях там не объявлены. Что в свою очередь означает, что адреса нужных функций придется грузить ручками (с помощью wglGetProcAddress), а прототипы набивать где-то у себя в исходниках.


Те, кто не любит заниматься такой фигней могут воспользоваться одной из библиотек, облегчающей данный процесс. Я после того, как проделал это с десятком функций, решил, что рутинное повторение операции "объявить указатель на функцию/загрузить адрес" мне особо понимания происходящего не прибиавит и взял GLee. Использование ее заключается в том, что из zip-файла берутся .h и .c файлы и добавляются в проект (я использую Visual Studio), если проект C++ и используются precompiled headers, надо .c файл переименовать в .cpp, иначе студия будет ругаться, что нельзя использовать precompiled headers в проекте на двух языках.


Вообще, пользование опенглом в Windows начинается с того, что создается окно, в нем создается контекст OpenGL и после этого можно рисовать. Почти. Порядок создания контекста спецификацией не оговаривается и оставляется на совести разработчика реализации опенгла на каждой конкретной платформе. Соответственно, функция wglCreateContext, имеющаяся в распоряжении человека, заинклюдившего gl.h из Windows SDK, создает контекст опенгла, совместимый со спецификацией 1.1.


Контекст, совместимый с 3.x создается функцией wglCreateContextAttribsARB (да, все, что имеет префикс wgl, является Windows-specific, так что неумеренное использование приведет к проблемам с переносимостью на другие ОСи), адрес которой надо грузить вручную. Но загрузить адрес опенгловой функции можно только уже имея проинициализированный контекст опенгла, иначе wglGetProcAddress вас пошлет далеко и надолго. Соответственно, процесс создания OpenGL 3.x контекста выглядит так:



  1. создаем окно;

  2. с помощью wglCreateContext создаем в нем хоть какой-нибудь rendering context опенгла (тут есть неясный мне момент: надо ли устанавливать перед этим DC окна PixelFormat, я устанавливал, может быть это и не нужно было) и выбираем его (wglMakeCurrent);

  3. загружаем нужные адреса функций. Потребуются как минимум wglChoosePixelFormatARB и wglCreateContextAttribsARB. В случае использования GLee просто вызваем GLeeInit() - она загрузит все;

  4. убиваем контекст опенгла (wglMakeCurrent(0, 0); wglDeleteContext(hRC);), убиваем следом и само окно: вроде как повторно использовать его не получится, я, опять же, не проверял;

  5. создаем новое окно;

  6. создаем и устанавливаем этому окну pixel format с помощью функций wglChoosePixelFormatARB и SetPixelFormat (в принципе, можно обойтись и без wglChoosePixelFormatARB, но тогда настроить можно будет только то, что есть в структуре PIXELFORMATDESCRIPTOR, передаваемой в SetPixelFormat): полученный из wglChoosePixelFormatARB pixelFormat передается как второй аргумент SetPixelFormat (либо пишем туда 0, если не заморачивались);

  7. создаем rendering context функцией wglCreateContextAttribsARB;

  8. выбираем его (wglMakeCurrent);


Мой код выглядит примерно так:


m_window = createNewWindowForOpenGL(hInstance); // моя функция создания окна
m_dc = GetDC(m_window);

const int ATTR_LIST[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
// WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
// WGL_SAMPLES_ARB, 4,
0,
};

int pixelFormat;
UINT numFormats;

wglChoosePixelFormatARB(m_dc, ATTR_LIST, NULL, 1, &pixelFormat, &numFormats);

PIXELFORMATDESCRIPTOR pfd;
fillPFD(pfd); // моя функция заполнения PFD

SetPixelFormat(m_dc, pixelFormat, &pfd);

const int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
// WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};

m_rc = wglCreateContextAttribsARB(m_dc, NULL, attribs);

wglMakeCurrent(m_dc, m_rc);

int openGLMajorVersion, openGLMinorVersion;
glGetIntegerv(GL_MAJOR_VERSION, &openGLMajorVersion);
glGetIntegerv(GL_MINOR_VERSION, &openGLMinorVersion);

обработка ошибок для краткости выкинута. В переменных openGLMajorVersion и openGLMinorVersion находится реальная версия опенгла, с которой был создан контекст. Она может отличаться от запрошенной.


В созданном контексте хоть что-то вывести можно только с помощью Vertex buffer object'ов и Vertex array object'ов. Причем, в контексте 3.0 можно обойтись только VBO (там есть "умолчальный array object" с номером 0), а в более поздних версиях обязательно использование и VAO, а если включен forward compatible bit (последняя закомментированная строчка в коде), то и в 3.0 контексте обязательно использование VAO


Теперь о граблях. Изначально код я писал на компе с видеокартой NVidia и к моему удивлению написанный код почти сразу начал делать то, что я хотел. Позже выяснилось, что при попытке запустить ее на видеокарте ATI/AMD программа не работала: я видел только clear color и больше ничего. Ввиду моего некоторого недопонимания как делать правильно, а также недостатка проверок результатов вызовов функций, был (возможно зря) переписан код создания окон (изначально создавалось два окна сразу, в одном инициализировался стандартный контекст, получились указатели, окно убивалось и инициализировался нужный контекст во втором окне, после переписывания окна создавались и убивались строго последовательно). В конце концов, я выяснил, что использование VAO обязательно и просто одними VBO не обойтись (нвидиевские драйвера, видимо, прощают гораздо больше, чем атишные), и обложил все вызовы опенгла проверками того, что они сработали — дело поиска косяков пошло веселее, но возвращаемые ошибки иногда помогали слабо. Так что надо проверять на разном железе — необычное занятие для человека, занимающегося программированием для консолей.

11 окт. 2009 г.

Про базы данных

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


Ввиду отсутствия хоть какого-бы опыта применения баз данных на реальных задачах, было принято решение взять MySQL, PostgreSQL и SQLite и потестировать скорость интересующих меня операций.


В каждом случае была заведена таблица из трех колонок: целочисленный id, являющийся первичным ключом и трех строк по 180 символов.


Тестировались:


  1. скорость добавления одной отдельной записи в базу;

  2. скорость извлечения одной записи из базы;

  3. и скорость обновления записи.



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


Для тестирования использовался перл-скрипт, производящий все операции и засекающий время их исполнения


Результаты. В таблице указано количество операций в секунду:


insertselectupdate
MySQL InnoDB45498942
MySQL MyISAM977451099539
PostgreSQL122317891181
SQLite12759012

Скрипт запускался несколько раз, указаны скорости, близкие к средним. MyISAM не поддерживает транзакций и тестировался просто для сравнения.


Результаты меня весьма удивили, такой низкой скорости записи я не ожидал. В ближайшее время я попытаюсь перепроверить результаты на другом компьютере.


Использовались следующие версии ПО:


  • MySQL 5.1.39 x64

  • PostgreSQL 8.4.1 x86

  • SQLite, шедший в комплекте с ActivePerl 5.10.1 x64


Тестировалось все на Windows Vista x64, на компьютере с процессором Core 2 6750 2.66 ГГц, 2 ГБ памяти.


Update: Проверка на Linux'е показала такие результаты:

insertselectupdate
MySQL InnoDB8901891690
MySQL MyISAM316218612995
SQLite1582997201

Компьютер с линуксом не первой свежести (Sempron 2800, 512 МБ памяти), этим, вероятно, объясняется снижение производительности MyISAM и других вариантов на чтение

На третьем компьютере с 32-битной вистой и конфигурацией, аналогичной первому компьютеру, результаты были таковы:

insertselectupdate
MySQL InnoDB3795793432
MySQL MyISAM914557839641
SQLite34690374

18 мая 2009 г.

КРИ 2009

Съездил в очередной раз на КРИ. Выставка, в целом, помельчала, доклады были оккупированы интелом. Докладчики от интела, судя по некоторым из них, были туда загнаны чуть ли не насильно и делали доклады не по тем темам, в которых разбираются. Микрософт с их XNA тоже был весьма уныл. Запомнившихся докладов было два: «Teamwork» Дениса Вайханского и "Геймдизайн для всех, кроме нас" Павла Епишина, затянувшийся на 20 минут.

Выглядело все так:

Если придти пораньше, можно побродить по пустым стендам

OG Games оформили свой стенд, посвященный игре Nova online, под лабораторию:

Народ завлекался широким спектром средств:

Стенд 1С помельчал с прошлого года, и показывал оказуалившийся Ил-2: штурмовик, Fallout 3 и еще что-то:

Бука показывала свои игры, некоторые из которых были сыроватыми альфами:


Нивал ненавязчиво зазывал поработать:


Kraken Games представлял «MMORPG по мотивам игры Soldat» Warside:


Девушки, завалившие всех своим спамом:


Autodesk проводил конкурс и давал планшет Wacom в качестве приза:


Обнаженные девушки рекламировали, как и в прошлом году, Mass Effect:


GSC, по всей видимости, поставила производство сталкеров на поток и показывала очередную серию «Зов Припяти»:



Пьер Гийод на своем докладе рассказывал про игры Gobliiins, для которых он рисовал; про то, чем занимался после выхода третьей части; про то, что сделал четвертую. Ролик про четвертую часть меня что-то не порадовал, игру по причине любви Пьера к трехмерной графике сделали в 3D, что как мне кажется, было лишним. Сам доклад оказался весьма сумбурным.

NVidia показывала "новую стереотехнологию", первые варианты которой я видел лет 6 назад у того же производителя, только очки тогда были проводными и втыкались в видеокарту, сейчас они беспроводные и передатчик втыкается в USB. Поступить это добро в продажу должно в июне по цене примерно в $200 (нужен еще монитор, способный выдать развертку 100 Гц).


Как говорили люди, представлявшие эти очки, батарейки в них хватает примерно на час, после чего надо 15 минут заряжать аккумуляторы, во время зарядки играть нельзя. При наличии залмановских стереомониторов по сносным ценам с поляризационными очками, которым вообще электричество не нужно (и вывод на которые также поддерживается драйверами nvidia), эта "технология" мне кажется будет не очень востребована.

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

7 мая 2009 г.

Про линупс и телевизор

Есть у меня телевизор с HDMI входом и компьютер с нвидиевской видеокартой с двумая видеовыходами. Использовать его для просмотра фильмов кажется весьма заманчивой идеей.

Целью является получение системы позволяющей за минимальное время и усилия смотреть видео на телевизоре из произвольного исходного положения. Кроме того, во время использования телевизора на него не должна убегать мышка ни при каких обстоятельствах, но иметь возможность переместить мышь между мониторами должна быть (хоткеем, например).

Добиться требуемого удалось ознакомившись с двумя документами: X.Org/Dual Moniors на gentoo-wiki и NVIDIA Accelerated Linux Graphics Driver README and Installation Guide.

Итак, сначала учим систему думать, что телевизор всегда подключен: для этого добавляем строчку

Option "ConnectedMonitor" "DFP,DFP"

в секцию Device файла /etc/X11/xorg.conf. У меня два DVI выхода, поэтому написано DFP,DFP. Если один из выходов — обычный VGA DSUB, то надо писать CRT, вместо одного из DFP, если TV out, то, соответственно, TV.

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

Проблема с мышкой решается добавлением строчек

Screen 0 "Screen0" 0 0
Screen 1 "Screen1" 2000 0

в секцию ServerLayout файла /etc/X11/xorg.conf. Этого достаточно, чтобы мышка перестала убегать на второй монитор, но следствием этого становится то, что на второй монитор теперь совсем невозможно попасть. Это решим позже.

Теперь с видеорежимами. Иксы при запуске запрашивают из монитора EDID — запись с данными о поддерживаемых монитором видеорежимах. Т.к. в нашем случае, монитор в момент запуска иксов отключен, иксам эту информацию брать неоткуда. По идее, решить это можно добавив строчки ModeLine в секцию Monitor соответствующего монитора или Option "metamodes" в секцию Device соответствующего видеовыхода, но мне это, по неизвестным мне причинам, не помогло. Решением было считать EDID из монитора когда он был подключен в момент запуска иксов и заставить иксы использовать EDID из файла вместо запроса его у монитора. Сохранить EDID можно либо утилитой read-edid, которая работает только в 32-битном линуксе, либо nvidia-settings, которая работает везде, но только при наличии видеокарты nvidia. Получив файл с требуемой информацией, необходимо подсунуть ее иксам. Этого можно добиться добавив

Option "CustomEDID" "DFP-1:/etc/X11/myedid.bin"

в секцию Device. Естественно, DFP-1 и путь к файлу с данными надо поправить на свои. Эта опция добавляется драйвером nvidia, и с другими драйверами скорее всего не заработает. На этом конфигурация X-сервера завершена.

Теперь настроим KDE так, чтобы он не пытался использовать второй монитор для рабочего стола. Для этого находим файл ~/.kde/share/config/kcmdisplayrc и добавляем в него строчки

[X11]
disableMultihead=true

Перезапускаем сеанс KDE и теперь на втором мониторе рабочего стола не будет.

Переключение между мониторами можно организовать установив утилиту switchscreen, и добавив хоткей для ее вызова, с помощью, например, xbindkeys.

Запускать приложения на втором мониторе можно установив переменную окружения DISPLAY в значение :0.1 перед запуском приложения. Например, так:

$ DISPLAY=:0.1 smplayer ./somevideo.avi

В моем случае, я завел скрипт для запуска smplayer'а на втором мониторе, который берет специальные настройки плеера из нестандартного места, чтобы "телевизионный" вариан вел себя несколько иначе, чем "стандартный". В частности, телевизор подключен ко второй звуковой карте, соответственно звук надо выводить на нее, а не на основную.