/** * Returns a pixel format identifier that is suitable for Java 2D's needs * (must have a depth buffer, support for pbuffers, etc). This method will * iterate through all pixel formats (if any) that match the requested * attributes and will attempt to find a pixel format with a minimal combined * depth+stencil buffer. Note that we currently only need depth capabilities * (for shape clipping purposes), but wglChoosePixelFormatARB() will often * return a list of pixel formats with the largest depth buffer (and stencil) * sizes at the top of the list. Therefore, we scan through the whole list * to find the most VRAM-efficient pixel format. If no appropriate pixel * format can be found, this method returns 0. */ static int WGLGC_GetPixelFormatForDC(HDC hdc) { int attrs[] = { WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_DEPTH_BITS_ARB, 16, // anything >= 16 will work for us 0 }; int pixfmts[32]; int chosenPixFmt = 0; int nfmts, i; // this is the initial minimum value for the combined depth+stencil size // (we initialize it to some absurdly high value; realistic values will // be much less than this number) int minDepthPlusStencil = 512; J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGC_GetPixelFormatForDC"); // find all pixel formats (maximum of 32) with the provided attributes if (!j2d_wglChoosePixelFormatARB(hdc, attrs, NULL, 32, pixfmts, &nfmts)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLGC_GetPixelFormatForDC: error choosing pixel format"); return 0; } if (nfmts <= 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLGC_GetPixelFormatForDC: no pixel formats found"); return 0; } J2dRlsTraceLn(J2D_TRACE_VERBOSE, " candidate pixel formats:"); // iterate through the list of pixel formats, looking for the one that // meets our requirements while keeping the combined depth+stencil sizes // to a minimum for (i = 0; i < nfmts; i++) { int attrKeys[] = { WGL_DEPTH_BITS_ARB, WGL_STENCIL_BITS_ARB, WGL_DOUBLE_BUFFER_ARB, WGL_ALPHA_BITS_ARB }; int attrVals[4]; int pixfmt = pixfmts[i]; int depth, stencil, db, alpha; j2d_wglGetPixelFormatAttribivARB(hdc, pixfmt, 0, 4, attrKeys, attrVals); depth = attrVals[0]; stencil = attrVals[1]; db = attrVals[2]; alpha = attrVals[3]; J2dRlsTrace5(J2D_TRACE_VERBOSE, "[V] pixfmt=%d db=%d alpha=%d depth=%d stencil=%d valid=", pixfmt, db, alpha, depth, stencil); if ((depth + stencil) < minDepthPlusStencil) { J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); minDepthPlusStencil = depth + stencil; chosenPixFmt = pixfmt; } else { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (large depth)\n"); } } if (chosenPixFmt == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLGC_GetPixelFormatForDC: could not find appropriate pixfmt"); return 0; } J2dRlsTraceLn1(J2D_TRACE_INFO, "WGLGC_GetPixelFormatForDC: chose %d as the best pixel format", chosenPixFmt); return chosenPixFmt; }
/** * Attempts to create a new GLXFBConfig for the requested screen and visual. * If visualid is 0, this method will iterate through all GLXFBConfigs (if * any) that match the requested attributes and will attempt to find an * fbconfig with a minimal combined depth+stencil buffer. Note that we * currently only need depth capabilities (for shape clipping purposes), but * glXChooseFBConfig() will often return a list of fbconfigs with the largest * depth buffer (and stencil) sizes at the top of the list. Therefore, we * scan through the whole list to find the most VRAM-efficient fbconfig. * If visualid is non-zero, the GLXFBConfig associated with the given visual * is chosen (assuming it meets the requested attributes). If there are no * valid GLXFBConfigs available, this method returns 0. */ static GLXFBConfig GLXGC_InitFBConfig(JNIEnv *env, jint screennum, VisualID visualid) { GLXFBConfig *fbconfigs; GLXFBConfig chosenConfig = 0; int nconfs, i; int attrlist[] = {GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PBUFFER_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_CONFIG_CAVEAT, GLX_NONE, // avoid "slow" configs GLX_DEPTH_SIZE, 16, // anything >= 16 will work for us 0}; // this is the initial minimum value for the combined depth+stencil size // (we initialize it to some absurdly high value; realistic values will // be much less than this number) int minDepthPlusStencil = 512; J2dRlsTraceLn2(J2D_TRACE_INFO, "GLXGC_InitFBConfig: scn=%d vis=0x%x", screennum, visualid); // find all fbconfigs for this screen with the provided attributes fbconfigs = j2d_glXChooseFBConfig(awt_display, screennum, attrlist, &nconfs); if ((fbconfigs == NULL) || (nconfs <= 0)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_InitFBConfig: could not find any valid fbconfigs"); return 0; } J2dRlsTraceLn(J2D_TRACE_VERBOSE, " candidate fbconfigs:"); // iterate through the list of fbconfigs, looking for the one that matches // the requested VisualID and supports RGBA rendering as well as the // creation of windows and pbuffers for (i = 0; i < nconfs; i++) { XVisualInfo *xvi; VisualID fbvisualid; GLXFBConfig fbc = fbconfigs[i]; // get VisualID from GLXFBConfig xvi = j2d_glXGetVisualFromFBConfig(awt_display, fbc); if (xvi == NULL) { continue; } fbvisualid = xvi->visualid; XFree(xvi); if (visualid == 0 || visualid == fbvisualid) { int dtype, rtype, depth, stencil, db, alpha, gamma; // get GLX-specific attributes from GLXFBConfig j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_DRAWABLE_TYPE, &dtype); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_RENDER_TYPE, &rtype); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_DEPTH_SIZE, &depth); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_STENCIL_SIZE, &stencil); // these attributes don't affect our decision, but they are // interesting for trace logs, so we will query them anyway j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_DOUBLEBUFFER, &db); j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_ALPHA_SIZE, &alpha); J2dRlsTrace5(J2D_TRACE_VERBOSE, "[V] id=0x%x db=%d alpha=%d depth=%d stencil=%d valid=", fbvisualid, db, alpha, depth, stencil); #ifdef __sparc /* * Sun's OpenGL implementation will always * return at least two GLXFBConfigs (visuals) from * glXChooseFBConfig(). The first will be a linear (gamma * corrected) visual; the second will have the same capabilities * as the first, except it will be a non-linear (non-gamma * corrected) visual, which is the one we want, otherwise * everything will look "washed out". So we will reject any * visuals that have gamma values other than 1.0 (the value * returned by glXGetFBConfigAttrib() will be scaled * by 100, so 100 corresponds to a gamma value of 1.0, 220 * corresponds to 2.2, and so on). */ j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_GAMMA_VALUE_SUN, &gamma); if (gamma != 100) { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (linear visual)\n"); continue; } #endif /* __sparc */ if ((dtype & GLX_WINDOW_BIT) && (dtype & GLX_PBUFFER_BIT) && (rtype & GLX_RGBA_BIT) && (depth >= 16)) { if (visualid == 0) { // when visualid == 0, we loop through all configs // looking for an fbconfig that has the smallest combined // depth+stencil size (this keeps VRAM usage to a minimum) if ((depth + stencil) < minDepthPlusStencil) { J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); minDepthPlusStencil = depth + stencil; chosenConfig = fbc; } else { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (large depth)\n"); } continue; } else { // in this case, visualid == fbvisualid, which means // we've found a valid fbconfig corresponding to the // requested VisualID, so break out of the loop J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); chosenConfig = fbc; break; } } else { J2dRlsTrace(J2D_TRACE_VERBOSE, "false (bad match)\n"); } } } // free the list of fbconfigs XFree(fbconfigs); if (chosenConfig == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_InitFBConfig: could not find an appropriate fbconfig"); return 0; } return chosenConfig; }