x11drv/opengl: Pixel format rewrite.

This commit is contained in:
Roderick Colenbrander 2006-08-16 16:42:23 +02:00 committed by Alexandre Julliard
parent e73890a72c
commit 59dc73b911
4 changed files with 305 additions and 156 deletions

View File

@ -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<nCfgs; i++) {
wine_glx.p_glXGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
wine_glx.p_glXGetFBConfigAttrib(display, cfgs[i], GLX_FBCONFIG_ID, &tmp_fmt_id);
/* We are looking up the GLX index of our main visual and have found it :) */
if(iPixelFormat == 1 && visualid == tmp_vis_id) {
*fmt_index = i;
TRACE("Found FBCONFIG_ID 0x%x at index %d for VISUAL_ID 0x%x\n", tmp_fmt_id, *fmt_index, tmp_vis_id);
res = TRUE;
}
/* We found an offscreen rendering format :) */
else if(tmp_vis_id == 0) {
nFormats++;
TRACE("Checking offscreen format FBCONFIG_ID 0x%x at index %d\n", tmp_fmt_id, i);
if(iPixelFormat == nFormats) {
*fmt_index = i;
TRACE("Found offscreen format FBCONFIG_ID 0x%x corresponding to iPixelFormat %d at GLX index %d\n", tmp_fmt_id, iPixelFormat, i);
res = TRUE;
}
}
}
*fmt_count = nFormats;
TRACE("Number of offscreen formats: %d; returning index: %d\n", *fmt_count, *fmt_index);
if(cfgs != NULL) XFree(cfgs);
return res;
}
/***********************************************************************
* wglCreateContext (OPENGL32.@)
@ -207,26 +268,21 @@ inline static Font get_font( HDC hdc )
HGLRC WINAPI wglCreateContext(HDC hdc)
{
Wine_GLContext *ret;
int num;
XVisualInfo template;
XVisualInfo *vis = NULL;
Display *display = get_display( hdc );
int hdcPF = GetPixelFormat(hdc);
int hdcPF = 1; /* We can only use the Wine's main visual which has an index of 1 */
int tmp = 0;
int fmt_index = 0;
GLXFBConfig cur_cfg;
TRACE("(%p)->(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");

View File

@ -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;

View File

@ -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;

View File

@ -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; i<nCfgs; i++) {
pglXGetFBConfigAttrib(gdi_display, cfgs[i], GLX_FBCONFIG_ID, &tmp_fmt_id);
pglXGetFBConfigAttrib(gdi_display, cfgs[i], GLX_VISUAL_ID, &tmp_vis_id);
if(tmp_vis_id == visualid) {
*fmt_id = tmp_fmt_id;
*fmt_index = i + 1; /* Use a one based index, iPixelFormat uses that too */
TRACE("Found FBCONFIG_ID 0x%x at index %d for VISUAL_ID 0x%x\n", *fmt_id, *fmt_index, tmp_vis_id);
if(cfgs != NULL) XFree(cfgs);
return TRUE;
}
}
ERR("Can't find a matching FBCONFIG_ID for VISUAL_ID 0x%lx!\n", visualid);
if(cfgs != NULL) XFree(cfgs);
return FALSE;
}
/**
* X11DRV_ChoosePixelFormat
@ -184,141 +216,104 @@ sym_not_found:
*/
int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev,
const PIXELFORMATDESCRIPTOR *ppfd) {
int att_list[64];
int att_pos = 0;
int att_pos_fac = 0;
GLXFBConfig* cfgs = NULL;
int ret = 0;
int nCfgs = 0;
int fmt_id = 0;
int fmt_index = 0;
if (!has_opengl()) {
ERR("No libGL on this box - disabling OpenGL support !\n");
return 0;
}
if (TRACE_ON(opengl)) {
TRACE("(%p,%p)\n", physDev, ppfd);
dump_PIXELFORMATDESCRIPTOR((const PIXELFORMATDESCRIPTOR *) ppfd);
}
/* Now, build the request to GLX */
if (ppfd->iPixelType == 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;