From 219269c0f1e2b5be78b88f490741be2f6123f361 Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander <thunderbird2k@gmx.net> Date: Wed, 1 Aug 2007 14:38:49 +0200 Subject: [PATCH] wgl: GetPixelFormat fix for offscreen formats. --- .gitignore | 4 + Makefile.in | 2 + configure | 3 + configure.ac | 1 + dlls/Makefile.in | 1 + dlls/opengl32/tests/Makefile.in | 13 ++ dlls/opengl32/tests/opengl.c | 211 ++++++++++++++++++++++++++++++++ dlls/winex11.drv/opengl.c | 20 ++- programs/winetest/Makefile.in | 3 + programs/winetest/winetest.rc | 1 + 10 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 dlls/opengl32/tests/Makefile.in create mode 100644 dlls/opengl32/tests/opengl.c diff --git a/.gitignore b/.gitignore index 369e0c1ed94..2c87b7ad778 100644 --- a/.gitignore +++ b/.gitignore @@ -433,6 +433,9 @@ dlls/olepro32/version.res dlls/olesvr.dll16 dlls/olesvr32/libolesvr32.def dlls/opengl32/libopengl32.def +dlls/opengl32/tests/*.ok +dlls/opengl32/tests/opengl32_crosstest.exe +dlls/opengl32/tests/testlist.c dlls/opengl32/version.res dlls/pdh/libpdh.def dlls/pdh/tests/*.ok @@ -894,6 +897,7 @@ programs/winetest/ntprint_test.exe programs/winetest/odbccp32_test.exe programs/winetest/ole32_test.exe programs/winetest/oleaut32_test.exe +programs/winetest/opengl32_test.exe programs/winetest/pdh_test.exe programs/winetest/psapi_test.exe programs/winetest/quartz_test.exe diff --git a/Makefile.in b/Makefile.in index 7ae30499911..8174a91fcb5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -333,6 +333,7 @@ ALL_MAKEFILES = \ dlls/olepro32/Makefile \ dlls/olesvr32/Makefile \ dlls/opengl32/Makefile \ + dlls/opengl32/tests/Makefile \ dlls/pdh/Makefile \ dlls/pdh/tests/Makefile \ dlls/powrprof/Makefile \ @@ -695,6 +696,7 @@ dlls/oledlg/Makefile: dlls/oledlg/Makefile.in dlls/Makedll.rules dlls/olepro32/Makefile: dlls/olepro32/Makefile.in dlls/Makedll.rules dlls/olesvr32/Makefile: dlls/olesvr32/Makefile.in dlls/Makedll.rules dlls/opengl32/Makefile: dlls/opengl32/Makefile.in dlls/Makedll.rules +dlls/opengl32/tests/Makefile: dlls/opengl32/tests/Makefile.in dlls/Maketest.rules dlls/pdh/Makefile: dlls/pdh/Makefile.in dlls/Makedll.rules dlls/pdh/tests/Makefile: dlls/pdh/tests/Makefile.in dlls/Maketest.rules dlls/powrprof/Makefile: dlls/powrprof/Makefile.in dlls/Makedll.rules diff --git a/configure b/configure index b5904578b55..35ec7ffa345 100755 --- a/configure +++ b/configure @@ -20616,6 +20616,8 @@ ac_config_files="$ac_config_files dlls/olesvr32/Makefile" ac_config_files="$ac_config_files dlls/opengl32/Makefile" +ac_config_files="$ac_config_files dlls/opengl32/tests/Makefile" + ac_config_files="$ac_config_files dlls/pdh/Makefile" ac_config_files="$ac_config_files dlls/pdh/tests/Makefile" @@ -21701,6 +21703,7 @@ do "dlls/olepro32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/olepro32/Makefile" ;; "dlls/olesvr32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/olesvr32/Makefile" ;; "dlls/opengl32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/opengl32/Makefile" ;; + "dlls/opengl32/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/opengl32/tests/Makefile" ;; "dlls/pdh/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/pdh/Makefile" ;; "dlls/pdh/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/pdh/tests/Makefile" ;; "dlls/powrprof/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/powrprof/Makefile" ;; diff --git a/configure.ac b/configure.ac index 7f52da66c98..780b4196862 100644 --- a/configure.ac +++ b/configure.ac @@ -1734,6 +1734,7 @@ AC_CONFIG_FILES([dlls/oledlg/Makefile]) AC_CONFIG_FILES([dlls/olepro32/Makefile]) AC_CONFIG_FILES([dlls/olesvr32/Makefile]) AC_CONFIG_FILES([dlls/opengl32/Makefile]) +AC_CONFIG_FILES([dlls/opengl32/tests/Makefile]) AC_CONFIG_FILES([dlls/pdh/Makefile]) AC_CONFIG_FILES([dlls/pdh/tests/Makefile]) AC_CONFIG_FILES([dlls/powrprof/Makefile]) diff --git a/dlls/Makefile.in b/dlls/Makefile.in index 72b2e365eb6..a1bbfdc391d 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in @@ -277,6 +277,7 @@ TESTSUBDIRS = \ odbccp32/tests \ ole32/tests \ oleaut32/tests \ + opengl32/tests \ pdh/tests \ psapi/tests \ quartz/tests \ diff --git a/dlls/opengl32/tests/Makefile.in b/dlls/opengl32/tests/Makefile.in new file mode 100644 index 00000000000..2655941b38f --- /dev/null +++ b/dlls/opengl32/tests/Makefile.in @@ -0,0 +1,13 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +TESTDLL = opengl32.dll +IMPORTS = opengl32 user32 gdi32 kernel32 + +CTESTS = \ + opengl.c + +@MAKE_TEST_RULES@ + +@DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c new file mode 100644 index 00000000000..ca2710cac86 --- /dev/null +++ b/dlls/opengl32/tests/opengl.c @@ -0,0 +1,211 @@ +/* + * Some tests for OpenGL functions + * + * Copyright (C) 2007 Roderick Colenbrander + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windows.h> +#include <wingdi.h> +#include "wine/test.h" + +#define MAX_FORMATS 256 +typedef void* HPBUFFERARB; + +/* WGL_ARB_extensions_string */ +static const char* (WINAPI *pwglGetExtensionsStringARB)(HDC); +static int (WINAPI *pwglReleasePbufferDCARB)(HPBUFFERARB, HDC); + +/* WGL_ARB_pixel_format */ +static BOOL (WINAPI *pwglChoosePixelFormatARB)(HDC, const int *, const FLOAT *, UINT, int *, UINT *); + +/* WGL_ARB_pbuffer */ +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +static HPBUFFERARB* (WINAPI *pwglCreatePbufferARB)(HDC, int, int, int, const int *); +static HDC (WINAPI *pwglGetPbufferDCARB)(HPBUFFERARB); + +static const char* wgl_extensions = NULL; + +static void init_functions(void) +{ + /* WGL_ARB_extensions_string */ + pwglGetExtensionsStringARB = (void*)wglGetProcAddress("wglGetExtensionsStringARB"); + + /* WGL_ARB_pixel_format */ + pwglChoosePixelFormatARB = (void*)wglGetProcAddress("wglChoosePixelFormatARB"); + + /* WGL_ARB_pbuffer */ + pwglCreatePbufferARB = (void*)wglGetProcAddress("wglCreatePbufferARB"); + pwglGetPbufferDCARB = (void*)wglGetProcAddress("wglGetPbufferDCARB"); + pwglReleasePbufferDCARB = (void*)wglGetProcAddress("wglReleasePbufferDCARB"); +} + +static void test_pbuffers(HDC hdc) +{ + const int iAttribList[] = { WGL_DRAW_TO_PBUFFER_ARB, 1, /* Request pbuffer support */ + 0 }; + int iFormats[MAX_FORMATS]; + unsigned int nOnscreenFormats; + unsigned int nFormats; + int i, res; + int iPixelFormat = 0; + + nOnscreenFormats = DescribePixelFormat(hdc, 0, 0, NULL); + + /* When you want to render to a pbuffer you need to call wglGetPbufferDCARB which + * returns a 'magic' HDC which you can then pass to wglMakeCurrent to switch rendering + * to the pbuffer. Below some tests are performed on what happens if you use standard WGL calls + * on this 'magic' HDC for both a pixelformat that support onscreen and offscreen rendering + * and a pixelformat that's only available for offscreen rendering (this means that only + * wglChoosePixelFormatARB and friends know about the format. + * + * The first thing we need are pixelformats with pbuffer capabilites. + */ + res = pwglChoosePixelFormatARB(hdc, iAttribList, NULL, MAX_FORMATS, iFormats, &nFormats); + if(res <= 0) + { + skip("No pbuffer compatible formats found while WGL_ARB_pbuffer is supported\n"); + return; + } + trace("nOnscreenFormats: %d\n", nOnscreenFormats); + trace("Total number of pbuffer capable pixelformats: %d\n", nFormats); + + /* Try to select an onscreen pixelformat out of the list */ + for(i=0; i < nFormats; i++) + { + /* Check if the format is onscreen, if it is choose it */ + if(iFormats[i] <= nOnscreenFormats) + { + iPixelFormat = iFormats[i]; + trace("Selected iPixelFormat=%d\n", iPixelFormat); + break; + } + } + + /* A video driver supports a large number of onscreen and offscreen pixelformats. + * The traditional WGL calls only see a subset of the whole pixelformat list. First + * of all they only see the onscreen formats (the offscreen formats are at the end of the + * pixelformat list) and second extended pixelformat capabilities are hidden from the + * standard WGL calls. Only functions that depend on WGL_ARB_pixel_format can see them. + * + * Below we check if the pixelformat is also supported onscreen. + */ + if(iPixelFormat != 0) + { + HDC pbuffer_hdc; + HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, NULL); + if(!pbuffer) + skip("Pbuffer creation failed!\n"); + + /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */ + pbuffer_hdc = pwglGetPbufferDCARB(pbuffer); + res = GetPixelFormat(pbuffer_hdc); + ok(res == iPixelFormat, "Unexpected iPixelFormat=%d returned by GetPixelFormat for format %d\n", res, iPixelFormat); + trace("iPixelFormat returned by GetPixelFormat: %d\n", res); + trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat); + + pwglReleasePbufferDCARB(pbuffer, hdc); + } + else skip("Pbuffer test for onscreen pixelformat skipped as no onscreen format with pbuffer capabilities have been found\n"); + + /* Search for a real offscreen format */ + for(i=0, iPixelFormat=0; i<nFormats; i++) + { + if(iFormats[i] > nOnscreenFormats) + { + iPixelFormat = iFormats[i]; + trace("Selected iPixelFormat: %d\n", iPixelFormat); + break; + } + } + + if(iPixelFormat != 0) + { + HDC pbuffer_hdc; + HPBUFFERARB pbuffer = pwglCreatePbufferARB(hdc, iPixelFormat, 640 /* width */, 480 /* height */, NULL); + if(!pbuffer) + skip("Pbuffer creation failed!\n"); + + /* Test the pixelformat returned by GetPixelFormat on a pbuffer as the behavior is not clear */ + pbuffer_hdc = pwglGetPbufferDCARB(pbuffer); + res = GetPixelFormat(pbuffer_hdc); + + ok(res == 1, "Unexpected iPixelFormat=%d (1 expected) returned by GetPixelFormat for offscreen format %d\n", res, iPixelFormat); + trace("iPixelFormat returned by GetPixelFormat: %d\n", res); + trace("PixelFormat from wglChoosePixelFormatARB: %d\n", iPixelFormat); + pwglReleasePbufferDCARB(pbuffer, hdc); + } + else skip("Pbuffer test for offscreen pixelformat skipped as no offscreen-only format with pbuffer capabilities has been found\n"); +} + +START_TEST(opengl) +{ + HWND hwnd; + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, /* version */ + PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 24, /* 24-bit color depth */ + 0, 0, 0, 0, 0, 0, /* color bits */ + 0, /* alpha buffer */ + 0, /* shift bit */ + 0, /* accumulation buffer */ + 0, 0, 0, 0, /* accum bits */ + 32, /* z-buffer */ + 0, /* stencil buffer */ + 0, /* auxiliary buffer */ + PFD_MAIN_PLANE, /* main layer */ + 0, /* reserved */ + 0, 0, 0 /* layer masks */ + }; + + hwnd = CreateWindow("static", "Title", WS_OVERLAPPEDWINDOW, + 10, 10, 200, 200, NULL, NULL, NULL, NULL); + ok(hwnd != NULL, "err: %d\n", GetLastError()); + if (hwnd) + { + HDC hdc; + int iPixelFormat, res; + HGLRC hglrc; + ShowWindow(hwnd, SW_SHOW); + + hdc = GetDC(hwnd); + + iPixelFormat = ChoosePixelFormat(hdc, &pfd); + ok(iPixelFormat > 0, "No pixelformat found!\n"); /* This should never happen as ChoosePixelFormat always returns a closest match */ + + res = SetPixelFormat(hdc, iPixelFormat, &pfd); + ok(res, "SetPixelformat failed: %x\n", GetLastError()); + + hglrc = wglCreateContext(hdc); + res = wglMakeCurrent(hdc, hglrc); + ok(res, "wglMakeCurrent failed!\n"); + init_functions(); + + wgl_extensions = pwglGetExtensionsStringARB(hdc); + if(wgl_extensions == NULL) skip("Skipping opengl32 tests because this OpenGL implementation doesn't support WGL extensions!\n"); + + if(strstr(wgl_extensions, "WGL_ARB_pbuffer")) + test_pbuffers(hdc); + else + trace("WGL_ARB_pbuffer not supported, skipping pbuffer test\n"); + + DestroyWindow(hwnd); + } +} diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 214335d45d8..265e67f595c 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1257,9 +1257,27 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, * Get the pixel-format id used by this DC */ int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) { - TRACE("(%p): returns %d\n", physDev, physDev->current_pf); + WineGLPixelFormat *fmt; + int tmp; + TRACE("(%p)\n", physDev); + + fmt = ConvertPixelFormatWGLtoGLX(gdi_display, physDev->current_pf, TRUE, &tmp); + if(!fmt) + { + /* This happens on HDCs on which SetPixelFormat wasn't called yet */ + ERR("Unable to find a WineGLPixelFormat for iPixelFormat=%d\n", physDev->current_pf); + return 0; + } + else if(fmt->offscreenOnly) + { + /* Offscreen formats can't be used with traditional WGL calls. + * As has been verified on Windows GetPixelFormat doesn't fail but returns iPixelFormat=1. */ + TRACE("Returning iPixelFormat=1 for offscreen format: %d\n", fmt->iPixelFormat); + return 1; + } return physDev->current_pf; + TRACE("(%p): returns %d\n", physDev, physDev->current_pf); } /** diff --git a/programs/winetest/Makefile.in b/programs/winetest/Makefile.in index f0eeac44451..01111f4444b 100644 --- a/programs/winetest/Makefile.in +++ b/programs/winetest/Makefile.in @@ -64,6 +64,7 @@ TESTBINS = \ odbccp32_test.exe \ ole32_test.exe \ oleaut32_test.exe \ + opengl32_test.exe \ pdh_test.exe \ psapi_test.exe \ quartz_test.exe \ @@ -172,6 +173,8 @@ ole32_test.exe: $(DLLDIR)/ole32/tests/ole32_test.exe$(DLLEXT) cp $(DLLDIR)/ole32/tests/ole32_test.exe$(DLLEXT) $@ && $(STRIP) $@ oleaut32_test.exe: $(DLLDIR)/oleaut32/tests/oleaut32_test.exe$(DLLEXT) cp $(DLLDIR)/oleaut32/tests/oleaut32_test.exe$(DLLEXT) $@ && $(STRIP) $@ +opengl32_test.exe: $(DLLDIR)/opengl32/tests/opengl32_test.exe$(DLLEXT) + cp $(DLLDIR)/opengl32/tests/opengl32_test.exe$(DLLEXT) $@ && $(STRIP) $@ pdh_test.exe: $(DLLDIR)/pdh/tests/pdh_test.exe$(DLLEXT) cp $(DLLDIR)/pdh/tests/pdh_test.exe$(DLLEXT) $@ && $(STRIP) $@ psapi_test.exe: $(DLLDIR)/psapi/tests/psapi_test.exe$(DLLEXT) diff --git a/programs/winetest/winetest.rc b/programs/winetest/winetest.rc index 37a9e5c0fd6..4cf35a9eb1d 100644 --- a/programs/winetest/winetest.rc +++ b/programs/winetest/winetest.rc @@ -187,6 +187,7 @@ ntprint_test.exe TESTRES "ntprint_test.exe" odbccp32_test.exe TESTRES "odbccp32_test.exe" ole32_test.exe TESTRES "ole32_test.exe" oleaut32_test.exe TESTRES "oleaut32_test.exe" +opengl32_test.exe TESTRES "opengl32_test.exe" pdh_test.exe TESTRES "pdh_test.exe" psapi_test.exe TESTRES "psapi_test.exe" quartz_test.exe TESTRES "quartz_test.exe" -- GitLab