--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include <jlong.h>
+
+#include "sun_java2d_opengl_GLXSurfaceData.h"
+
+#include "OGLRenderQueue.h"
+#include "GLXGraphicsConfig.h"
+#include "GLXSurfaceData.h"
+#include "awt_Component.h"
+#include "awt_GraphicsEnv.h"
+
+/**
+ * The methods in this file implement the native windowing system specific
+ * layer (GLX) for the OpenGL-based Java 2D pipeline.
+ */
+
+#ifndef HEADLESS
+
+extern LockFunc OGLSD_Lock;
+extern GetRasInfoFunc OGLSD_GetRasInfo;
+extern UnlockFunc OGLSD_Unlock;
+extern DisposeFunc OGLSD_Dispose;
+
+extern struct MComponentPeerIDs mComponentPeerIDs;
+
+jboolean surfaceCreationFailed = JNI_FALSE;
+
+#endif /* !HEADLESS */
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_opengl_GLXSurfaceData_initOps(JNIEnv *env, jobject glxsd,
+ jobject peer, jlong aData)
+{
+#ifndef HEADLESS
+ OGLSDOps *oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, glxsd,
+ sizeof(OGLSDOps));
+ GLXSDOps *glxsdo = (GLXSDOps *)malloc(sizeof(GLXSDOps));
+
+ J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps");
+
+ if (glxsdo == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "creating native GLX ops");
+ return;
+ }
+
+ oglsdo->privOps = glxsdo;
+
+ oglsdo->sdOps.Lock = OGLSD_Lock;
+ oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo;
+ oglsdo->sdOps.Unlock = OGLSD_Unlock;
+ oglsdo->sdOps.Dispose = OGLSD_Dispose;
+
+ oglsdo->drawableType = OGLSD_UNDEFINED;
+ oglsdo->activeBuffer = GL_FRONT;
+ oglsdo->needsInit = JNI_TRUE;
+
+#ifdef XAWT
+ if (peer != NULL) {
+ glxsdo->window = JNU_CallMethodByName(env, NULL, peer,
+ "getContentWindow", "()J").j;
+ } else {
+ glxsdo->window = 0;
+ }
+#else
+ if (peer != NULL) {
+ struct ComponentData *cdata;
+ cdata = (struct ComponentData *)
+ JNU_GetLongFieldAsPtr(env, peer, mComponentPeerIDs.pData);
+ if (cdata == NULL) {
+ free(glxsdo);
+ JNU_ThrowNullPointerException(env, "Component data missing");
+ return;
+ }
+ if (cdata->widget == NULL) {
+ free(glxsdo);
+ JNU_ThrowInternalError(env, "Widget is NULL in initOps");
+ return;
+ }
+ glxsdo->widget = cdata->widget;
+ } else {
+ glxsdo->widget = NULL;
+ }
+#endif
+
+ glxsdo->configData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(aData);
+ if (glxsdo->configData == NULL) {
+ free(glxsdo);
+ JNU_ThrowNullPointerException(env,
+ "Native GraphicsConfig data block missing");
+ return;
+ }
+
+ if (glxsdo->configData->glxInfo == NULL) {
+ free(glxsdo);
+ JNU_ThrowNullPointerException(env, "GLXGraphicsConfigInfo missing");
+ return;
+ }
+#endif /* HEADLESS */
+}
+
+#ifndef HEADLESS
+
+/**
+ * This function disposes of any native windowing system resources associated
+ * with this surface. For instance, if the given OGLSDOps is of type
+ * OGLSD_PBUFFER, this method implementation will destroy the actual pbuffer
+ * surface.
+ */
+void
+OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)
+{
+ GLXSDOps *glxsdo = (GLXSDOps *)oglsdo->privOps;
+
+ J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
+
+ if (oglsdo->drawableType == OGLSD_PBUFFER) {
+ if (glxsdo->drawable != 0) {
+ j2d_glXDestroyPbuffer(awt_display, glxsdo->drawable);
+ glxsdo->drawable = 0;
+ }
+ } else if (oglsdo->drawableType == OGLSD_WINDOW) {
+ // X Window is free'd later by AWT code...
+ }
+}
+
+/**
+ * Makes the given context current to its associated "scratch" surface. If
+ * the operation is successful, this method will return JNI_TRUE; otherwise,
+ * returns JNI_FALSE.
+ */
+static jboolean
+GLXSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)
+{
+ GLXCtxInfo *ctxInfo;
+
+ J2dTraceLn(J2D_TRACE_INFO, "GLXSD_MakeCurrentToScratch");
+
+ if (oglc == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "GLXSD_MakeCurrentToScratch: context is null");
+ return JNI_FALSE;
+ }
+
+ ctxInfo = (GLXCtxInfo *)oglc->ctxInfo;
+ if (!j2d_glXMakeContextCurrent(awt_display,
+ ctxInfo->scratchSurface,
+ ctxInfo->scratchSurface,
+ ctxInfo->context))
+ {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "GLXSD_MakeCurrentToScratch: could not make current");
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+/**
+ * Returns a pointer (as a jlong) to the native GLXGraphicsConfigInfo
+ * associated with the given OGLSDOps. This method can be called from
+ * shared code to retrieve the native GraphicsConfig data in a platform-
+ * independent manner.
+ */
+jlong
+OGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo)
+{
+ GLXSDOps *glxsdo;
+
+ if (oglsdo == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_GetNativeConfigInfo: ops are null");
+ return 0L;
+ }
+
+ glxsdo = (GLXSDOps *)oglsdo->privOps;
+ if (glxsdo == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_GetNativeConfigInfo: glx ops are null");
+ return 0L;
+ }
+
+ if (glxsdo->configData == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_GetNativeConfigInfo: config data is null");
+ return 0L;
+ }
+
+ return ptr_to_jlong(glxsdo->configData->glxInfo);
+}
+
+/**
+ * Makes the given GraphicsConfig's context current to its associated
+ * "scratch" surface. If there is a problem making the context current,
+ * this method will return NULL; otherwise, returns a pointer to the
+ * OGLContext that is associated with the given GraphicsConfig.
+ */
+OGLContext *
+OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)
+{
+ GLXGraphicsConfigInfo *glxInfo =
+ (GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
+ OGLContext *oglc;
+
+ J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");
+
+ if (glxInfo == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_SetScratchContext: glx config info is null");
+ return NULL;
+ }
+
+ oglc = glxInfo->context;
+ if (!GLXSD_MakeCurrentToScratch(env, oglc)) {
+ return NULL;
+ }
+
+ if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
+ // the GL_EXT_framebuffer_object extension is present, so this call
+ // will ensure that we are bound to the scratch pbuffer (and not
+ // some other framebuffer object)
+ j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+
+ return oglc;
+}
+
+/**
+ * Makes a context current to the given source and destination
+ * surfaces. If there is a problem making the context current, this method
+ * will return NULL; otherwise, returns a pointer to the OGLContext that is
+ * associated with the destination surface.
+ */
+OGLContext *
+OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)
+{
+ GLXSDOps *dstGLXOps = (GLXSDOps *)dstOps->privOps;
+ OGLContext *oglc;
+
+ J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");
+
+ oglc = dstGLXOps->configData->glxInfo->context;
+ if (oglc == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_MakeOGLContextCurrent: context is null");
+ return NULL;
+ }
+
+ if (dstOps->drawableType == OGLSD_FBOBJECT) {
+ OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
+
+ // first make sure we have a current context (if the context isn't
+ // already current to some drawable, we will make it current to
+ // its scratch surface)
+ if (oglc != currentContext) {
+ if (!GLXSD_MakeCurrentToScratch(env, oglc)) {
+ return NULL;
+ }
+ }
+
+ // now bind to the fbobject associated with the destination surface;
+ // this means that all rendering will go into the fbobject destination
+ // (note that we unbind the currently bound texture first; this is
+ // recommended procedure when binding an fbobject)
+ j2d_glBindTexture(dstOps->textureTarget, 0);
+ j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
+ } else {
+ GLXSDOps *srcGLXOps = (GLXSDOps *)srcOps->privOps;
+ GLXCtxInfo *ctxinfo = (GLXCtxInfo *)oglc->ctxInfo;
+
+ // make the context current
+ if (!j2d_glXMakeContextCurrent(awt_display,
+ dstGLXOps->drawable,
+ srcGLXOps->drawable,
+ ctxinfo->context))
+ {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_MakeOGLContextCurrent: could not make current");
+ return NULL;
+ }
+
+ if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
+ // the GL_EXT_framebuffer_object extension is present, so we
+ // must bind to the default (windowing system provided)
+ // framebuffer
+ j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+ }
+
+ return oglc;
+}
+
+/**
+ * This function initializes a native window surface and caches the window
+ * bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was
+ * successful; JNI_FALSE otherwise.
+ */
+jboolean
+OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
+{
+ GLXSDOps *glxsdo;
+ Window window;
+#ifdef XAWT
+ XWindowAttributes attr;
+#else
+ Widget widget;
+#endif
+
+ J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
+
+ if (oglsdo == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_InitOGLWindow: ops are null");
+ return JNI_FALSE;
+ }
+
+ glxsdo = (GLXSDOps *)oglsdo->privOps;
+ if (glxsdo == NULL) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_InitOGLWindow: glx ops are null");
+ return JNI_FALSE;
+ }
+
+#ifdef XAWT
+ window = glxsdo->window;
+ if (window == 0) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_InitOGLWindow: window is invalid");
+ return JNI_FALSE;
+ }
+
+ XGetWindowAttributes(awt_display, window, &attr);
+ oglsdo->width = attr.width;
+ oglsdo->height = attr.height;
+#else
+ widget = glxsdo->widget;
+ if (widget == NULL) {
+ J2dTraceLn(J2D_TRACE_WARNING, "OGLSD_InitOGLWindow: widget is null");
+ }
+
+ if (!XtIsRealized(widget)) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_InitOGLWindow: widget is unrealized");
+ return JNI_FALSE;
+ }
+
+ window = XtWindow(widget);
+ oglsdo->width = widget->core.width;
+ oglsdo->height = widget->core.height;
+#endif
+
+ oglsdo->drawableType = OGLSD_WINDOW;
+ oglsdo->isOpaque = JNI_TRUE;
+ oglsdo->xOffset = 0;
+ oglsdo->yOffset = 0;
+ glxsdo->drawable = window;
+ glxsdo->xdrawable = window;
+
+ J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d",
+ oglsdo->width, oglsdo->height);
+
+ return JNI_TRUE;
+}
+
+static int
+GLXSD_BadAllocXErrHandler(Display *display, XErrorEvent *xerr)
+{
+ int ret = 0;
+ if (xerr->error_code == BadAlloc) {
+ surfaceCreationFailed = JNI_TRUE;
+ } else {
+ ret = (*xerror_saved_handler)(display, xerr);
+ }
+ return ret;
+}
+
+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;
+}
+
+void
+OGLSD_SwapBuffers(JNIEnv *env, jlong window)
+{
+ J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
+
+ if (window == 0L) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "OGLSD_SwapBuffers: window is null");
+ return;
+ }
+
+ j2d_glXSwapBuffers(awt_display, (Window)window);
+}
+
+#endif /* !HEADLESS */