/** * Initializes the shared context and shared surface. */ static jint GLXGC_InitSharedContext(JNIEnv *env, GLXGraphicsConfigInfo *glxinfo) { GLXPbuffer pbuffer; int attrlist[] = {GLX_PBUFFER_WIDTH, 1, GLX_PBUFFER_HEIGHT, 1, GLX_PRESERVED_CONTENTS, GL_FALSE, 0}; J2dTraceLn(J2D_TRACE_INFO, "in GLXGC_InitSharedContext"); sharedContext = GLXGC_InitOGLContext(env, glxinfo, NULL, JNI_FALSE); if (sharedContext == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "could not create shared context"); return SD_FAILURE; } sharedSurface = j2d_glXCreatePbuffer(awt_display, glxinfo->fbconfig, attrlist); if (sharedSurface == 0) { J2dTraceLn(J2D_TRACE_ERROR, "could not create shared surface"); GLXGC_DestroyOGLContext(env, sharedContext); return SD_FAILURE; } sharedConfigInfo = glxinfo; return SD_SUCCESS; }
/** * Creates a scratch pbuffer, which can be used to make a context current * for extension queries, etc. */ static GLXPbuffer GLXGC_InitScratchPbuffer(GLXFBConfig fbconfig) { int pbattrlist[] = {GLX_PBUFFER_WIDTH, 4, GLX_PBUFFER_HEIGHT, 4, GLX_PRESERVED_CONTENTS, GL_FALSE, 0}; J2dTraceLn(J2D_TRACE_INFO, "GLXGC_InitScratchPbuffer"); return j2d_glXCreatePbuffer(awt_display, fbconfig, pbattrlist); }
JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer (JNIEnv *env, jobject glxsd, jlong pData, jlong pConfigInfo, jboolean isOpaque, jint width, jint height) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); GLXGraphicsConfigInfo *glxinfo = (GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); GLXSDOps *glxsdo; GLXPbuffer pbuffer; int attrlist[] = {GLX_PBUFFER_WIDTH, 0, GLX_PBUFFER_HEIGHT, 0, GLX_PRESERVED_CONTENTS, GL_FALSE, 0}; J2dTraceLn3(J2D_TRACE_INFO, "GLXSurfaceData_initPbuffer: w=%d h=%d opq=%d", width, height, isOpaque); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXSurfaceData_initPbuffer: ops are null"); return JNI_FALSE; } glxsdo = (GLXSDOps *)oglsdo->privOps; if (glxsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXSurfaceData_initPbuffer: glx ops are null"); return JNI_FALSE; } if (glxinfo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXSurfaceData_initPbuffer: glx config info is null"); return JNI_FALSE; } attrlist[1] = width; attrlist[3] = height; surfaceCreationFailed = JNI_FALSE; EXEC_WITH_XERROR_HANDLER( GLXSD_BadAllocXErrHandler, pbuffer = j2d_glXCreatePbuffer(awt_display, glxinfo->fbconfig, attrlist)); if ((pbuffer == 0) || surfaceCreationFailed) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXSurfaceData_initPbuffer: could not create glx pbuffer"); return JNI_FALSE; } oglsdo->drawableType = OGLSD_PBUFFER; oglsdo->isOpaque = isOpaque; oglsdo->width = width; oglsdo->height = height; oglsdo->xOffset = 0; oglsdo->yOffset = 0; glxsdo->drawable = pbuffer; glxsdo->xdrawable = 0; return JNI_TRUE; }
/** * Determines whether the GLX pipeline can be used for a given GraphicsConfig * provided its screen number and visual ID. If the minimum requirements are * met, the native GLXGraphicsConfigInfo structure is initialized for this * GraphicsConfig with the necessary information (pthread key, GLXFBConfig, * etc.) and a pointer to this structure is returned as a jlong. If * initialization fails at any point, zero is returned, indicating that GLX * cannot be used for this GraphicsConfig (we should fallback on the existing * X11 pipeline). */ static jlong GLXGC_GetGLXConfigInfo(JNIEnv *env, jint screennum, jint visnum) { GLXFBConfig fbconfig; GLXContext context; GLXPbuffer glxpbuffer; int pbattrlist[] = {GLX_PBUFFER_WIDTH, 1, GLX_PBUFFER_HEIGHT, 1, GLX_PRESERVED_CONTENTS, GL_FALSE, 0}; GLXGraphicsConfigInfo *glxinfo; int db; const unsigned char *versionstr; J2dTraceLn(J2D_TRACE_INFO, "in GLXGC_GetGLXConfigInfo"); fbconfig = GLXGC_InitFBConfig(env, screennum, visnum); if (fbconfig == 0) { J2dTraceLn(J2D_TRACE_ERROR, "could not create fbconfig"); return 0; } glxinfo = (GLXGraphicsConfigInfo *)malloc(sizeof(GLXGraphicsConfigInfo)); if (glxinfo == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "could not allocate memory for glxinfo"); return 0; } // create a temporary context, used for querying OpenGL version and // extensions context = j2d_glXCreateNewContext(awt_display, fbconfig, GLX_RGBA_TYPE, NULL, GL_TRUE); if (context == 0) { J2dTraceLn(J2D_TRACE_ERROR, "could not create temp GLX context"); free(glxinfo); return 0; } // this is pretty sketchy, but it seems to be the easiest way to create // some form of GLXDrawable using only the display and a GLXFBConfig // (in order to make the context current for checking the version, // extensions, etc)... glxpbuffer = j2d_glXCreatePbuffer(awt_display, fbconfig, pbattrlist); if (glxpbuffer == 0) { J2dTraceLn(J2D_TRACE_ERROR, "could not create scratch pbuffer"); j2d_glXDestroyContext(awt_display, context); free(glxinfo); return 0; } // the temporary context must be made current before we can query the // version and extension strings j2d_glXMakeContextCurrent(awt_display, glxpbuffer, glxpbuffer, context); versionstr = j2d_glGetString(GL_VERSION); OGLContext_GetExtensionInfo(&glxinfo->extInfo); // destroy the temporary resources j2d_glXMakeContextCurrent(awt_display, None, None, NULL); j2d_glXDestroyPbuffer(awt_display, glxpbuffer); j2d_glXDestroyContext(awt_display, context); // invalidate the current context OGLContext_InvalidateCurrentContext(env); J2dTraceLn(J2D_TRACE_VERBOSE, "finished with temporary pbuffer/context"); J2dTraceLn1(J2D_TRACE_INFO, "OpenGL version: %s", versionstr); if (!OGLContext_IsVersionSupported(versionstr)) { J2dTraceLn(J2D_TRACE_ERROR, "invalid OpenGL version; 1.2 is required"); free(glxinfo); return 0; } J2dTraceLn(J2D_TRACE_VERBOSE, "successfully finished checking dependencies"); j2d_glXGetFBConfigAttrib(awt_display, fbconfig, GLX_DOUBLEBUFFER, &db); glxinfo->screen = screennum; glxinfo->visual = visnum; glxinfo->fbconfig = fbconfig; glxinfo->isDoubleBuffered = db; // create the single shared context (if it hasn't been created already) if (sharedContext == NULL) { if (GLXGC_InitSharedContext(env, glxinfo) == SD_FAILURE) { J2dTraceLn(J2D_TRACE_ERROR, "could not init shared context"); free(glxinfo); return 0; } } return ptr_to_jlong(glxinfo); }
JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer (JNIEnv *env, jobject glxsd, jlong pCtx, jlong pData, jint width, jint height) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); OGLContext *oglc = (OGLContext *)jlong_to_ptr(pCtx); GLXSDOps *glxsdo; GLXCtxInfo *ctxinfo; GLXPbuffer pbuffer; int attrlist[] = {GLX_PBUFFER_WIDTH, 0, GLX_PBUFFER_HEIGHT, 0, GLX_PRESERVED_CONTENTS, GL_FALSE, 0}; J2dTraceLn2(J2D_TRACE_INFO, "in GLXSurfaceData_initPbuffer (w=%d h=%d)", width, height); if (oglsdo == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "ops are null"); return JNI_FALSE; } glxsdo = (GLXSDOps *)oglsdo->privOps; if (glxsdo == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "glx ops are null"); return JNI_FALSE; } if (oglc == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "context is null"); return JNI_FALSE; } ctxinfo = (GLXCtxInfo *)oglc->ctxInfo; if (ctxinfo == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "glx context info is null"); return JNI_FALSE; } attrlist[1] = width; attrlist[3] = height; surfaceCreationFailed = JNI_FALSE; EXEC_WITH_XERROR_HANDLER( GLXSD_BadAllocXErrHandler, pbuffer = j2d_glXCreatePbuffer(awt_display, ctxinfo->fbconfig, attrlist)); if ((pbuffer == 0) || surfaceCreationFailed) { J2dTraceLn(J2D_TRACE_ERROR, "could not create glx pbuffer"); return JNI_FALSE; } oglsdo->drawableType = OGLSD_PBUFFER; oglsdo->width = width; oglsdo->height = height; oglsdo->xOffset = 0; oglsdo->yOffset = 0; oglsdo->isPremult = JNI_TRUE; glxsdo->drawable = pbuffer; glxsdo->xdrawable = 0; return JNI_TRUE; }