QVector<int> qglx_buildSpec(const QPlatformWindowFormat &format, int drawableBit) { QVector<int> spec(48); int i = 0; spec[i++] = GLX_LEVEL; spec[i++] = 0; spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = drawableBit; if (format.rgba()) { spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); if (format.alpha()) { spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); } if (format.accum()) { spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); if (format.alpha()) { spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); } } } else { spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; } spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; if (format.depth()) { spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); } if (format.stencil()) { spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); } if (format.sampleBuffers()) { spec[i++] = GLX_SAMPLE_BUFFERS_ARB; spec[i++] = 1; spec[i++] = GLX_SAMPLES_ARB; spec[i++] = format.samples() == -1 ? 4 : format.samples(); } spec[i++] = XNone; return spec; }
GLXFBConfig qglx_findConfig(Display *display, int screen , const QPlatformWindowFormat &format, int drawableBit) { bool reduced = true; GLXFBConfig chosenConfig = 0; QPlatformWindowFormat reducedFormat = format; while (!chosenConfig && reduced) { QVector<int> spec = qglx_buildSpec(reducedFormat, drawableBit); int confcount = 0; GLXFBConfig *configs; configs = glXChooseFBConfig(display, screen,spec.constData(),&confcount); if (confcount) { for (int i = 0; i < confcount; i++) { chosenConfig = configs[i]; // Make sure we try to get an ARGB visual if the format asked for an alpha: if (reducedFormat.alpha()) { int alphaSize; glXGetFBConfigAttrib(display,configs[i],GLX_ALPHA_SIZE,&alphaSize); if (alphaSize > 0) break; } else { break; // Just choose the first in the list if there's no alpha requested } } XFree(configs); } reducedFormat = qglx_reducePlatformWindowFormat(reducedFormat,&reduced); } if (!chosenConfig) qWarning("Warning: no suitable glx confiuration found"); return chosenConfig; }
QT_BEGIN_NAMESPACE QGLFormat QGLFormat::fromPlatformWindowFormat(const QPlatformWindowFormat &format) { QGLFormat retFormat; retFormat.setAccum(format.accum()); if (format.accumBufferSize() >= 0) retFormat.setAccumBufferSize(format.accumBufferSize()); retFormat.setAlpha(format.alpha()); if (format.alphaBufferSize() >= 0) retFormat.setAlphaBufferSize(format.alphaBufferSize()); if (format.blueBufferSize() >= 0) retFormat.setBlueBufferSize(format.blueBufferSize()); retFormat.setDepth(format.depth()); if (format.depthBufferSize() >= 0) retFormat.setDepthBufferSize(format.depthBufferSize()); retFormat.setDirectRendering(format.directRendering()); retFormat.setDoubleBuffer(format.doubleBuffer()); if (format.greenBufferSize() >= 0) retFormat.setGreenBufferSize(format.greenBufferSize()); if (format.redBufferSize() >= 0) retFormat.setRedBufferSize(format.redBufferSize()); retFormat.setRgba(format.rgba()); retFormat.setSampleBuffers(format.sampleBuffers()); retFormat.setSamples(format.sampleBuffers()); retFormat.setStencil(format.stencil()); if (format.stencilBufferSize() >= 0) retFormat.setStencilBufferSize(format.stencilBufferSize()); retFormat.setStereo(format.stereo()); retFormat.setSwapInterval(format.swapInterval()); return retFormat; }
QPlatformWindowFormat qglx_reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) { QPlatformWindowFormat retFormat = format; *reduced = true; if (retFormat.sampleBuffers()) { retFormat.setSampleBuffers(false); } else if (retFormat.stereo()) { retFormat.setStereo(false); } else if (retFormat.accum()) { retFormat.setAccum(false); }else if (retFormat.stencil()) { retFormat.setStencil(false); }else if (retFormat.alpha()) { retFormat.setAlpha(false); }else if (retFormat.depth()) { retFormat.setDepth(false); }else if (retFormat.doubleBuffer()) { retFormat.setDoubleBuffer(false); }else{ *reduced = false; } return retFormat; }
QT_BEGIN_NAMESPACE QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format) { int redSize = format.redBufferSize(); int greenSize = format.greenBufferSize(); int blueSize = format.blueBufferSize(); int alphaSize = format.alphaBufferSize(); int depthSize = format.depthBufferSize(); int stencilSize = format.stencilBufferSize(); int sampleCount = format.samples(); // QPlatformWindowFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that // type has been requested. So we must check QPlatformWindowFormat's booleans too if size is -1: if (format.alpha() && alphaSize <= 0) alphaSize = 1; if (format.depth() && depthSize <= 0) depthSize = 1; if (format.stencil() && stencilSize <= 0) stencilSize = 1; if (format.sampleBuffers() && sampleCount <= 0) sampleCount = 1; // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide // the best performance. The EGL config selection algorithm is a bit stange in this regard: // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort // order is special and described as "by larger _total_ number of color bits.". So EGL will // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on // to say "If the requested number of bits in attrib_list for a particular component is 0, // then the number of bits for that component is not considered". This part of the spec also // seems to imply that setting the red/green/blue bits to zero means none of the components // are considered and EGL disregards the entire sorting rule. It then looks to the next // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that // if the application sets the red/green/blue size to 5/6/5 on the QPlatformWindowFormat, // they will probably get a 32-bit config, even when there's an RGB565 config available. // Now normalize the values so -1 becomes 0 redSize = redSize > 0 ? redSize : 0; greenSize = greenSize > 0 ? greenSize : 0; blueSize = blueSize > 0 ? blueSize : 0; alphaSize = alphaSize > 0 ? alphaSize : 0; depthSize = depthSize > 0 ? depthSize : 0; stencilSize = stencilSize > 0 ? stencilSize : 0; sampleCount = sampleCount > 0 ? sampleCount : 0; QVector<EGLint> configAttributes; configAttributes.append(EGL_RED_SIZE); configAttributes.append(redSize); configAttributes.append(EGL_GREEN_SIZE); configAttributes.append(greenSize); configAttributes.append(EGL_BLUE_SIZE); configAttributes.append(blueSize); configAttributes.append(EGL_ALPHA_SIZE); configAttributes.append(alphaSize); configAttributes.append(EGL_DEPTH_SIZE); configAttributes.append(depthSize); configAttributes.append(EGL_STENCIL_SIZE); configAttributes.append(stencilSize); configAttributes.append(EGL_SAMPLES); configAttributes.append(sampleCount); configAttributes.append(EGL_SAMPLE_BUFFERS); configAttributes.append(sampleCount? 1:0); return configAttributes; }