Path: blob/master/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c
41159 views
/*1* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <jlong.h>2627#include "sun_java2d_opengl_GLXSurfaceData.h"2829#include "OGLRenderQueue.h"30#include "GLXGraphicsConfig.h"31#include "GLXSurfaceData.h"32#include "awt_Component.h"33#include "awt_GraphicsEnv.h"3435/**36* The methods in this file implement the native windowing system specific37* layer (GLX) for the OpenGL-based Java 2D pipeline.38*/3940#ifndef HEADLESS4142extern LockFunc OGLSD_Lock;43extern GetRasInfoFunc OGLSD_GetRasInfo;44extern UnlockFunc OGLSD_Unlock;45extern DisposeFunc OGLSD_Dispose;4647extern void48OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, jint w, jint h);4950jboolean surfaceCreationFailed = JNI_FALSE;5152#endif /* !HEADLESS */5354JNIEXPORT void JNICALL55Java_sun_java2d_opengl_GLXSurfaceData_initOps(JNIEnv *env, jobject glxsd,56jobject gc,57jobject peer, jlong aData)58{59#ifndef HEADLESS60gc = (*env)->NewGlobalRef(env, gc);61if (gc == NULL) {62JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");63return;64}6566OGLSDOps *oglsdo = (OGLSDOps *)SurfaceData_InitOps(env, glxsd,67sizeof(OGLSDOps));68if (oglsdo == NULL) {69(*env)->DeleteGlobalRef(env, gc);70JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");71return;72}73// later the graphicsConfig will be used for deallocation of oglsdo74oglsdo->graphicsConfig = gc;7576GLXSDOps *glxsdo = (GLXSDOps *)malloc(sizeof(GLXSDOps));7778if (glxsdo == NULL) {79JNU_ThrowOutOfMemoryError(env, "creating native GLX ops");80return;81}8283J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps");8485oglsdo->privOps = glxsdo;8687oglsdo->sdOps.Lock = OGLSD_Lock;88oglsdo->sdOps.GetRasInfo = OGLSD_GetRasInfo;89oglsdo->sdOps.Unlock = OGLSD_Unlock;90oglsdo->sdOps.Dispose = OGLSD_Dispose;9192oglsdo->drawableType = OGLSD_UNDEFINED;93oglsdo->activeBuffer = GL_FRONT;94oglsdo->needsInit = JNI_TRUE;9596if (peer != NULL) {97glxsdo->window = JNU_CallMethodByName(env, NULL, peer,98"getContentWindow", "()J").j;99} else {100glxsdo->window = 0;101}102glxsdo->configData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(aData);103if (glxsdo->configData == NULL) {104free(glxsdo);105JNU_ThrowNullPointerException(env,106"Native GraphicsConfig data block missing");107return;108}109110if (glxsdo->configData->glxInfo == NULL) {111free(glxsdo);112JNU_ThrowNullPointerException(env, "GLXGraphicsConfigInfo missing");113return;114}115#endif /* HEADLESS */116}117118#ifndef HEADLESS119120/**121* This function disposes of any native windowing system resources associated122* with this surface.123*/124void125OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)126{127J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");128// X Window is free'd later by AWT code...129}130131/**132* Makes the given context current to its associated "scratch" surface. If133* the operation is successful, this method will return JNI_TRUE; otherwise,134* returns JNI_FALSE.135*/136static jboolean137GLXSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)138{139GLXCtxInfo *ctxInfo;140141J2dTraceLn(J2D_TRACE_INFO, "GLXSD_MakeCurrentToScratch");142143if (oglc == NULL) {144J2dRlsTraceLn(J2D_TRACE_ERROR,145"GLXSD_MakeCurrentToScratch: context is null");146return JNI_FALSE;147}148149ctxInfo = (GLXCtxInfo *)oglc->ctxInfo;150if (!j2d_glXMakeContextCurrent(awt_display,151ctxInfo->scratchSurface,152ctxInfo->scratchSurface,153ctxInfo->context))154{155J2dRlsTraceLn(J2D_TRACE_ERROR,156"GLXSD_MakeCurrentToScratch: could not make current");157return JNI_FALSE;158}159160return JNI_TRUE;161}162163/**164* Makes the given GraphicsConfig's context current to its associated165* "scratch" surface. If there is a problem making the context current,166* this method will return NULL; otherwise, returns a pointer to the167* OGLContext that is associated with the given GraphicsConfig.168*/169OGLContext *170OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)171{172GLXGraphicsConfigInfo *glxInfo =173(GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);174OGLContext *oglc;175176J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");177178if (glxInfo == NULL) {179J2dRlsTraceLn(J2D_TRACE_ERROR,180"OGLSD_SetScratchContext: glx config info is null");181return NULL;182}183184oglc = glxInfo->context;185if (!GLXSD_MakeCurrentToScratch(env, oglc)) {186return NULL;187}188189if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {190// the GL_EXT_framebuffer_object extension is present, so this call191// will ensure that we are bound to the scratch pbuffer (and not192// some other framebuffer object)193j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);194}195196return oglc;197}198199/**200* Makes a context current to the given source and destination201* surfaces. If there is a problem making the context current, this method202* will return NULL; otherwise, returns a pointer to the OGLContext that is203* associated with the destination surface.204*/205OGLContext *206OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)207{208GLXSDOps *dstGLXOps = (GLXSDOps *)dstOps->privOps;209OGLContext *oglc;210211J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");212213oglc = dstGLXOps->configData->glxInfo->context;214if (oglc == NULL) {215J2dRlsTraceLn(J2D_TRACE_ERROR,216"OGLSD_MakeOGLContextCurrent: context is null");217return NULL;218}219220if (dstOps->drawableType == OGLSD_FBOBJECT) {221OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();222223// first make sure we have a current context (if the context isn't224// already current to some drawable, we will make it current to225// its scratch surface)226if (oglc != currentContext) {227if (!GLXSD_MakeCurrentToScratch(env, oglc)) {228return NULL;229}230}231232// now bind to the fbobject associated with the destination surface;233// this means that all rendering will go into the fbobject destination234// (note that we unbind the currently bound texture first; this is235// recommended procedure when binding an fbobject)236j2d_glBindTexture(dstOps->textureTarget, 0);237j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);238} else {239GLXSDOps *srcGLXOps = (GLXSDOps *)srcOps->privOps;240GLXCtxInfo *ctxinfo = (GLXCtxInfo *)oglc->ctxInfo;241242// make the context current243if (!j2d_glXMakeContextCurrent(awt_display,244dstGLXOps->drawable,245srcGLXOps->drawable,246ctxinfo->context))247{248J2dRlsTraceLn(J2D_TRACE_ERROR,249"OGLSD_MakeOGLContextCurrent: could not make current");250return NULL;251}252253if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {254// the GL_EXT_framebuffer_object extension is present, so we255// must bind to the default (windowing system provided)256// framebuffer257j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);258}259}260261return oglc;262}263264/**265* This function initializes a native window surface and caches the window266* bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was267* successful; JNI_FALSE otherwise.268*/269jboolean270OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)271{272GLXSDOps *glxsdo;273Window window;274XWindowAttributes attr;275276J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");277278if (oglsdo == NULL) {279J2dRlsTraceLn(J2D_TRACE_ERROR,280"OGLSD_InitOGLWindow: ops are null");281return JNI_FALSE;282}283284glxsdo = (GLXSDOps *)oglsdo->privOps;285if (glxsdo == NULL) {286J2dRlsTraceLn(J2D_TRACE_ERROR,287"OGLSD_InitOGLWindow: glx ops are null");288return JNI_FALSE;289}290291window = glxsdo->window;292if (window == 0) {293J2dRlsTraceLn(J2D_TRACE_ERROR,294"OGLSD_InitOGLWindow: window is invalid");295return JNI_FALSE;296}297298XGetWindowAttributes(awt_display, window, &attr);299oglsdo->width = attr.width;300oglsdo->height = attr.height;301302oglsdo->drawableType = OGLSD_WINDOW;303oglsdo->isOpaque = JNI_TRUE;304oglsdo->xOffset = 0;305oglsdo->yOffset = 0;306glxsdo->drawable = window;307glxsdo->xdrawable = window;308309J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d",310oglsdo->width, oglsdo->height);311312return JNI_TRUE;313}314315static int316GLXSD_BadAllocXErrHandler(Display *display, XErrorEvent *xerr)317{318if (xerr->error_code == BadAlloc) {319surfaceCreationFailed = JNI_TRUE;320}321return 0;322}323324void325OGLSD_SwapBuffers(JNIEnv *env, jlong window)326{327J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");328329if (window == 0L) {330J2dRlsTraceLn(J2D_TRACE_ERROR,331"OGLSD_SwapBuffers: window is null");332return;333}334335j2d_glXSwapBuffers(awt_display, (Window)window);336}337338// needed by Mac OS X port, no-op on other platforms339void340OGLSD_Flush(JNIEnv *env)341{342}343344#endif /* !HEADLESS */345346347