Доброго времени суток экспертам! Сегодня столкнулся с очень странным поведением функции wglUseFontOutlines. Сами символы выводятся в штатном режиме, однако все они повёрнуты на некоторый угол. Причём угол, насколько могу судить, является функцией от позиции вызова wglUseFontOutlines внутри кода… Эффект проявляется только на виртуальной машине (WinXP SP2 на VirtualBox 4.0.10), «нормальные» Винды, а также, как ни странно, WINE, отображают символы прямо. Как Вы считаете, что может служить причиной? Поскольку для меня устранение этого глюка критично, уже готовлю запасные решения, такие как перегон символов на текстуры или создание tesselated-объектов вручную по кривым Безье, полученным из GDI32.GetGlyphOutline. Однако хотелось бы обойтись малой кровью. Код: Код (Text): .386 .model flat, stdcall option casemap:none include c:\masm32\include\windows.inc include c:\masm32\include\user32.inc include c:\masm32\include\kernel32.inc include c:\masm32\include\gdi32.inc include c:\masm32\include\opengl32.inc include c:\masm32\include\glu32.inc includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\gdi32.lib includelib c:\masm32\lib\opengl32.lib includelib c:\masm32\lib\glu32.lib include c:\masm32\macros\macros.asm ;const WW equ 600 WH equ 400 IC equ 1 GLF_START_LIST equ 1000 .code WN db "TEST1", 0 WC db "OGLclass", 0 WF db "Verdana", 0 TT db "ABC" TL equ $ - TT @main: xor edi, edi invoke GetModuleHandle, edi mov esi, eax push offset WC push edi push COLOR_BTNFACE + 1 invoke LoadCursor, edi, IDC_HAND push eax invoke LoadIcon, esi, IC push eax push esi push edi push edi push offset WindowProc push CS_HREDRAW or CS_VREDRAW mov ebp, esp invoke RegisterClass, ebp push edi push edi push edi push edi push WH push WW invoke GetSystemMetrics, SM_CYSCREEN sub eax, WH shr eax, 1 push eax invoke GetSystemMetrics, SM_CXSCREEN sub eax, WW shr eax, 1 push eax push WS_VISIBLE or WS_SYSMENU push offset WN push offset WC push WS_EX_CLIENTEDGE CALL CreateWindowEx invoke ShowWindow, eax, SW_SHOWNORMAL push edi push edi push edi jmp @mget @loop: invoke DispatchMessage, ebp @mget: push ebp call GetMessage sub esp, 12 test eax, eax jne @loop invoke ExitProcess, edi WindowProc proc hWnd: dword, uMsg: dword, wPrm: dword, lPrm: dword xor eax, eax cmp dword ptr [uMsg], WM_PAINT je @WM_PAINT cmp dword ptr [uMsg], WM_SIZE je @WM_SIZE cmp dword ptr [uMsg], WM_DESTROY je @WM_DESTROY cmp dword ptr [uMsg], WM_SYSCOLORCHANGE je @GCOL cmp dword ptr [uMsg], WM_CREATE jne @DEFAULT mov edi, @main mov ecx, SIZEOF(PIXELFORMATDESCRIPTOR)/4 + 1 rep lodsd mov (PIXELFORMATDESCRIPTOR ptr[@main]).dwFlags, PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER mov (PIXELFORMATDESCRIPTOR ptr[@main]).iPixelType, PFD_TYPE_RGBA mov (PIXELFORMATDESCRIPTOR ptr[@main]).cColorBits, 32 mov (PIXELFORMATDESCRIPTOR ptr[@main]).dwLayerMask, PFD_MAIN_PLANE invoke CreateFont, -10, eax, eax, eax, FW_BOLD, eax, eax, eax, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH or FF_DONTCARE, offset WF push eax push eax invoke GetDC, hWnd mov dword ptr [@main + 4], eax mov edi, eax push edi call SelectObject push eax invoke ChoosePixelFormat, edi, @main invoke SetPixelFormat, edi, eax, @main invoke wglCreateContext, edi mov dword ptr [@main], eax invoke wglMakeCurrent, edi, eax invoke glHint, GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST invoke glPointSize, FP4(20.0) invoke glEnable, GL_COLOR_MATERIAL invoke glEnable, GL_DEPTH_TEST invoke glEnable, GL_LIGHTING invoke glEnable, GL_LIGHT0 invoke wglUseFontOutlines, dword ptr [@main + 4], 0, 255, GLF_START_LIST, FP4(0.0), FP4(0.0), WGL_FONT_POLYGONS, 0 push edi call SelectObject call DeleteObject @GCOL: invoke GetSysColor, COLOR_BTNFACE push 255 fild dword ptr [esp] fld1 fstp dword ptr [esp] fld st(0) fld st(0) mov edx, eax shr edx, 16 movzx edx, dl push edx fidivr dword ptr [esp] fstp dword ptr [esp] movzx edx, ah push edx fidivr dword ptr [esp] fstp dword ptr [esp] movzx edx, al push edx fidivr dword ptr [esp] fstp dword ptr [esp] call glClearColor xor eax, eax ret @WM_PAINT: invoke BeginPaint, hWnd, @main + 8 invoke glClear, GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT invoke glColor3ub, 255, 127, 0 invoke glPushMatrix invoke glScalef, FP4(10.0), FP4(10.0), FP4(10.0) invoke glListBase, GLF_START_LIST invoke glCallLists, TL, GL_UNSIGNED_BYTE, offset TT invoke glPopMatrix ; invoke glBegin, GL_LINE_LOOP ; invoke glVertex2f, FP4(0.0), FP4(0.0) ; invoke glVertex2f, FP4(1.0), FP4(-1.0) ; invoke glVertex2f, FP4(1.0), FP4(1.0) ; invoke glEnd invoke SwapBuffers, dword ptr [@main + 8] invoke EndPaint, hWnd, @main + 8 xor eax, eax ret @WM_SIZE: mov eax, lPrm mov edx, eax movzx eax, ax shr edx, 16 xor ecx, ecx push 408f4000h; <<< 1000.0 push ecx push 3fba0000h; <<< 0.1 push ecx push eax fild dword ptr [esp] push edx fidiv dword ptr [esp] fstp qword ptr [esp]; <<< ratio push 40468000h; <<< 45.0 push ecx invoke glViewport, 0, 0, eax, edx invoke glMatrixMode, GL_PROJECTION invoke glLoadIdentity call gluPerspective invoke glMatrixMode, GL_MODELVIEW invoke glLoadIdentity invoke glTranslatef, FP4(0.0), FP4(0.0), FP4(-50.0) ret @WM_DESTROY: push eax push eax mov edi, dword ptr [@main + 4] invoke glDeleteLists, GLF_START_LIST, 256 call wglMakeCurrent invoke wglDeleteContext, dword ptr [@main] invoke ReleaseDC, hWnd, edi invoke DeleteDC, edi invoke PostQuitMessage, eax xor eax, eax ret @DEFAULT: invoke DefWindowProc, hWnd, uMsg, wPrm, lPrm ret WindowProc endp end @main Обратите внимание, что в программе присутствует прямая запись в кодовый сегмент (линкер делает его перезаписываемым, когда склеивает с сегментами данных и ресурсов), однако по всем расчётам, и подтверждающим их экспериментам, записываемое неспособно достать до места вызова. Заранее спасибо за совет. [U:] На всякий случай, вот код сборочного батника: Код (Text): @echo off if exist oOGL.obj del oOGL.obj if exist oOGL.exe del oOGL.exe C:\MASM32\BIN\ml.exe /c /coff oOGL.asm if errorlevel 1 goto errasm C:\MASM32\BIN\PoLink.exe /SUBSYSTEM:WINDOWS /merge:.data=.text /merge:.rsrc=.text oOGL.obj > nul if errorlevel 1 goto errlink dir oOGL.exe goto TheEnd :errlink echo There has been an error while linking this project. goto TheEnd :errasm echo There has been an error while assembling this project. goto TheEnd :TheEnd if exist oOGL.obj del oOGL.obj pause А вот так вышесказанное выглядит на виртуальной машине: А вот так оно должно выглядеть:
Ох. Вот она, сила форумов. После того как запостил, начинаешь вчитываться в собственный код. Проблема была вот в этой строке: Код (Text): rep lodsd На виртуальной машине она отчего-то портит EAX. Решается это элементарно, заменой в последующем вызове Код (Text): invoke CreateFont, -10, eax, eax, eax, FW_BOLD, eax, eax, eax, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH or FF_DONTCARE, offset WF всех EAX на ECX, который, поскольку из REP мы вышли, с гарантией равен 0. И вообще, на месте LODSD должен был быть STOSD. Прошу прощения за беспокойство, тему можно удалять.