/** * Initializes a framebuffer object, using the given width and height as * a guide. See OGLSD_InitTextureObject() and OGLSD_InitFBObject() * for more information. */ JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_OGLSurfaceData_initFBObject (JNIEnv *env, jobject oglsd, jlong pData, jboolean isOpaque, jboolean texNonPow2, jboolean texRect, jint width, jint height) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); GLuint fbobjectID, depthID; J2dTraceLn2(J2D_TRACE_INFO, "OGLSurfaceData_initFBObject: w=%d h=%d", width, height); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFBObject: ops are null"); return JNI_FALSE; } // initialize color texture object if (!OGLSD_InitTextureObject(oglsdo, isOpaque, texNonPow2, texRect, width, height)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFBObject: could not init texture object"); return JNI_FALSE; } // initialize framebuffer object using color texture created above if (!OGLSD_InitFBObject(&fbobjectID, &depthID, oglsdo->textureID, oglsdo->textureTarget, oglsdo->textureWidth, oglsdo->textureHeight)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFBObject: could not init fbobject"); j2d_glDeleteTextures(1, &oglsdo->textureID); return JNI_FALSE; } oglsdo->drawableType = OGLSD_FBOBJECT; // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() oglsdo->fbobjectID = fbobjectID; oglsdo->depthID = depthID; OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->textureWidth, oglsdo->textureHeight); // framebuffer objects differ from other OpenGL surfaces in that the // value passed to glRead/DrawBuffer() must be GL_COLOR_ATTACHMENTn_EXT, // rather than GL_FRONT (or GL_BACK) oglsdo->activeBuffer = GL_COLOR_ATTACHMENT0_EXT; return JNI_TRUE; }
/** * Initializes an OpenGL texture, using the given width and height as * a guide. See OGLSD_InitTextureObject() for more information. */ JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_OGLSurfaceData_initTexture (JNIEnv *env, jobject oglsd, jlong pData, jboolean isOpaque, jboolean texNonPow2, jboolean texRect, jint width, jint height) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); J2dTraceLn2(J2D_TRACE_INFO, "OGLSurfaceData_initTexture: w=%d h=%d", width, height); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initTexture: ops are null"); return JNI_FALSE; } /* * We only use the GL_ARB_texture_rectangle extension if it is available * and the requested bounds are not pow2 (it is probably faster to use * GL_TEXTURE_2D for pow2 textures, and besides, our TexturePaint * code relies on GL_REPEAT, which is not allowed for * GL_TEXTURE_RECTANGLE_ARB targets). */ texRect = texRect && !OGLSD_IsPowerOfTwo(width, height); if (!OGLSD_InitTextureObject(oglsdo, isOpaque, texNonPow2, texRect, width, height)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initTexture: could not init texture object"); return JNI_FALSE; } OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->textureWidth, oglsdo->textureHeight); oglsdo->drawableType = OGLSD_TEXTURE; // other fields (e.g. width, height) are set in OGLSD_InitTextureObject() return JNI_TRUE; }
/** * Initializes a surface in the backbuffer of a given double-buffered * onscreen window for use in a BufferStrategy.Flip situation. The bounds of * the backbuffer surface should always be kept in sync with the bounds of * the underlying native window. */ JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_OGLSurfaceData_initFlipBackbuffer (JNIEnv *env, jobject oglsd, jlong pData) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); J2dTraceLn(J2D_TRACE_INFO, "OGLSurfaceData_initFlipBackbuffer"); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFlipBackbuffer: ops are null"); return JNI_FALSE; } if (oglsdo->drawableType == OGLSD_UNDEFINED) { if (!OGLSD_InitOGLWindow(env, oglsdo)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFlipBackbuffer: could not init window"); return JNI_FALSE; } } if (oglsdo->drawableType != OGLSD_WINDOW) { J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSurfaceData_initFlipBackbuffer: drawable is not a window"); return JNI_FALSE; } oglsdo->drawableType = OGLSD_FLIP_BACKBUFFER; // x/yOffset have already been set in OGLSD_InitOGLWindow()... // REMIND: for some reason, flipping won't work properly on IFB unless we // explicitly use BACK_LEFT rather than BACK... oglsdo->activeBuffer = GL_BACK_LEFT; OGLSD_SetNativeDimensions(env, oglsdo, oglsdo->width, oglsdo->height); return JNI_TRUE; }
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; OGLSD_SetNativeDimensions(env, oglsdo, width, height); return JNI_TRUE; }
JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_WGLSurfaceData_initPbuffer (JNIEnv *env, jobject wglsd, jlong pData, jlong pConfigInfo, jboolean isOpaque, jint width, jint height) { int attrKeys[] = { WGL_MAX_PBUFFER_WIDTH_ARB, WGL_MAX_PBUFFER_HEIGHT_ARB, }; int attrVals[2]; int pbAttrList[] = { 0 }; OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); WGLGraphicsConfigInfo *wglInfo = (WGLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); WGLSDOps *wglsdo; HWND hwnd; HDC hdc, pbufferDC; HPBUFFERARB pbuffer; int maxWidth, maxHeight; int actualWidth, actualHeight; J2dTraceLn3(J2D_TRACE_INFO, "WGLSurfaceData_initPbuffer: w=%d h=%d opq=%d", width, height, isOpaque); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: ops are null"); return JNI_FALSE; } wglsdo = (WGLSDOps *)oglsdo->privOps; if (wglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: wgl ops are null"); return JNI_FALSE; } if (wglInfo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: wgl config info is null"); return JNI_FALSE; } // create a scratch window hwnd = WGLGC_CreateScratchWindow(wglInfo->screen); if (hwnd == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not create scratch window"); return JNI_FALSE; } // get the HDC for the scratch window hdc = GetDC(hwnd); if (hdc == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not get dc for scratch window"); DestroyWindow(hwnd); return JNI_FALSE; } // get the maximum allowable pbuffer dimensions j2d_wglGetPixelFormatAttribivARB(hdc, wglInfo->pixfmt, 0, 2, attrKeys, attrVals); maxWidth = attrVals[0]; maxHeight = attrVals[1]; J2dTraceLn4(J2D_TRACE_VERBOSE, " desired pbuffer dimensions: w=%d h=%d maxw=%d maxh=%d", width, height, maxWidth, maxHeight); // if either dimension is 0 or larger than the maximum, we cannot // allocate a pbuffer with the requested dimensions if (width == 0 || width > maxWidth || height == 0 || height > maxHeight) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: invalid dimensions"); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); return JNI_FALSE; } pbuffer = j2d_wglCreatePbufferARB(hdc, wglInfo->pixfmt, width, height, pbAttrList); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd); if (pbuffer == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not create wgl pbuffer"); return JNI_FALSE; } // note that we get the DC for the pbuffer at creation time, and then // release the DC when the pbuffer is disposed; the WGL_ARB_pbuffer // spec is vague about such things, but from past experience we know // this approach to be more robust than, for example, doing a // Get/ReleasePbufferDC() everytime we make a context current pbufferDC = j2d_wglGetPbufferDCARB(pbuffer); if (pbufferDC == 0) { J2dRlsTraceLn(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: could not get dc for pbuffer"); j2d_wglDestroyPbufferARB(pbuffer); return JNI_FALSE; } // make sure the actual dimensions match those that we requested j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_WIDTH_ARB, &actualWidth); j2d_wglQueryPbufferARB(pbuffer, WGL_PBUFFER_HEIGHT_ARB, &actualHeight); if (width != actualWidth || height != actualHeight) { J2dRlsTraceLn2(J2D_TRACE_ERROR, "WGLSurfaceData_initPbuffer: actual (w=%d h=%d) != requested", actualWidth, actualHeight); j2d_wglReleasePbufferDCARB(pbuffer, pbufferDC); j2d_wglDestroyPbufferARB(pbuffer); return JNI_FALSE; } oglsdo->drawableType = OGLSD_PBUFFER; oglsdo->isOpaque = isOpaque; oglsdo->width = width; oglsdo->height = height; wglsdo->pbuffer = pbuffer; wglsdo->pbufferDC = pbufferDC; OGLSD_SetNativeDimensions(env, oglsdo, width, height); return JNI_TRUE; }