1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #ifndef HEADLESS 27 28 #include <stdlib.h> 29 30 #include "sun_java2d_metal_MTLSurfaceData.h" 31 32 #include "jlong.h" 33 #include "jni_util.h" 34 #include "MTLSurfaceData.h" 35 #import "ThreadUtilities.h" 36 37 /** 38 * The following methods are implemented in the windowing system (i.e. GLX 39 * and WGL) source files. 40 */ 41 extern jlong MTLSD_GetNativeConfigInfo(MTLSDOps *mtlsdo); 42 extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo); 43 extern void MTLSD_DestroyMTLSurface(JNIEnv *env, MTLSDOps *mtlsdo); 44 45 void MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo, jint w, jint h); 46 47 /** 48 * This table contains the "pixel formats" for all system memory surfaces 49 * that OpenGL is capable of handling, indexed by the "PF_" constants defined 50 * in MTLSurfaceData.java. These pixel formats contain information that is 51 * passed to OpenGL when copying from a system memory ("Sw") surface to 52 * an OpenGL "Surface" (via glDrawPixels()) or "Texture" (via glTexImage2D()). 53 */ 54 MTLPixelFormat MTPixelFormats[] = {}; 55 56 /** 57 * Given a starting value and a maximum limit, returns the first power-of-two 58 * greater than the starting value. If the resulting value is greater than 59 * the maximum limit, zero is returned. 60 */ 61 jint 62 MTLSD_NextPowerOfTwo(jint val, jint max) 63 { 64 jint i; 65 66 if (val > max) { 67 return 0; 68 } 69 70 for (i = 1; i < val; i *= 2); 71 72 return i; 73 } 74 75 /** 76 * Returns true if both given dimensions are a power of two. 77 */ 78 static jboolean 79 MTLSD_IsPowerOfTwo(jint width, jint height) 80 { 81 return (((width & (width-1)) | (height & (height-1))) == 0); 82 } 83 84 /** 85 * Initializes an OpenGL texture object. 86 * 87 * If the isOpaque parameter is JNI_FALSE, then the texture will have a 88 * full alpha channel; otherwise, the texture will be opaque (this can 89 * help save VRAM when translucency is not needed). 90 * 91 * If the GL_ARB_texture_non_power_of_two extension is present (texNonPow2 92 * is JNI_TRUE), the actual texture is allowed to have non-power-of-two 93 * dimensions, and therefore width==textureWidth and height==textureHeight. 94 * 95 * Failing that, if the GL_ARB_texture_rectangle extension is present 96 * (texRect is JNI_TRUE), the actual texture is allowed to have 97 * non-power-of-two dimensions, except that instead of using the usual 98 * GL_TEXTURE_2D target, we need to use the GL_TEXTURE_RECTANGLE_ARB target. 99 * Note that the GL_REPEAT wrapping mode is not allowed with this target, 100 * so if that mode is needed (e.g. as is the case in the TexturePaint code) 101 * one should pass JNI_FALSE to avoid using this extension. Also note that 102 * when the texture target is GL_TEXTURE_RECTANGLE_ARB, texture coordinates 103 * must be specified in the range [0,width] and [0,height] rather than 104 * [0,1] as is the case with the usual GL_TEXTURE_2D target (so take care)! 105 * 106 * Otherwise, the actual texture must have power-of-two dimensions, and 107 * therefore the textureWidth and textureHeight will be the next 108 * power-of-two greater than (or equal to) the requested width and height. 109 */ 110 static jboolean 111 MTLSD_InitTextureObject(MTLSDOps *mtlsdo, 112 jboolean isOpaque, 113 jboolean texNonPow2, jboolean texRect, 114 jint width, jint height) 115 { 116 //TODO 117 J2dTraceNotImplPrimitive("MTLSD_InitTextureObject"); 118 return JNI_TRUE; 119 } 120 121 /** 122 * Initializes an MTL texture, using the given width and height as 123 * a guide. See MTLSD_InitTextureObject() for more information. 124 */ 125 JNIEXPORT jboolean JNICALL 126 Java_sun_java2d_metal_MTLSurfaceDataBase_initTexture 127 (JNIEnv *env, jobject mtlsd, 128 jlong pData, jboolean isOpaque, 129 jboolean texNonPow2, jboolean texRect, 130 jint width, jint height) 131 { 132 BMTLSDOps *mtlsdo = (BMTLSDOps *)jlong_to_ptr(pData); 133 J2dTraceLn2(J2D_TRACE_INFO, "MTLSurfaceData_initTexture: w=%d h=%d", 134 width, height); 135 136 if (mtlsdo == NULL) { 137 J2dRlsTraceLn(J2D_TRACE_ERROR, 138 "MTLSurfaceData_initTexture: ops are null"); 139 return JNI_FALSE; 140 } 141 142 /* 143 * We only use the GL_ARB_texture_rectangle extension if it is available 144 * and the requested bounds are not pow2 (it is probably faster to use 145 * GL_TEXTURE_2D for pow2 textures, and besides, our TexturePaint 146 * code relies on GL_REPEAT, which is not allowed for 147 * GL_TEXTURE_RECTANGLE_ARB targets). 148 */ 149 texRect = texRect && !MTLSD_IsPowerOfTwo(width, height); 150 151 if (!MTLSD_InitTextureObject(mtlsdo, isOpaque, texNonPow2, texRect, 152 width, height)) 153 { 154 J2dRlsTraceLn(J2D_TRACE_ERROR, 155 "MTLSurfaceData_initTexture: could not init texture object"); 156 return JNI_FALSE; 157 } 158 159 MTLSD_SetNativeDimensions(env, mtlsdo, 160 mtlsdo->textureWidth, mtlsdo->textureHeight); 161 162 mtlsdo->drawableType = MTLSD_TEXTURE; 163 // other fields (e.g. width, height) are set in MTLSD_InitTextureObject() 164 165 return JNI_TRUE; 166 } 167 168 /** 169 * Initializes a framebuffer object, using the given width and height as 170 * a guide. See MTLSD_InitTextureObject() and MTLSD_InitFBObject() 171 * for more information. 172 */ 173 JNIEXPORT jboolean JNICALL 174 Java_sun_java2d_metal_MTLSurfaceDataBase_initFBObject 175 (JNIEnv *env, jobject mtlsd, 176 jlong pData, jboolean isOpaque, 177 jboolean texNonPow2, jboolean texRect, 178 jint width, jint height) 179 { 180 181 BMTLSDOps *bmtlsdo = (BMTLSDOps *)jlong_to_ptr(pData); 182 183 if (bmtlsdo == NULL) { 184 J2dRlsTraceLn(J2D_TRACE_ERROR, 185 "MTLSurfaceData_initFBObject: BMTLSDOps are null"); 186 return JNI_FALSE; 187 } 188 189 MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps; 190 191 if (mtlsdo == NULL) { 192 J2dRlsTraceLn(J2D_TRACE_ERROR, 193 "MTLSurfaceData_initFBObject: MTLSDOps are null"); 194 return JNI_FALSE; 195 } 196 197 J2dTraceLn2(J2D_TRACE_INFO, 198 "MTLSurfaceData_initFBObject: w=%d h=%d", 199 width, height); 200 201 202 203 if (mtlsdo->configInfo) { 204 if (mtlsdo->configInfo->context != NULL) { 205 MTLContext* ctx = mtlsdo->configInfo->context; 206 if (ctx == NULL) { 207 NSLog(@"ctx is NULL"); 208 } else { 209 [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ 210 MTLTextureDescriptor *textureDescriptor = 211 [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatRGBA8Unorm 212 width: width 213 height: height 214 mipmapped: NO]; 215 ctx->mtlFrameBuffer = [[ctx->mtlDevice newTextureWithDescriptor: textureDescriptor] retain]; 216 }]; 217 } 218 } 219 } 220 221 222 bmtlsdo->drawableType = MTLSD_FBOBJECT; 223 224 return JNI_TRUE; 225 } 226 227 /** 228 * Initializes a surface in the backbuffer of a given double-buffered 229 * onscreen window for use in a BufferStrategy.Flip situation. The bounds of 230 * the backbuffer surface should always be kept in sync with the bounds of 231 * the underlying native window. 232 */ 233 JNIEXPORT jboolean JNICALL 234 Java_sun_java2d_metal_MTLSurfaceDataBase_initFlipBackbuffer 235 (JNIEnv *env, jobject mtlsd, 236 jlong pData) 237 { 238 //TODO 239 J2dTraceNotImplPrimitive("MTLSurfaceDataBase_initFlipBackbuffer"); 240 MTLSDOps *mtlsdo = (MTLSDOps *)jlong_to_ptr(pData); 241 242 J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_initFlipBackbuffer"); 243 return JNI_TRUE; 244 } 245 246 JNIEXPORT jint JNICALL 247 Java_sun_java2d_metal_MTLSurfaceDataBase_getTextureTarget 248 (JNIEnv *env, jobject mtlsd, 249 jlong pData) 250 { 251 //TODO 252 J2dTraceNotImplPrimitive("MTLSurfaceDataBase_getTextureTarget"); 253 MTLSDOps *mtlsdo = (MTLSDOps *)jlong_to_ptr(pData); 254 255 J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_getTextureTarget"); 256 257 return 0; 258 } 259 260 JNIEXPORT jint JNICALL 261 Java_sun_java2d_metal_MTLSurfaceDataBase_getTextureID 262 (JNIEnv *env, jobject mtlsd, 263 jlong pData) 264 { 265 //TODO 266 J2dTraceNotImplPrimitive("MTLSurfaceDataBase_getTextureID"); 267 return 0; 268 } 269 270 /** 271 * Initializes nativeWidth/Height fields of the surfaceData object with 272 * passed arguments. 273 */ 274 void 275 MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo, 276 jint width, jint height) 277 { 278 jobject sdObject; 279 280 sdObject = (*env)->NewLocalRef(env, mtlsdo->sdOps.sdObject); 281 if (sdObject == NULL) { 282 return; 283 } 284 285 JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width); 286 if (!((*env)->ExceptionOccurred(env))) { 287 JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height); 288 } 289 290 (*env)->DeleteLocalRef(env, sdObject); 291 } 292 293 /** 294 * Deletes native OpenGL resources associated with this surface. 295 */ 296 void 297 MTLSD_Delete(JNIEnv *env, BMTLSDOps *mtlsdo) 298 { 299 //TODO 300 J2dTraceNotImplPrimitive("MTLSD_Delete"); 301 J2dTraceLn1(J2D_TRACE_INFO, "MTLSD_Delete: type=%d", 302 mtlsdo->drawableType); 303 } 304 305 /** 306 * This is the implementation of the general DisposeFunc defined in 307 * SurfaceData.h and used by the Disposer mechanism. It first flushes all 308 * native OpenGL resources and then frees any memory allocated within the 309 * native MTLSDOps structure. 310 */ 311 void 312 MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops) 313 { 314 MTLSDOps *mtlsdo = (MTLSDOps *)ops; 315 jlong pConfigInfo = MTLSD_GetNativeConfigInfo(mtlsdo); 316 317 JNU_CallStaticMethodByName(env, NULL, "sun/java2d/metal/MTLSurfaceData", 318 "dispose", "(JJ)V", 319 ptr_to_jlong(ops), pConfigInfo); 320 } 321 322 /** 323 * This is the implementation of the general surface LockFunc defined in 324 * SurfaceData.h. 325 */ 326 jint 327 MTLSD_Lock(JNIEnv *env, 328 SurfaceDataOps *ops, 329 SurfaceDataRasInfo *pRasInfo, 330 jint lockflags) 331 { 332 JNU_ThrowInternalError(env, "MTLSD_Lock not implemented!"); 333 return SD_FAILURE; 334 } 335 336 /** 337 * This is the implementation of the general GetRasInfoFunc defined in 338 * SurfaceData.h. 339 */ 340 void 341 MTLSD_GetRasInfo(JNIEnv *env, 342 SurfaceDataOps *ops, 343 SurfaceDataRasInfo *pRasInfo) 344 { 345 JNU_ThrowInternalError(env, "MTLSD_GetRasInfo not implemented!"); 346 } 347 348 /** 349 * This is the implementation of the general surface UnlockFunc defined in 350 * SurfaceData.h. 351 */ 352 void 353 MTLSD_Unlock(JNIEnv *env, 354 SurfaceDataOps *ops, 355 SurfaceDataRasInfo *pRasInfo) 356 { 357 JNU_ThrowInternalError(env, "MTLSD_Unlock not implemented!"); 358 } 359 360 #endif /* !HEADLESS */