Это ошибка в C-коде. В строке surface.c 2258 для surf_blits
имеется следующий тест:
if (dest->flags & SDL_OPENGL &&
!(dest->flags & (SDL_OPENGLBLIT & ~SDL_OPENGL))) {
bliterrornum = BLITS_ERR_NO_OPENGL_SURF;
goto bliterror;
}
Тогда как в строке surface.c 2121 для surf_blit
код:
#if IS_SDLv1
if (dest->flags & SDL_OPENGL &&
!(dest->flags & (SDL_OPENGLBLIT & ~SDL_OPENGL)))
return RAISE(pgExc_SDLError,
"Cannot blit to OPENGL Surfaces (OPENGLBLIT is ok)");
#endif /* IS_SDLv1 */
Обратите внимание на #if IS_SDLv1
.
Проблема, кажется, исходит из SDL_OPENGLBLIT
, который в настоящее время устарел .
Не используйте устаревший режим SDL_OPENGLBLIT, который разрешал как блиттинг, так и использование OpenGL. Этот флаг устарел, по нескольким причинам. При многочисленных обстоятельствах использование SDL_OPENGLBLIT может повредить ваше состояние OpenGL.
blockquote>К сожалению, я не эксперт в OpenGL и не могу объяснить дальше. Надеюсь, кто-то может опубликовать более точный ответ.
Что я точно знаю, так это то, что я могу поднять
BLITS_ERR_SEQUENCE_SURF
непосредственно перед (например, даваяpygame.Rect
в качестве первого объекта вblit_args
), и я не могу поднятьBLITS_ERR_INVALID_DESTINATION
сразу после. [ 1121]Это заставляет меня думать, что что-то происходит с линиями выше.
РЕДАКТИРОВАТЬ
Я могу подтвердить, что, если я добавлю
#if IS_SDLv1
вокруг теста выше и перекомпилирую Pygame, это сработает. Не знаю почему, хотя! ☺Я поднял проблему на GitHub .
Предварительно инициализированный массив был бы быстрее, чем HashMap. Что-то вроде этого:
int CharValues['f'-'0'+1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, ... -1, 10, 11, 12, ...};
if (c < '0' || c > 'f') {
throw new IllegalArgumentException();
}
int n = CharValues[c-'0'];
if (n < 0) {
throw new IllegalArgumentException();
}
// n contains the digit value
Необходимо сравнить этого метода с другими методами (такими как прямой метод Jon Skeet) для определения, который будет самым быстрым для приложения.
Хеш-таблица была бы относительно медленной. Это довольно быстро:
if (c >= '0' && c <= '9')
{
return c - '0';
}
if (c >= 'a' && c <= 'f')
{
return c - 'a' + 10;
}
if (c >= 'A' && c <= 'F')
{
return c - 'A' + 10;
}
throw new IllegalArgumentException();
Другая опция состояла бы в том, чтобы попробовать переключатель/оператор выбора. Массив мог бы быть хорошо, если это находится в кэше, но мисс могла бы быть дорогой.
Я не помню, чтобы видел этот метод раньше, но Микко Рантанен указал на это уравнение в комментарии к вопросу: Код гольфа - двоичное преобразование в шестнадцатеричное (сырое) значение
(char | 32) % 39 - 9
Я не знаю, как оно будет измеряться (возможно, кто-то может добавить его в приведенный выше тест и запустить это, но я предполагаю, что% убивает производительность) - но это аккуратная, простая однострочная для преобразования одного символа в шестнадцатеричное в десятичное. Ручки 0-9, AF, аф.
Я не знаю, как он будет тестироваться (возможно, кто-то может добавить его к тесту выше и запустить его, но я предполагаю, что% убивает производительность) - но это аккуратная, простая однострочная строка для преобразования одного символа в шестнадцатеричное в десятичное. Ручки 0-9, AF, аф. Я не знаю, как он будет тестироваться (возможно, кто-то может добавить его к тесту выше и запустить его, но я предполагаю, что% убивает производительность) - но это аккуратная, простая однострочная строка для преобразования одного символа в шестнадцатеричное в десятичное. Ручки 0-9, AF, аф.int CharValues[256] =
{
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,0,1,2,3,4,5,6,7,8,9,16,16,16,16,16,16,16,
16,10,11,12,13,14,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,10,11,12,13,14,15,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
}
int n = CharValues[c];
if (n == 16)
throw new IllegalArgumentException();
// n contains the digit value
Character.getNumericValue (символ) иначе:
char c = 'a';
System.out.println(c + "->" + Character.getNumericValue(c));
Печать 'a-> 10' как Вы хочет, например. Кто-то еще должен был бы прокомментировать эффективность статического вызова метода по сравнению с поиском HashMap, или Вы могли проверить ее для себя. Это кажется инструментом для очистки/больше, читаемым мне все же.
Используя массив должно быть самым быстрым.
Массив мог иметь размер 16, 16^2, 16^3, 16^4 и т.д.
При преобразовании числа в более многочисленных группах, чем можно было бы дать увеличение производительности.
Будет зона наилучшего восприятия, где это наиболее стоит, возможно 4 цифры (64k таблица).
простой, но медленный:
int i = Integer.parseInt(String.ValueOf(c), 16);
быстрее:
int i = Character.digit(c, 16);
Я привычка использую любой специальный код для "проблем производительности". Если Вы действительно часто будете использовать это, то JIT создаст скомпилированный код, и выполнение станет быстрым. Содержите свой код в чистоте. Вы можете иметь попытку и записать тест производительности, сравнивающий время выполнения из кода выше и любой специальной реализации - я поставил Вас, привычка получает существенные улучшения.
Стоит отметить, что вы выполняете синхронизацию% операции в большинстве ваших тестов. Эта операция занимает примерно столько же времени, что и некоторые другие параметры.
private static byte lookUpTest(int i) {
return (byte) cs[i%cs.length];
}
Я не думаю, что можно победить прямой поиск массива.
static final int[] precalc = new int['f'+1];
static {
for (char c='0'; c<='9'; c++) precalc[c] = c-'0';
for (char c='A'; c<='F'; c++) precalc[c] = c-'A';
for (char c='a'; c<='f'; c++) precalc[c] = c-'a';
}
System.out.println(precalc['f']);
Вот моя настроенная версия кода Greg. На моем поле это незначительно быстрее - но вероятно в шуме. Это избегает проверки нижней границы и не должно делать никакого вычитания. Создание массива 64K и предотвращение любой проверки принадлежности к диапазону, казалось, замедлили вещи - но снова, с синхронизацией как это фактически невозможно быть уверенным, что реально и что является шумом.
public class HexParser
{
private static final byte VALUES = new int['f'];
// Easier to get right for bozos like me (Jon) than
// a hard-coded array :)
static
{
for (int i=0; i < VALUES.length; i++)
{
VALUES[i] = (byte) -1;
}
for (int i='0'; i <= '9'; i++)
{
VALUES[i] = (byte) i-'0';
}
for (int i='A'; i <= 'F'; i++)
{
VALUES[i] = (byte) (i-'A'+10);
}
for (int i='a'; i <= 'f'; i++)
{
VALUES[i] = (byte) (i-'a'+10);
}
}
public static byte parseHexChar(char c)
{
if (c > 'f')
{
throw new IllegalArgumentException();
}
byte ret = VALUES[c];
if (ret == -1)
{
throw new IllegalArgumentException();
}
return ret;
}
}