0N/A/*
6447N/A * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <jlong.h>
0N/A
0N/A#include "sun_java2d_opengl_GLXSurfaceData.h"
0N/A
0N/A#include "OGLRenderQueue.h"
0N/A#include "GLXGraphicsConfig.h"
0N/A#include "GLXSurfaceData.h"
0N/A#include "awt_Component.h"
0N/A#include "awt_GraphicsEnv.h"
0N/A
0N/A/**
0N/A * The methods in this file implement the native windowing system specific
0N/A * layer (GLX) for the OpenGL-based Java 2D pipeline.
0N/A */
0N/A
0N/A#ifndef HEADLESS
0N/A
0N/Aextern LockFunc OGLSD_Lock;
0N/Aextern GetRasInfoFunc OGLSD_GetRasInfo;
0N/Aextern UnlockFunc OGLSD_Unlock;
0N/Aextern DisposeFunc OGLSD_Dispose;
0N/A
0N/Aextern struct MComponentPeerIDs mComponentPeerIDs;
0N/A
430N/Aextern void
430N/A OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);
430N/A
0N/A#endif /* !HEADLESS */
0N/A
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_java2d_opengl_GLXSurfaceData_initOps(JNIEnv *env, jobject glxsd,
0N/A jobject peer, jlong aData)
0N/A{
0N/A#ifndef HEADLESS
0N/A OGLSDOps *oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, glxsd,
0N/A sizeof(OGLSDOps));
0N/A GLXSDOps *glxsdo = (GLXSDOps *)malloc(sizeof(GLXSDOps));
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps");
0N/A
2514N/A if (oglsdo == NULL) {
2514N/A JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
2514N/A return;
2514N/A }
2514N/A
0N/A if (glxsdo == NULL) {
0N/A JNU_ThrowOutOfMemoryError(env, "creating native GLX ops");
0N/A return;
0N/A }
0N/A
0N/A oglsdo->privOps = glxsdo;
0N/A
0N/A oglsdo->sdOps.Lock = OGLSD_Lock;
0N/A oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo;
0N/A oglsdo->sdOps.Unlock = OGLSD_Unlock;
0N/A oglsdo->sdOps.Dispose = OGLSD_Dispose;
0N/A
0N/A oglsdo->drawableType = OGLSD_UNDEFINED;
0N/A oglsdo->activeBuffer = GL_FRONT;
0N/A oglsdo->needsInit = JNI_TRUE;
0N/A
0N/A#ifdef XAWT
0N/A if (peer != NULL) {
0N/A glxsdo->window = JNU_CallMethodByName(env, NULL, peer,
0N/A "getContentWindow", "()J").j;
0N/A } else {
0N/A glxsdo->window = 0;
0N/A }
0N/A#else
0N/A if (peer != NULL) {
0N/A struct ComponentData *cdata;
0N/A cdata = (struct ComponentData *)
0N/A JNU_GetLongFieldAsPtr(env, peer, mComponentPeerIDs.pData);
0N/A if (cdata == NULL) {
0N/A free(glxsdo);
0N/A JNU_ThrowNullPointerException(env, "Component data missing");
0N/A return;
0N/A }
0N/A if (cdata->widget == NULL) {
0N/A free(glxsdo);
0N/A JNU_ThrowInternalError(env, "Widget is NULL in initOps");
0N/A return;
0N/A }
0N/A glxsdo->widget = cdata->widget;
0N/A } else {
0N/A glxsdo->widget = NULL;
0N/A }
0N/A#endif
0N/A
0N/A glxsdo->configData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(aData);
0N/A if (glxsdo->configData == NULL) {
0N/A free(glxsdo);
0N/A JNU_ThrowNullPointerException(env,
0N/A "Native GraphicsConfig data block missing");
0N/A return;
0N/A }
0N/A
0N/A if (glxsdo->configData->glxInfo == NULL) {
0N/A free(glxsdo);
0N/A JNU_ThrowNullPointerException(env, "GLXGraphicsConfigInfo missing");
0N/A return;
0N/A }
0N/A#endif /* HEADLESS */
0N/A}
0N/A
0N/A#ifndef HEADLESS
0N/A
0N/A/**
0N/A * This function disposes of any native windowing system resources associated
0N/A * with this surface. For instance, if the given OGLSDOps is of type
0N/A * OGLSD_PBUFFER, this method implementation will destroy the actual pbuffer
0N/A * surface.
0N/A */
0N/Avoid
0N/AOGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)
0N/A{
0N/A GLXSDOps *glxsdo = (GLXSDOps *)oglsdo->privOps;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");
0N/A
0N/A if (oglsdo->drawableType == OGLSD_PBUFFER) {
0N/A if (glxsdo->drawable != 0) {
0N/A j2d_glXDestroyPbuffer(awt_display, glxsdo->drawable);
0N/A glxsdo->drawable = 0;
0N/A }
0N/A } else if (oglsdo->drawableType == OGLSD_WINDOW) {
0N/A // X Window is free'd later by AWT code...
0N/A }
0N/A}
0N/A
0N/A/**
0N/A * Makes the given context current to its associated "scratch" surface. If
0N/A * the operation is successful, this method will return JNI_TRUE; otherwise,
0N/A * returns JNI_FALSE.
0N/A */
0N/Astatic jboolean
0N/AGLXSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)
0N/A{
0N/A GLXCtxInfo *ctxInfo;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "GLXSD_MakeCurrentToScratch");
0N/A
0N/A if (oglc == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "GLXSD_MakeCurrentToScratch: context is null");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A ctxInfo = (GLXCtxInfo *)oglc->ctxInfo;
0N/A if (!j2d_glXMakeContextCurrent(awt_display,
0N/A ctxInfo->scratchSurface,
0N/A ctxInfo->scratchSurface,
0N/A ctxInfo->context))
0N/A {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "GLXSD_MakeCurrentToScratch: could not make current");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/A/**
0N/A * Returns a pointer (as a jlong) to the native GLXGraphicsConfigInfo
0N/A * associated with the given OGLSDOps. This method can be called from
0N/A * shared code to retrieve the native GraphicsConfig data in a platform-
0N/A * independent manner.
0N/A */
0N/Ajlong
0N/AOGLSD_GetNativeConfigInfo(OGLSDOps *oglsdo)
0N/A{
0N/A GLXSDOps *glxsdo;
0N/A
0N/A if (oglsdo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_GetNativeConfigInfo: ops are null");
0N/A return 0L;
0N/A }
0N/A
0N/A glxsdo = (GLXSDOps *)oglsdo->privOps;
0N/A if (glxsdo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_GetNativeConfigInfo: glx ops are null");
0N/A return 0L;
0N/A }
0N/A
0N/A if (glxsdo->configData == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_GetNativeConfigInfo: config data is null");
0N/A return 0L;
0N/A }
0N/A
0N/A return ptr_to_jlong(glxsdo->configData->glxInfo);
0N/A}
0N/A
0N/A/**
0N/A * Makes the given GraphicsConfig's context current to its associated
0N/A * "scratch" surface. If there is a problem making the context current,
0N/A * this method will return NULL; otherwise, returns a pointer to the
0N/A * OGLContext that is associated with the given GraphicsConfig.
0N/A */
0N/AOGLContext *
0N/AOGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)
0N/A{
0N/A GLXGraphicsConfigInfo *glxInfo =
0N/A (GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
0N/A OGLContext *oglc;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");
0N/A
0N/A if (glxInfo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_SetScratchContext: glx config info is null");
0N/A return NULL;
0N/A }
0N/A
0N/A oglc = glxInfo->context;
0N/A if (!GLXSD_MakeCurrentToScratch(env, oglc)) {
0N/A return NULL;
0N/A }
0N/A
0N/A if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
0N/A // the GL_EXT_framebuffer_object extension is present, so this call
0N/A // will ensure that we are bound to the scratch pbuffer (and not
0N/A // some other framebuffer object)
0N/A j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
0N/A }
0N/A
0N/A return oglc;
0N/A}
0N/A
0N/A/**
0N/A * Makes a context current to the given source and destination
0N/A * surfaces. If there is a problem making the context current, this method
0N/A * will return NULL; otherwise, returns a pointer to the OGLContext that is
0N/A * associated with the destination surface.
0N/A */
0N/AOGLContext *
0N/AOGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)
0N/A{
0N/A GLXSDOps *dstGLXOps = (GLXSDOps *)dstOps->privOps;
0N/A OGLContext *oglc;
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");
0N/A
0N/A oglc = dstGLXOps->configData->glxInfo->context;
0N/A if (oglc == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_MakeOGLContextCurrent: context is null");
0N/A return NULL;
0N/A }
0N/A
0N/A if (dstOps->drawableType == OGLSD_FBOBJECT) {
0N/A OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();
0N/A
0N/A // first make sure we have a current context (if the context isn't
0N/A // already current to some drawable, we will make it current to
0N/A // its scratch surface)
0N/A if (oglc != currentContext) {
0N/A if (!GLXSD_MakeCurrentToScratch(env, oglc)) {
0N/A return NULL;
0N/A }
0N/A }
0N/A
0N/A // now bind to the fbobject associated with the destination surface;
0N/A // this means that all rendering will go into the fbobject destination
0N/A // (note that we unbind the currently bound texture first; this is
0N/A // recommended procedure when binding an fbobject)
0N/A j2d_glBindTexture(dstOps->textureTarget, 0);
0N/A j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);
0N/A } else {
0N/A GLXSDOps *srcGLXOps = (GLXSDOps *)srcOps->privOps;
0N/A GLXCtxInfo *ctxinfo = (GLXCtxInfo *)oglc->ctxInfo;
0N/A
0N/A // make the context current
0N/A if (!j2d_glXMakeContextCurrent(awt_display,
0N/A dstGLXOps->drawable,
0N/A srcGLXOps->drawable,
0N/A ctxinfo->context))
0N/A {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_MakeOGLContextCurrent: could not make current");
0N/A return NULL;
0N/A }
0N/A
0N/A if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {
0N/A // the GL_EXT_framebuffer_object extension is present, so we
0N/A // must bind to the default (windowing system provided)
0N/A // framebuffer
0N/A j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
0N/A }
0N/A }
0N/A
0N/A return oglc;
0N/A}
0N/A
0N/A/**
0N/A * This function initializes a native window surface and caches the window
0N/A * bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was
0N/A * successful; JNI_FALSE otherwise.
0N/A */
0N/Ajboolean
0N/AOGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)
0N/A{
0N/A GLXSDOps *glxsdo;
0N/A Window window;
0N/A#ifdef XAWT
0N/A XWindowAttributes attr;
0N/A#else
0N/A Widget widget;
0N/A#endif
0N/A
0N/A J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");
0N/A
0N/A if (oglsdo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_InitOGLWindow: ops are null");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A glxsdo = (GLXSDOps *)oglsdo->privOps;
0N/A if (glxsdo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_InitOGLWindow: glx ops are null");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A#ifdef XAWT
0N/A window = glxsdo->window;
0N/A if (window == 0) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_InitOGLWindow: window is invalid");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A XGetWindowAttributes(awt_display, window, &attr);
0N/A oglsdo->width = attr.width;
0N/A oglsdo->height = attr.height;
0N/A#else
0N/A widget = glxsdo->widget;
0N/A if (widget == NULL) {
0N/A J2dTraceLn(J2D_TRACE_WARNING, "OGLSD_InitOGLWindow: widget is null");
0N/A }
0N/A
0N/A if (!XtIsRealized(widget)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_InitOGLWindow: widget is unrealized");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A window = XtWindow(widget);
0N/A oglsdo->width = widget->core.width;
0N/A oglsdo->height = widget->core.height;
0N/A#endif
0N/A
0N/A oglsdo->drawableType = OGLSD_WINDOW;
0N/A oglsdo->isOpaque = JNI_TRUE;
0N/A oglsdo->xOffset = 0;
0N/A oglsdo->yOffset = 0;
0N/A glxsdo->drawable = window;
0N/A glxsdo->xdrawable = window;
0N/A
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d",
0N/A oglsdo->width, oglsdo->height);
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/AJNIEXPORT jboolean JNICALL
0N/AJava_sun_java2d_opengl_GLXSurfaceData_initPbuffer
0N/A (JNIEnv *env, jobject glxsd,
0N/A jlong pData, jlong pConfigInfo,
0N/A jboolean isOpaque,
0N/A jint width, jint height)
0N/A{
0N/A OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
0N/A GLXGraphicsConfigInfo *glxinfo =
0N/A (GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
0N/A GLXSDOps *glxsdo;
0N/A GLXPbuffer pbuffer;
0N/A int attrlist[] = {GLX_PBUFFER_WIDTH, 0,
0N/A GLX_PBUFFER_HEIGHT, 0,
0N/A GLX_PRESERVED_CONTENTS, GL_FALSE, 0};
6447N/A jboolean errorOccurredFlag;
6447N/A jobject errorHandlerRef;
0N/A
0N/A J2dTraceLn3(J2D_TRACE_INFO,
0N/A "GLXSurfaceData_initPbuffer: w=%d h=%d opq=%d",
0N/A width, height, isOpaque);
0N/A
0N/A if (oglsdo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "GLXSurfaceData_initPbuffer: ops are null");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A glxsdo = (GLXSDOps *)oglsdo->privOps;
0N/A if (glxsdo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "GLXSurfaceData_initPbuffer: glx ops are null");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A if (glxinfo == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "GLXSurfaceData_initPbuffer: glx config info is null");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A attrlist[1] = width;
0N/A attrlist[3] = height;
0N/A
6447N/A WITH_XERROR_HANDLER(env, "sun/awt/X11/XErrorHandler$GLXBadAllocHandler",
6447N/A "()Lsun/awt/X11/XErrorHandler$GLXBadAllocHandler;", JNI_TRUE, errorHandlerRef);
6447N/A pbuffer = j2d_glXCreatePbuffer(awt_display, glxinfo->fbconfig, attrlist);
6447N/A // Call XSync without the acquired AWT lock to avoid a deadlock (see 8015730).
6447N/A XSync(awt_display, False);
6447N/A RESTORE_XERROR_HANDLER(env, JNI_FALSE);
6447N/A errorOccurredFlag = GET_HANDLER_ERROR_OCCURRED_FLAG(env, errorHandlerRef);
6447N/A
6447N/A if ((pbuffer == 0) || errorOccurredFlag) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "GLXSurfaceData_initPbuffer: could not create glx pbuffer");
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A oglsdo->drawableType = OGLSD_PBUFFER;
0N/A oglsdo->isOpaque = isOpaque;
0N/A oglsdo->width = width;
0N/A oglsdo->height = height;
0N/A oglsdo->xOffset = 0;
0N/A oglsdo->yOffset = 0;
0N/A
0N/A glxsdo->drawable = pbuffer;
0N/A glxsdo->xdrawable = 0;
0N/A
430N/A OGLSD_SetNativeDimensions(env, oglsdo, width, height);
430N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
0N/Avoid
0N/AOGLSD_SwapBuffers(JNIEnv *env, jlong window)
0N/A{
0N/A J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");
0N/A
0N/A if (window == 0L) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "OGLSD_SwapBuffers: window is null");
0N/A return;
0N/A }
0N/A
0N/A j2d_glXSwapBuffers(awt_display, (Window)window);
0N/A}
0N/A
4632N/A// needed by Mac OS X port, no-op on other platforms
4632N/Avoid
4632N/AOGLSD_Flush(JNIEnv *env)
4632N/A{
4632N/A}
4632N/A
0N/A#endif /* !HEADLESS */