Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c
32288 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. For instance, if the given OGLSDOps is of type123* OGLSD_PBUFFER, this method implementation will destroy the actual pbuffer124* surface.125*/126void127OGLSD_DestroyOGLSurface(JNIEnv *env, OGLSDOps *oglsdo)128{129GLXSDOps *glxsdo = (GLXSDOps *)oglsdo->privOps;130131J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface");132133if (oglsdo->drawableType == OGLSD_PBUFFER) {134if (glxsdo->drawable != 0) {135j2d_glXDestroyPbuffer(awt_display, glxsdo->drawable);136glxsdo->drawable = 0;137}138} else if (oglsdo->drawableType == OGLSD_WINDOW) {139// X Window is free'd later by AWT code...140}141}142143/**144* Makes the given context current to its associated "scratch" surface. If145* the operation is successful, this method will return JNI_TRUE; otherwise,146* returns JNI_FALSE.147*/148static jboolean149GLXSD_MakeCurrentToScratch(JNIEnv *env, OGLContext *oglc)150{151GLXCtxInfo *ctxInfo;152153J2dTraceLn(J2D_TRACE_INFO, "GLXSD_MakeCurrentToScratch");154155if (oglc == NULL) {156J2dRlsTraceLn(J2D_TRACE_ERROR,157"GLXSD_MakeCurrentToScratch: context is null");158return JNI_FALSE;159}160161ctxInfo = (GLXCtxInfo *)oglc->ctxInfo;162if (!j2d_glXMakeContextCurrent(awt_display,163ctxInfo->scratchSurface,164ctxInfo->scratchSurface,165ctxInfo->context))166{167J2dRlsTraceLn(J2D_TRACE_ERROR,168"GLXSD_MakeCurrentToScratch: could not make current");169return JNI_FALSE;170}171172return JNI_TRUE;173}174175/**176* Makes the given GraphicsConfig's context current to its associated177* "scratch" surface. If there is a problem making the context current,178* this method will return NULL; otherwise, returns a pointer to the179* OGLContext that is associated with the given GraphicsConfig.180*/181OGLContext *182OGLSD_SetScratchSurface(JNIEnv *env, jlong pConfigInfo)183{184GLXGraphicsConfigInfo *glxInfo =185(GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);186OGLContext *oglc;187188J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SetScratchContext");189190if (glxInfo == NULL) {191J2dRlsTraceLn(J2D_TRACE_ERROR,192"OGLSD_SetScratchContext: glx config info is null");193return NULL;194}195196oglc = glxInfo->context;197if (!GLXSD_MakeCurrentToScratch(env, oglc)) {198return NULL;199}200201if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {202// the GL_EXT_framebuffer_object extension is present, so this call203// will ensure that we are bound to the scratch pbuffer (and not204// some other framebuffer object)205j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);206}207208return oglc;209}210211/**212* Makes a context current to the given source and destination213* surfaces. If there is a problem making the context current, this method214* will return NULL; otherwise, returns a pointer to the OGLContext that is215* associated with the destination surface.216*/217OGLContext *218OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps)219{220GLXSDOps *dstGLXOps = (GLXSDOps *)dstOps->privOps;221OGLContext *oglc;222223J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent");224225oglc = dstGLXOps->configData->glxInfo->context;226if (oglc == NULL) {227J2dRlsTraceLn(J2D_TRACE_ERROR,228"OGLSD_MakeOGLContextCurrent: context is null");229return NULL;230}231232if (dstOps->drawableType == OGLSD_FBOBJECT) {233OGLContext *currentContext = OGLRenderQueue_GetCurrentContext();234235// first make sure we have a current context (if the context isn't236// already current to some drawable, we will make it current to237// its scratch surface)238if (oglc != currentContext) {239if (!GLXSD_MakeCurrentToScratch(env, oglc)) {240return NULL;241}242}243244// now bind to the fbobject associated with the destination surface;245// this means that all rendering will go into the fbobject destination246// (note that we unbind the currently bound texture first; this is247// recommended procedure when binding an fbobject)248j2d_glBindTexture(dstOps->textureTarget, 0);249j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dstOps->fbobjectID);250} else {251GLXSDOps *srcGLXOps = (GLXSDOps *)srcOps->privOps;252GLXCtxInfo *ctxinfo = (GLXCtxInfo *)oglc->ctxInfo;253254// make the context current255if (!j2d_glXMakeContextCurrent(awt_display,256dstGLXOps->drawable,257srcGLXOps->drawable,258ctxinfo->context))259{260J2dRlsTraceLn(J2D_TRACE_ERROR,261"OGLSD_MakeOGLContextCurrent: could not make current");262return NULL;263}264265if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_FBOBJECT)) {266// the GL_EXT_framebuffer_object extension is present, so we267// must bind to the default (windowing system provided)268// framebuffer269j2d_glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);270}271}272273return oglc;274}275276/**277* This function initializes a native window surface and caches the window278* bounds in the given OGLSDOps. Returns JNI_TRUE if the operation was279* successful; JNI_FALSE otherwise.280*/281jboolean282OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo)283{284GLXSDOps *glxsdo;285Window window;286XWindowAttributes attr;287288J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitOGLWindow");289290if (oglsdo == NULL) {291J2dRlsTraceLn(J2D_TRACE_ERROR,292"OGLSD_InitOGLWindow: ops are null");293return JNI_FALSE;294}295296glxsdo = (GLXSDOps *)oglsdo->privOps;297if (glxsdo == NULL) {298J2dRlsTraceLn(J2D_TRACE_ERROR,299"OGLSD_InitOGLWindow: glx ops are null");300return JNI_FALSE;301}302303window = glxsdo->window;304if (window == 0) {305J2dRlsTraceLn(J2D_TRACE_ERROR,306"OGLSD_InitOGLWindow: window is invalid");307return JNI_FALSE;308}309310XGetWindowAttributes(awt_display, window, &attr);311oglsdo->width = attr.width;312oglsdo->height = attr.height;313314oglsdo->drawableType = OGLSD_WINDOW;315oglsdo->isOpaque = JNI_TRUE;316oglsdo->xOffset = 0;317oglsdo->yOffset = 0;318glxsdo->drawable = window;319glxsdo->xdrawable = window;320321J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d",322oglsdo->width, oglsdo->height);323324return JNI_TRUE;325}326327static int328GLXSD_BadAllocXErrHandler(Display *display, XErrorEvent *xerr)329{330if (xerr->error_code == BadAlloc) {331surfaceCreationFailed = JNI_TRUE;332}333return 0;334}335336JNIEXPORT jboolean JNICALL337Java_sun_java2d_opengl_GLXSurfaceData_initPbuffer338(JNIEnv *env, jobject glxsd,339jlong pData, jlong pConfigInfo,340jboolean isOpaque,341jint width, jint height)342{343OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);344GLXGraphicsConfigInfo *glxinfo =345(GLXGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);346GLXSDOps *glxsdo;347GLXPbuffer pbuffer;348int attrlist[] = {GLX_PBUFFER_WIDTH, 0,349GLX_PBUFFER_HEIGHT, 0,350GLX_PRESERVED_CONTENTS, GL_FALSE, 0};351352J2dTraceLn3(J2D_TRACE_INFO,353"GLXSurfaceData_initPbuffer: w=%d h=%d opq=%d",354width, height, isOpaque);355356if (oglsdo == NULL) {357J2dRlsTraceLn(J2D_TRACE_ERROR,358"GLXSurfaceData_initPbuffer: ops are null");359return JNI_FALSE;360}361362glxsdo = (GLXSDOps *)oglsdo->privOps;363if (glxsdo == NULL) {364J2dRlsTraceLn(J2D_TRACE_ERROR,365"GLXSurfaceData_initPbuffer: glx ops are null");366return JNI_FALSE;367}368369if (glxinfo == NULL) {370J2dRlsTraceLn(J2D_TRACE_ERROR,371"GLXSurfaceData_initPbuffer: glx config info is null");372return JNI_FALSE;373}374375attrlist[1] = width;376attrlist[3] = height;377378surfaceCreationFailed = JNI_FALSE;379EXEC_WITH_XERROR_HANDLER(380GLXSD_BadAllocXErrHandler,381pbuffer = j2d_glXCreatePbuffer(awt_display,382glxinfo->fbconfig, attrlist));383if ((pbuffer == 0) || surfaceCreationFailed) {384J2dRlsTraceLn(J2D_TRACE_ERROR,385"GLXSurfaceData_initPbuffer: could not create glx pbuffer");386return JNI_FALSE;387}388389oglsdo->drawableType = OGLSD_PBUFFER;390oglsdo->isOpaque = isOpaque;391oglsdo->width = width;392oglsdo->height = height;393oglsdo->xOffset = 0;394oglsdo->yOffset = 0;395396glxsdo->drawable = pbuffer;397glxsdo->xdrawable = 0;398399OGLSD_SetNativeDimensions(env, oglsdo, width, height);400401return JNI_TRUE;402}403404void405OGLSD_SwapBuffers(JNIEnv *env, jlong window)406{407J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers");408409if (window == 0L) {410J2dRlsTraceLn(J2D_TRACE_ERROR,411"OGLSD_SwapBuffers: window is null");412return;413}414415j2d_glXSwapBuffers(awt_display, (Window)window);416}417418// needed by Mac OS X port, no-op on other platforms419void420OGLSD_Flush(JNIEnv *env)421{422}423424#endif /* !HEADLESS */425426427