--- /dev/null 2019-06-19 14:03:03.000000000 +0530 +++ new/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m 2019-06-19 14:03:02.000000000 +0530 @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#import + +#import "sun_java2d_metal_MTLSurfaceData.h" + +#import "jni_util.h" +#import "MTLRenderQueue.h" +#import "MTLGraphicsConfig.h" +#import "MTLSurfaceData.h" +#import "ThreadUtilities.h" +#include "jlong.h" + +/** + * The following methods are implemented in the windowing system (i.e. GLX + * and WGL) source files. + */ +extern jlong MTLSD_GetNativeConfigInfo(BMTLSDOps *mtlsdo); +extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo); +extern void MTLSD_DestroyMTLSurface(JNIEnv *env, MTLSDOps *mtlsdo); + +void MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo, jint w, jint h); + +/** + * This table contains the "pixel formats" for all system memory surfaces + * that OpenGL is capable of handling, indexed by the "PF_" constants defined + * in MTLSurfaceData.java. These pixel formats contain information that is + * passed to OpenGL when copying from a system memory ("Sw") surface to + * an OpenGL "Surface" (via glDrawPixels()) or "Texture" (via glTexImage2D()). + */ +MTLPixelFormat MTPixelFormats[] = {}; + +/** + * Given a starting value and a maximum limit, returns the first power-of-two + * greater than the starting value. If the resulting value is greater than + * the maximum limit, zero is returned. + */ +jint +MTLSD_NextPowerOfTwo(jint val, jint max) +{ + jint i; + + if (val > max) { + return 0; + } + + for (i = 1; i < val; i *= 2); + + return i; +} + +/** + * Returns true if both given dimensions are a power of two. + */ +static jboolean +MTLSD_IsPowerOfTwo(jint width, jint height) +{ + return (((width & (width-1)) | (height & (height-1))) == 0); +} + +/** + * Initializes an MTL texture, using the given width and height as + * a guide. + */ +JNIEXPORT jboolean JNICALL +Java_sun_java2d_metal_MTLSurfaceData_initTexture + (JNIEnv *env, jobject mtlsd, + jlong pData, jboolean isOpaque, + jboolean texNonPow2, jboolean texRect, + jint width, jint height) +{ + BMTLSDOps *bmtlsdo = (BMTLSDOps *)jlong_to_ptr(pData); + J2dTraceLn3(J2D_TRACE_INFO, "MTLSurfaceData_initTexture: w=%d h=%d p=%p", width, height, bmtlsdo); + + if (bmtlsdo == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: ops are null"); + return JNI_FALSE; + } + + if (width <= 0 || height <= 0) { + J2dRlsTraceLn2(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions is incorrect, w=%d, h=%d", width, height); + return JNI_FALSE; + } + + MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps; + if (mtlsdo == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps are null"); + return JNI_FALSE; + } + + if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps wasn't initialized (context is null)"); + return JNI_FALSE; + } + + MTLContext* ctx = mtlsdo->configInfo->context; + + MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm width: width height: height mipmapped: NO]; + bmtlsdo->pTexture = [[ctx.device newTextureWithDescriptor: textureDescriptor] retain]; + bmtlsdo->isOpaque = isOpaque; + bmtlsdo->xOffset = 0; + bmtlsdo->yOffset = 0; + bmtlsdo->width = width; + bmtlsdo->height = height; + bmtlsdo->textureWidth = width; + bmtlsdo->textureHeight = height; + bmtlsdo->textureTarget = -1; + bmtlsdo->drawableType = MTLSD_TEXTURE; + + MTLSD_SetNativeDimensions(env, bmtlsdo, width, width); + J2dTraceLn4(J2D_TRACE_VERBOSE, "\tcreated MTLTexture [texture]: w=%d h=%d bp=%p [tex=%p]", width, height, bmtlsdo, bmtlsdo->pTexture); + + return JNI_TRUE; +} + +/** + * Initializes a framebuffer object, using the given width and height as + * a guide. See MTLSD_InitTextureObject() and MTLSD_initRTexture() + * for more information. + */ +JNIEXPORT jboolean JNICALL +Java_sun_java2d_metal_MTLSurfaceData_initRTexture + (JNIEnv *env, jobject mtlsd, + jlong pData, jboolean isOpaque, + jboolean texNonPow2, jboolean texRect, + jint width, jint height) +{ + + BMTLSDOps *bmtlsdo = (BMTLSDOps *)jlong_to_ptr(pData); + + if (bmtlsdo == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "MTLSurfaceData_initRTexture: BMTLSDOps are null"); + return JNI_FALSE; + } + + MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps; + + if (mtlsdo == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "MTLSurfaceData_initRTexture: MTLSDOps are null"); + return JNI_FALSE; + } + + if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) { + J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initRTexture: MTLSDOps wasn't initialized (context is null)"); + return JNI_FALSE; + } + + const MTLContext* ctx = mtlsdo->configInfo->context; + MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm width: width height: height mipmapped: NO]; + bmtlsdo->pTexture = [[ctx.device newTextureWithDescriptor: textureDescriptor] retain];; + + bmtlsdo->isOpaque = isOpaque; + bmtlsdo->xOffset = 0; + bmtlsdo->yOffset = 0; + bmtlsdo->width = width; + bmtlsdo->height = height; + bmtlsdo->textureWidth = width; + bmtlsdo->textureHeight = height; + bmtlsdo->textureTarget = -1; + bmtlsdo->drawableType = MTLSD_RT_TEXTURE; + + MTLSD_SetNativeDimensions(env, bmtlsdo, width, width); + J2dTraceLn4(J2D_TRACE_VERBOSE, "\tcreated MTLTexture [FBObject]: w=%d h=%d bp=%p [tex=%p]", width, height, bmtlsdo, bmtlsdo->pTexture); + + 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_metal_MTLSurfaceData_initFlipBackbuffer + (JNIEnv *env, jobject mtlsd, + jlong pData) +{ + //TODO + J2dTraceNotImplPrimitive("MTLSurfaceData_initFlipBackbuffer"); + MTLSDOps *mtlsdo = (MTLSDOps *)jlong_to_ptr(pData); + + J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_initFlipBackbuffer"); + return JNI_TRUE; +} + +JNIEXPORT jint JNICALL +Java_sun_java2d_metal_MTLSurfaceData_getTextureTarget + (JNIEnv *env, jobject mtlsd, + jlong pData) +{ + //TODO + J2dTraceNotImplPrimitive("MTLSurfaceData_getTextureTarget"); + MTLSDOps *mtlsdo = (MTLSDOps *)jlong_to_ptr(pData); + + J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_getTextureTarget"); + + return 0; +} + +JNIEXPORT jint JNICALL +Java_sun_java2d_metal_MTLSurfaceData_getTextureID + (JNIEnv *env, jobject mtlsd, + jlong pData) +{ + //TODO + J2dTraceNotImplPrimitive("MTLSurfaceData_getTextureID"); + return 0; +} + +/** + * Initializes nativeWidth/Height fields of the surfaceData object with + * passed arguments. + */ +void +MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo, + jint width, jint height) +{ + jobject sdObject; + + sdObject = (*env)->NewLocalRef(env, mtlsdo->sdOps.sdObject); + if (sdObject == NULL) { + return; + } + + JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); + if (!((*env)->ExceptionOccurred(env))) { + JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); + } + + (*env)->DeleteLocalRef(env, sdObject); +} + +/** + * Deletes native OpenGL resources associated with this surface. + */ +void +MTLSD_Delete(JNIEnv *env, BMTLSDOps *mtlsdo) +{ + //TODO + J2dTraceNotImplPrimitive("MTLSD_Delete"); + J2dTraceLn1(J2D_TRACE_INFO, "MTLSD_Delete: type=%d", + mtlsdo->drawableType); +} + +/** + * This is the implementation of the general DisposeFunc defined in + * SurfaceData.h and used by the Disposer mechanism. It first flushes all + * native OpenGL resources and then frees any memory allocated within the + * native MTLSDOps structure. + */ +void +MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops) +{ + MTLSDOps *mtlsdo = (MTLSDOps *)ops; + jlong pConfigInfo = MTLSD_GetNativeConfigInfo(mtlsdo); + + JNU_CallStaticMethodByName(env, NULL, "sun/java2d/metal/MTLSurfaceData", + "dispose", "(JJ)V", + ptr_to_jlong(ops), pConfigInfo); +} + +/** + * This is the implementation of the general surface LockFunc defined in + * SurfaceData.h. + */ +jint +MTLSD_Lock(JNIEnv *env, + SurfaceDataOps *ops, + SurfaceDataRasInfo *pRasInfo, + jint lockflags) +{ + JNU_ThrowInternalError(env, "MTLSD_Lock not implemented!"); + return SD_FAILURE; +} + +/** + * This is the implementation of the general GetRasInfoFunc defined in + * SurfaceData.h. + */ +void +MTLSD_GetRasInfo(JNIEnv *env, + SurfaceDataOps *ops, + SurfaceDataRasInfo *pRasInfo) +{ + JNU_ThrowInternalError(env, "MTLSD_GetRasInfo not implemented!"); +} + +/** + * This is the implementation of the general surface UnlockFunc defined in + * SurfaceData.h. + */ +void +MTLSD_Unlock(JNIEnv *env, + SurfaceDataOps *ops, + SurfaceDataRasInfo *pRasInfo) +{ + JNU_ThrowInternalError(env, "MTLSD_Unlock not implemented!"); +} + +/** + * This function disposes of any native windowing system resources associated + * with this surface. + */ +void +MTLSD_DestroyMTLSurface(JNIEnv *env, MTLSDOps *mtlsdo) +{ + J2dTraceLn(J2D_TRACE_INFO, "OGLSD_DestroyOGLSurface"); +} + +/** + * Returns a pointer (as a jlong) to the native CGLGraphicsConfigInfo + * 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 +MTLSD_GetNativeConfigInfo(BMTLSDOps *mtlsdo) +{ + J2dTraceLn(J2D_TRACE_INFO, "OGLSD_GetNativeConfigInfo"); + + return 0; +} + +/** + * 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 +MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *oglsdo) +{ + J2dTraceLn(J2D_TRACE_INFO, "MTLSD_InitMTLWindow"); + + return JNI_TRUE; +} + +void +MTLSD_SwapBuffers(JNIEnv *env, jlong pPeerData) +{ + J2dTraceLn(J2D_TRACE_INFO, "OGLSD_SwapBuffers"); +} + +#pragma mark - +#pragma mark "--- CGLSurfaceData methods ---" + +extern LockFunc MTLSD_Lock; +extern GetRasInfoFunc MTLSD_GetRasInfo; +extern UnlockFunc MTLSD_Unlock; + + +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLSurfaceData_initOps + (JNIEnv *env, jobject cglsd, + jlong pConfigInfo, jlong pPeerData, jlong layerPtr, + jint xoff, jint yoff, jboolean isOpaque) +{ + BMTLSDOps *bmtlsdo = (BMTLSDOps *)SurfaceData_InitOps(env, cglsd, sizeof(BMTLSDOps)); + MTLSDOps *mtlsdo = (MTLSDOps *)malloc(sizeof(MTLSDOps)); + + J2dTraceLn1(J2D_TRACE_INFO, "MTLSurfaceData_initOps p=%p", bmtlsdo); + J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); + J2dTraceLn1(J2D_TRACE_INFO, " layerPtr=%p", jlong_to_ptr(layerPtr)); + J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); + + if (mtlsdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "creating native cgl ops"); + return; + } + + bmtlsdo->privOps = mtlsdo; + + bmtlsdo->sdOps.Lock = MTLSD_Lock; + bmtlsdo->sdOps.GetRasInfo = MTLSD_GetRasInfo; + bmtlsdo->sdOps.Unlock = MTLSD_Unlock; + bmtlsdo->sdOps.Dispose = MTLSD_Dispose; + + bmtlsdo->drawableType = MTLSD_UNDEFINED; + bmtlsdo->needsInit = JNI_TRUE; + bmtlsdo->xOffset = xoff; + bmtlsdo->yOffset = yoff; + bmtlsdo->isOpaque = isOpaque; + + mtlsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData); + mtlsdo->layer = (MTLLayer *)jlong_to_ptr(layerPtr); + mtlsdo->configInfo = (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo); + + if (mtlsdo->configInfo == NULL) { + free(mtlsdo); + JNU_ThrowNullPointerException(env, "Config info is null in initOps"); + } +} + +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLSurfaceData_clearWindow +(JNIEnv *env, jobject cglsd) +{ + J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_clearWindow"); + + BMTLSDOps *mtlsdo = (MTLSDOps*) SurfaceData_GetOps(env, cglsd); + MTLSDOps *cglsdo = (MTLSDOps*) mtlsdo->privOps; + + cglsdo->peerData = NULL; + cglsdo->layer = NULL; +} + +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLSurfaceData_validate + (JNIEnv *env, jobject jsurfacedata, + jint xoff, jint yoff, jint width, jint height, jboolean isOpaque) +{ + J2dTraceLn2(J2D_TRACE_INFO, "MTLLSurfaceData_validate: w=%d h=%d", width, height); + + BMTLSDOps *mtlsdo = (BMTLSDOps*)SurfaceData_GetOps(env, jsurfacedata); + mtlsdo->needsInit = JNI_TRUE; + mtlsdo->xOffset = xoff; + mtlsdo->yOffset = yoff; + + mtlsdo->width = width; + mtlsdo->height = height; + mtlsdo->isOpaque = isOpaque; + + if (mtlsdo->drawableType == MTLSD_WINDOW) { + // J2dTraceLn4(J2D_TRACE_INFO, "MTLContext_SetSurfaces: w=%d h=%d src=%p dst=%p", width, height, mtlsdo, mtlsdo); + [MTLContext setSurfacesEnv:env src:ptr_to_jlong(mtlsdo) dst:ptr_to_jlong(mtlsdo)]; + + // we have to explicitly tell the NSOpenGLContext that its target + // drawable has changed size + MTLSDOps *cglsdo = (MTLSDOps *)mtlsdo->privOps; + MTLContext *mtlc = cglsdo->configInfo->context; + + } +}