From 59dc73b911e762495735e2ff6ed63b35a90cde21 Mon Sep 17 00:00:00 2001 From: Roderick Colenbrander Date: Wed, 16 Aug 2006 16:42:23 +0200 Subject: [PATCH] x11drv/opengl: Pixel format rewrite. --- dlls/opengl32/wgl.c | 86 ++++++++++--- dlls/opengl32/wgl_ext.c | 117 +++++++++++++---- dlls/opengl32/wgl_ext.h | 3 + dlls/winex11.drv/opengl.c | 255 +++++++++++++++++++++----------------- 4 files changed, 305 insertions(+), 156 deletions(-) diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 548ea7df8c4..45f629729e4 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -200,6 +200,67 @@ inline static Font get_font( HDC hdc ) return font; } +/* GLX can advertise dozens of different pixelformats including offscreen and onscreen ones. + * In our WGL implementation we only support a subset of these formats namely the format of + * Wine's main visual and offscreen formats (if they are available). + * This function converts a WGL format to its corresponding GLX one. It returns the index (zero-based) + * into the GLX FB config table and it returns the number of supported WGL formats in fmt_count. + */ +BOOL ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, int *fmt_index, int *fmt_count) +{ + int res = FALSE; + int i = 0; + GLXFBConfig* cfgs = NULL; + int nCfgs = 0; + int tmp_fmt_id = 0; + int tmp_vis_id = 0; + int nFormats = 1; /* Start at 1 as we allways have a main visual */ + VisualID visualid = 0; + + /* Request to look up the format of the main visual when iPixelFormat = 1 */ + if(iPixelFormat == 1) visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" ); + + /* As mentioned in various parts of the code only the format of the main visual can be used for onscreen rendering. + * Next to this format there are also so called offscreen rendering formats (used for pbuffers) which can be supported + * because they don't need a visual. Below we use glXGetFBConfigs instead of glXChooseFBConfig to enumerate the fb configurations + * bas this call lists both types of formats instead of only onscreen ones. */ + cfgs = wine_glx.p_glXGetFBConfigs(display, DefaultScreen(display), &nCfgs); + if (NULL == cfgs || 0 == nCfgs) { + ERR("glXChooseFBConfig returns NULL\n"); + if(cfgs != NULL) XFree(cfgs); + return FALSE; + } + + /* Find the requested offscreen format and count the number of offscreen formats */ + for(i=0; i(PF:%d)\n", hdc, hdcPF); /* First, get the visual in use by the X11DRV */ if (!display) return 0; - template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" ); - vis = XGetVisualInfo(display, VisualIDMask, &template, &num); - if (vis == NULL) { - ERR("NULL visual !!!\n"); - /* Need to set errors here */ - return NULL; - } - if (0 >= hdcPF) { + /* We can only render using the iPixelFormat (1) of Wine's Main visual, we need to get the correspondig GLX format. + * If this fails something is very wrong on the system. */ + if(!ConvertPixelFormatWGLtoGLX(display, hdcPF, &tmp, &fmt_index)) { + ERR("Cannot get FB Config for main iPixelFormat 1, expect problems!\n"); SetLastError(ERROR_INVALID_PIXEL_FORMAT); return NULL; } @@ -242,12 +298,12 @@ HGLRC WINAPI wglCreateContext(HDC hdc) SetLastError(ERROR_INVALID_PIXEL_FORMAT); return NULL; } - if (nCfgs_fmt < hdcPF) { - ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, hdcPF, nCfgs_fmt); + if (nCfgs_fmt < fmt_index) { + ERR("(%p): unexpected pixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, fmt_index, nCfgs_fmt); SetLastError(ERROR_INVALID_PIXEL_FORMAT); return NULL; } - cur_cfg = cfgs_fmt[hdcPF - 1]; + cur_cfg = cfgs_fmt[fmt_index]; gl_test = wine_glx.p_glXGetFBConfigAttrib(display, cur_cfg, GLX_FBCONFIG_ID, &value); if (gl_test) { ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); diff --git a/dlls/opengl32/wgl_ext.c b/dlls/opengl32/wgl_ext.c index 0147e598d12..6ef39786f58 100644 --- a/dlls/opengl32/wgl_ext.c +++ b/dlls/opengl32/wgl_ext.c @@ -616,6 +616,8 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa int hTest; int tmp; int curGLXAttr = 0; + int nWGLFormats = 0; + int fmt_index = 0; TRACE("(%p, %d, %d, %d, %p, %p)\n", hdc, iPixelFormat, iLayerPlane, nAttributes, piAttributes, piValues); @@ -630,13 +632,20 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa return GL_FALSE; } + /* Convert the WGL pixelformat to a GLX one, if this fails then most likely the iPixelFormat isn't supoprted. + * We don't have to fail yet as a program can specify an invaled iPixelFormat (lets say 0) if it wants to query + * the number of supported WGL formats. Whether the iPixelFormat is valid is handled in the for-loop below. */ + if(!ConvertPixelFormatWGLtoGLX(display, iPixelFormat, &fmt_index, &nWGLFormats)) { + ERR("Unable to convert iPixelFormat %d to a GLX one, expect problems!\n", iPixelFormat); + } + for (i = 0; i < nAttributes; ++i) { const int curWGLAttr = piAttributes[i]; TRACE("pAttr[%d] = %x\n", i, curWGLAttr); switch (curWGLAttr) { case WGL_NUMBER_PIXEL_FORMATS_ARB: - piValues[i] = nCfgs; + piValues[i] = nWGLFormats; continue ; case WGL_SUPPORT_OPENGL_ARB: @@ -661,8 +670,10 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa case WGL_TRANSPARENT_ARB: curGLXAttr = GLX_TRANSPARENT_TYPE; - if (nCfgs < iPixelFormat || 0 >= iPixelFormat) goto pix_error; - curCfg = cfgs[iPixelFormat - 1]; + /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of + * supported WGLFormats and also check if the GLX fmt_index is valid. */ + if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; + curCfg = cfgs[fmt_index]; hTest = glXGetFBConfigAttrib(display, curCfg, curGLXAttr, &tmp); if (hTest) goto get_error; piValues[i] = GL_FALSE; @@ -671,8 +682,10 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa case WGL_PIXEL_TYPE_ARB: curGLXAttr = GLX_RENDER_TYPE; - if (nCfgs < iPixelFormat || 0 >= iPixelFormat) goto pix_error; - curCfg = cfgs[iPixelFormat - 1]; + /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of + * supported WGLFormats and also check if the GLX fmt_index is valid. */ + if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; + curCfg = cfgs[fmt_index]; hTest = glXGetFBConfigAttrib(display, curCfg, curGLXAttr, &tmp); if (hTest) goto get_error; TRACE("WGL_PIXEL_TYPE_ARB: GLX_RENDER_TYPE = 0x%x\n", tmp); @@ -688,8 +701,10 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa case WGL_COLOR_BITS_ARB: /** see ConvertAttribWGLtoGLX for explain */ - if (nCfgs < iPixelFormat || 0 >= iPixelFormat) goto pix_error; - curCfg = cfgs[iPixelFormat - 1]; + /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of + * supported WGLFormats and also check if the GLX fmt_index is valid. */ + if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; + curCfg = cfgs[fmt_index]; hTest = glXGetFBConfigAttrib(display, curCfg, GLX_BUFFER_SIZE, piValues + i); if (hTest) goto get_error; TRACE("WGL_COLOR_BITS_ARB: GLX_BUFFER_SIZE = %d\n", piValues[i]); @@ -714,8 +729,10 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa continue ; } curGLXAttr = GLX_RENDER_TYPE; - if (nCfgs < iPixelFormat || 0 >= iPixelFormat) goto pix_error; - curCfg = cfgs[iPixelFormat - 1]; + /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of + * supported WGLFormats and also check if the GLX fmt_index is valid. */ + if((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs)) goto pix_error; + curCfg = cfgs[fmt_index]; hTest = glXGetFBConfigAttrib(display, curCfg, curGLXAttr, &tmp); if (hTest) goto get_error; if (GLX_COLOR_INDEX_BIT == tmp) { @@ -779,8 +796,10 @@ GLboolean WINAPI wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLa } if (0 != curGLXAttr) { - if (nCfgs < iPixelFormat || 0 >= iPixelFormat) goto pix_error; - curCfg = cfgs[iPixelFormat - 1]; + /* Check if the format is supported by checking if iPixelFormat isn't larger than the max number of + * supported WGLFormats and also check if the GLX fmt_index is valid. */ + if((iPixelFormat > 0) && ((iPixelFormat > nWGLFormats) || (fmt_index > nCfgs))) goto pix_error; + curCfg = cfgs[fmt_index]; hTest = glXGetFBConfigAttrib(display, curCfg, curGLXAttr, piValues + i); if (hTest) goto get_error; } else { @@ -815,6 +834,10 @@ GLboolean WINAPI wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, cons int gl_test = 0; int attribs[256]; int nAttribs = 0; + GLboolean res = FALSE; + + /* We need the visualid to check if the format is suitable */ + VisualID visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" ); GLXFBConfig* cfgs = NULL; int nCfgs = 0; @@ -825,8 +848,10 @@ GLboolean WINAPI wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, cons int nCfgs_fmt = 0; UINT it_fmt; int tmp_fmt_id; + int tmp_vis_id; int pfmt_it = 0; + int offscreen_index = 1; /* Start at one because we allways have a main visual at iPixelFormat=1 */ TRACE("(%p, %p, %p, %d, %p, %p): hackish\n", hdc, piAttribIList, pfAttribFList, nMaxFormats, piFormats, nNumFormats); if (NULL != pfAttribFList) { @@ -840,12 +865,14 @@ GLboolean WINAPI wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, cons } PUSH1(attribs, None); + /* Search for FB configurations matching the requirements in attribs */ cfgs = glXChooseFBConfig(display, DefaultScreen(display), attribs, &nCfgs); if (NULL == cfgs) { WARN("Compatible Pixel Format not found\n"); return GL_FALSE; } + /* Get a list of all FB configurations */ cfgs_fmt = glXGetFBConfigs(display, DefaultScreen(display), &nCfgs_fmt); if (NULL == cfgs_fmt) { ERR("Failed to get All FB Configs\n"); @@ -853,21 +880,60 @@ GLboolean WINAPI wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, cons return GL_FALSE; } - for (it = 0; it < nMaxFormats && it < nCfgs; ++it) { + /* Loop through all matching formats and check if they are suitable. + * Note that this function should at max return nMaxFormats different formats */ + for (it = 0; pfmt_it < nMaxFormats && it < nCfgs; ++it) { gl_test = glXGetFBConfigAttrib(display, cfgs[it], GLX_FBCONFIG_ID, &fmt_id); if (gl_test) { ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); continue ; } + + gl_test = glXGetFBConfigAttrib(display, cfgs[it], GLX_VISUAL_ID, &tmp_vis_id); + if (gl_test) { + ERR("Failed to retrieve VISUAL_ID from GLXFBConfig, expect problems.\n"); + continue ; + } + + /* When the visualid of the GLXFBConfig matches the one of the main visual we have found our + * only supported onscreen rendering format. This format has a WGL index of 1. */ + if(tmp_vis_id == visualid) { + piFormats[pfmt_it] = 1; + ++pfmt_it; + res = GL_TRUE; + TRACE("Found compatible GLXFBConfig 0x%x with WGL index 1\n", fmt_id); + continue; + } + /* Only continue with this loop for offscreen rendering formats (visualid = 0) */ + else if(tmp_vis_id != 0) { + TRACE("Discarded GLXFBConfig %0x with VisualID %x because the visualid is not the same as our main visual (%lx)\n", fmt_id, tmp_vis_id, visualid); + continue; + } + + /* Find the index of the found format in the whole format table */ for (it_fmt = 0; it_fmt < nCfgs_fmt; ++it_fmt) { gl_test = glXGetFBConfigAttrib(display, cfgs_fmt[it_fmt], GLX_FBCONFIG_ID, &tmp_fmt_id); if (gl_test) { ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); continue ; } + gl_test = glXGetFBConfigAttrib(display, cfgs[it], GLX_VISUAL_ID, &tmp_vis_id); + if (gl_test) { + ERR("Failed to retrieve VISUAL_ID from GLXFBConfig, expect problems.\n"); + continue ; + } + /* The format of Wine's main visual is stored at index 1 of our WGL format table. + * At higher indices we store offscreen rendering formats (visualid=0). Below we calculate + * the index of the offscreen format. We do this by counting the number of offscreen formats + * which we see upto reaching our target format. */ + if(tmp_vis_id == 0) + offscreen_index++; + + /* We have found the format in the table (note the format is offscreen) */ if (fmt_id == tmp_fmt_id) { int tmp; - piFormats[pfmt_it] = it_fmt + 1; + + piFormats[pfmt_it] = offscreen_index + 1; /* Add 1 to get a one-based index */ ++pfmt_it; glXGetFBConfigAttrib(display, cfgs_fmt[it_fmt], GLX_ALPHA_SIZE, &tmp); TRACE("ALPHA_SIZE of FBCONFIG_ID(%d/%d) found as '%d'\n", it_fmt + 1, nCfgs_fmt, tmp); @@ -897,13 +963,14 @@ HPBUFFERARB WINAPI wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, in int nCfgs = 0; int attribs[256]; unsigned nAttribs = 0; + int fmt_index = 0; TRACE("(%p, %d, %d, %d, %p)\n", hdc, iPixelFormat, iWidth, iHeight, piAttribList); if (0 >= iPixelFormat) { ERR("(%p): unexpected iPixelFormat(%d) <= 0, returns NULL\n", hdc, iPixelFormat); SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return NULL; /* unespected error */ + return NULL; /* unexpected error */ } cfgs = glXGetFBConfigs(display, DefaultScreen(display), &nCfgs); @@ -911,24 +978,25 @@ HPBUFFERARB WINAPI wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, in if (NULL == cfgs || 0 == nCfgs) { ERR("(%p): Cannot get FB Configs for iPixelFormat(%d), returns NULL\n", hdc, iPixelFormat); SetLastError(ERROR_INVALID_PIXEL_FORMAT); - return NULL; /* unespected error */ + return NULL; /* unexpected error */ } - if (nCfgs < iPixelFormat) { + + /* Convert the WGL pixelformat to a GLX format, if it fails then the format is invalid */ + if(!ConvertPixelFormatWGLtoGLX(display, iPixelFormat, &fmt_index, &nCfgs)) { ERR("(%p): unexpected iPixelFormat(%d) > nFormats(%d), returns NULL\n", hdc, iPixelFormat, nCfgs); SetLastError(ERROR_INVALID_PIXEL_FORMAT); - goto create_failed; /* unespected error */ + goto create_failed; /* unexpected error */ } object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Wine_GLPBuffer)); if (NULL == object) { SetLastError(ERROR_NO_SYSTEM_RESOURCES); - goto create_failed; /* unespected error */ + goto create_failed; /* unexpected error */ } object->hdc = hdc; object->display = display; object->width = iWidth; object->height = iHeight; - object->pixelFormat = iPixelFormat; nAttribs = ConvertAttribWGLtoGLX(piAttribList, attribs, object); if (-1 == nAttribs) { @@ -937,7 +1005,6 @@ HPBUFFERARB WINAPI wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, in } PUSH2(attribs, GLX_PBUFFER_WIDTH, iWidth); PUSH2(attribs, GLX_PBUFFER_HEIGHT, iHeight); - while (0 != *piAttribList) { int attr_v; switch (*piAttribList) { @@ -1063,12 +1130,11 @@ HPBUFFERARB WINAPI wglCreatePbufferARB(HDC hdc, int iPixelFormat, int iWidth, in } PUSH1(attribs, None); - - object->drawable = glXCreatePbuffer(display, cfgs[iPixelFormat - 1], attribs); + object->drawable = glXCreatePbuffer(display, cfgs[fmt_index], attribs); TRACE("new Pbuffer drawable as %p\n", (void*) object->drawable); if (!object->drawable) { SetLastError(ERROR_NO_SYSTEM_RESOURCES); - goto create_failed; /* unespected error */ + goto create_failed; /* unexpected error */ } TRACE("->(%p)\n", object); @@ -1092,7 +1158,10 @@ HDC WINAPI wglGetPbufferDCARB(HPBUFFERARB hPbuffer) return NULL; } hDC = CreateCompatibleDC(object->hdc); - SetPixelFormat(hDC, object->pixelFormat, NULL); + + /* The function wglGetPbufferDCARB returns a DC to which the pbuffer can be connected. + * We only support one onscreen rendering format (the one from the main visual), so use that. */ + SetPixelFormat(hDC, 1, NULL); set_drawable(hDC, object->drawable); /* works ?? */ TRACE("(%p)->(%p)\n", hPbuffer, hDC); return hDC; diff --git a/dlls/opengl32/wgl_ext.h b/dlls/opengl32/wgl_ext.h index 084c5207613..d70ba2756ed 100644 --- a/dlls/opengl32/wgl_ext.h +++ b/dlls/opengl32/wgl_ext.h @@ -29,6 +29,9 @@ typedef void* (*glXGetProcAddressARB_t)(const GLubyte *); void wgl_ext_initialize_extensions(Display *display, int screen, glXGetProcAddressARB_t proc, const char* disabled_extensions); void wgl_ext_finalize_extensions(void); +/* Used to convert between WGL and GLX pixel formats in wglMakeCurrent and some WGL extensions */ +BOOL ConvertPixelFormatWGLtoGLX(Display *display, int iPixelFormat, int *fmt_index, int *fmt_count); + typedef struct { const char *func_name; void *func_address; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 486f7db3fd8..1793a093bea 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -172,10 +172,42 @@ sym_not_found: return FALSE; } -#define TEST_AND_ADD1(t,a) if (t) att_list[att_pos++] = (a) -#define TEST_AND_ADD2(t,a,b) if (t) { att_list[att_pos++] = (a); att_list[att_pos++] = (b); } -#define NULL_TEST_AND_ADD2(tv,a,b) att_list[att_pos++] = (a); att_list[att_pos++] = ((tv) == 0 ? 0 : (b)) -#define ADD2(a,b) att_list[att_pos++] = (a); att_list[att_pos++] = (b) +static BOOL get_fbconfig_from_main_visual(int *fmt_id, int *fmt_index) +{ + int nCfgs = 0; + int tmp_fmt_id = 0; + int tmp_vis_id = 0; + int i = 0; + GLXFBConfig* cfgs = NULL; + + /* Retrieve the visualid from our main visual */ + VisualID visualid = XVisualIDFromVisual(visual); + + cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), NULL, &nCfgs); + if (NULL == cfgs || 0 == nCfgs) { + ERR("glXChooseFBConfig returns NULL (glError: %d)\n", pglGetError()); + if(cfgs != NULL) XFree(cfgs); + return FALSE; + } + + /* Walk through all FB configurations to retrieve the FB configuration matching our visual */ + for(i=0; iiPixelType == PFD_TYPE_COLORINDEX) { - ADD2(GLX_BUFFER_SIZE, ppfd->cColorBits); - } - if (ppfd->iPixelType == PFD_TYPE_RGBA) { - ADD2(GLX_RENDER_TYPE, GLX_RGBA_BIT); - if (ppfd->dwFlags & PFD_DEPTH_DONTCARE) { - ADD2(GLX_DEPTH_SIZE, GLX_DONT_CARE); - } else { - if (32 == ppfd->cDepthBits) { - /** - * for 32 bpp depth buffers force to use 24. - * needed as some drivers don't support 32bpp - */ - TEST_AND_ADD2(ppfd->cDepthBits, GLX_DEPTH_SIZE, 24); - } else { - TEST_AND_ADD2(ppfd->cDepthBits, GLX_DEPTH_SIZE, ppfd->cDepthBits); - } - } - if (32 == ppfd->cColorBits) { - ADD2(GLX_RED_SIZE, 8); - ADD2(GLX_GREEN_SIZE, 8); - ADD2(GLX_BLUE_SIZE, 8); - ADD2(GLX_ALPHA_SIZE, 8); - } else { - ADD2(GLX_BUFFER_SIZE, ppfd->cColorBits); - /* Some broken apps try to ask for more than 8 bits of alpha */ - TEST_AND_ADD2(ppfd->cAlphaBits, GLX_ALPHA_SIZE, min(ppfd->cAlphaBits,8)); - } - } - TEST_AND_ADD2(ppfd->cStencilBits, GLX_STENCIL_SIZE, ppfd->cStencilBits); - TEST_AND_ADD2(ppfd->cAuxBuffers, GLX_AUX_BUFFERS, ppfd->cAuxBuffers); - - /* These flags are not supported yet... - ADD2(GLX_ACCUM_SIZE, ppfd->cAccumBits); - */ - - /** facultative flags now */ - att_pos_fac = att_pos; - if (ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) { - ADD2(GLX_DOUBLEBUFFER, GLX_DONT_CARE); - } else { - ADD2(GLX_DOUBLEBUFFER, (ppfd->dwFlags & PFD_DOUBLEBUFFER) ? TRUE : FALSE); - } - if (ppfd->dwFlags & PFD_STEREO_DONTCARE) { - ADD2(GLX_STEREO, GLX_DONT_CARE); - } else { - ADD2(GLX_STEREO, (ppfd->dwFlags & PFD_STEREO) ? TRUE : FALSE); - } - - /** Attributes List End */ - att_list[att_pos] = None; - wine_tsx11_lock(); - { - int nCfgs = 0; - int gl_test = 0; - int fmt_id; + if(!visual) { + ERR("Can't get an opengl visual!\n"); + goto choose_exit; + } - GLXFBConfig* cfgs_fmt = NULL; - int nCfgs_fmt = 0; - int tmp_fmt_id; - UINT it_fmt; + /* Get a list containing all supported FB configurations */ + cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), NULL, &nCfgs); + if (NULL == cfgs || 0 == nCfgs) { + ERR("glXChooseFBConfig returns NULL (glError: %d)\n", pglGetError()); + goto choose_exit; + } - cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), att_list, &nCfgs); - /** - * if we have facultative flags and we failed, try without - * as MSDN said - * - * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/ntopnglr_2qb8.asp - */ - if ((NULL == cfgs || 0 == nCfgs) && att_pos > att_pos_fac) { - att_list[att_pos_fac] = None; - cfgs = pglXChooseFBConfig(gdi_display, DefaultScreen(gdi_display), att_list, &nCfgs); - } + /* In case an fbconfig was found, check if it matches to the requirements of the ppfd */ + if(!get_fbconfig_from_main_visual(&fmt_id, &fmt_index)) { + ERR("Can't find a matching FBCONFIG_ID for VISUAL_ID 0x%lx!\n", visual->visualid); + } else { + int dwFlags = 0; + int iPixelType = 0; + int value = 0; - if (NULL == cfgs || 0 == nCfgs) { - ERR("glXChooseFBConfig returns NULL (glError: %d)\n", pglGetError()); - ret = 0; - goto choose_exit; - } - - gl_test = pglXGetFBConfigAttrib(gdi_display, cfgs[0], GLX_FBCONFIG_ID, &fmt_id); - if (gl_test) { - ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); - ret = 0; - goto choose_exit; - } - - cfgs_fmt = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &nCfgs_fmt); - if (NULL == cfgs_fmt) { - ERR("Failed to get All FB Configs\n"); - ret = 0; + /* Pixel type */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_RENDER_TYPE, &value); + if (value & GLX_RGBA_BIT) + iPixelType = PFD_TYPE_RGBA; + else + iPixelType = PFD_TYPE_COLORINDEX; + + if (ppfd->iPixelType != iPixelType) { goto choose_exit; } - for (it_fmt = 0; it_fmt < nCfgs_fmt; ++it_fmt) { - gl_test = pglXGetFBConfigAttrib(gdi_display, cfgs_fmt[it_fmt], GLX_FBCONFIG_ID, &tmp_fmt_id); - if (gl_test) { - ERR("Failed to retrieve FBCONFIG_ID from GLXFBConfig, expect problems.\n"); - XFree(cfgs_fmt); - ret = 0; - goto choose_exit; - } - if (fmt_id == tmp_fmt_id) { - ret = it_fmt + 1; - break ; + /* Doublebuffer */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_DOUBLEBUFFER, &value); if (value) dwFlags |= PFD_DOUBLEBUFFER; + if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) { + if ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (dwFlags & PFD_DOUBLEBUFFER)) { + goto choose_exit; } } - if (it_fmt == nCfgs_fmt) { - ERR("Failed to get valid fmt for FBCONFIG_ID(%d)\n", fmt_id); - ret = 0; + + /* Stereo */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_STEREO, &value); if (value) dwFlags |= PFD_STEREO; + if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE)) { + if ((ppfd->dwFlags & PFD_STEREO) != (dwFlags & PFD_STEREO)) { + goto choose_exit; + } } - XFree(cfgs_fmt); + + /* Alpha bits */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_ALPHA_SIZE, &value); + if (ppfd->iPixelType==PFD_TYPE_RGBA && ppfd->cAlphaBits && !value) { + goto choose_exit; + } + + /* Depth bits */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_DEPTH_SIZE, &value); + if (ppfd->cDepthBits && !value) { + goto choose_exit; + } + + /* Stencil bits */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_STENCIL_SIZE, &value); + if (ppfd->cStencilBits && !value) { + goto choose_exit; + } + + /* Aux buffers */ + pglXGetFBConfigAttrib(gdi_display, cfgs[fmt_index], GLX_AUX_BUFFERS, &value); + if (ppfd->cAuxBuffers && !value) { + goto choose_exit; + } + + /* When we pass all the checks we have found a matching format :) */ + ret = 1; + TRACE("Succesfully found a matching mode, returning index: %d\n", ret); } choose_exit: + if(!ret) + TRACE("No matching mode was found returning 0\n"); + if (NULL != cfgs) XFree(cfgs); wine_tsx11_unlock(); return ret; @@ -358,6 +353,14 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, return 0; /* unespected error */ } + /* This function allways reports the total number of supported pixel formats. + * At the moment we only support the pixel format corresponding to the main + * visual which got created at x11drv initialization. More formats could be + * supported if there was a way to recreate x11 windows in x11drv. + * Because we only support one format nCfgs needs to be set to 1. + */ + nCfgs = 1; + if (ppfd == NULL) { /* The application is only querying the number of visuals */ wine_tsx11_lock(); @@ -377,6 +380,12 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, return 0; } + /* Retrieve the index in the FBConfig table corresponding to the visual ID from the main visual */ + if(!get_fbconfig_from_main_visual(&value, &iPixelFormat)) { + ERR("Can't find a valid pixel format index from the main visual, expect problems!\n"); + return 0; + } + ret = nCfgs; cur = cfgs[iPixelFormat - 1]; @@ -481,6 +490,15 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, const PIXELFORMATDESCRIPTOR *ppfd) { TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd); + /* At the moment we only support the pixelformat corresponding to the main + * x11drv visual which got created at x11drv initialization. More formats + * can be supported if there was a way to recreate x11 windows in x11drv + */ + if(iPixelFormat != 1) { + TRACE("Invalid iPixelFormat: %d\n", iPixelFormat); + return 0; + } + physDev->current_pf = iPixelFormat; if (TRACE_ON(opengl)) { @@ -490,6 +508,11 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, int value; int gl_test = 0; + if(!get_fbconfig_from_main_visual(&value, &iPixelFormat)) { + ERR("Can't find a valid pixel format index from the main visual, expect problems!\n"); + return TRUE; /* Return true because the SetPixelFormat stuff itself passed */ + } + /* * How to test if hdc current drawable is compatible (visual/FBConfig) ? * @@ -530,17 +553,15 @@ static XID create_glxpixmap(X11DRV_PDEVICE *physDev) XVisualInfo *vis; XVisualInfo template; int num; - GLXFBConfig *cfgs; wine_tsx11_lock(); - cfgs = pglXGetFBConfigs(gdi_display, DefaultScreen(gdi_display), &num); - pglXGetFBConfigAttrib(gdi_display, cfgs[physDev->current_pf - 1], GLX_VISUAL_ID, (int *)&template.visualid); + /* Retrieve the visualid from our main visual which is the only visual we can use */ + template.visualid = XVisualIDFromVisual(visual); vis = XGetVisualInfo(gdi_display, VisualIDMask, &template, &num); ret = pglXCreateGLXPixmap(gdi_display, vis, physDev->bitmap->pixmap); XFree(vis); - XFree(cfgs); wine_tsx11_unlock(); TRACE("return %lx\n", ret); return ret;