Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m
41159 views
/*1* Copyright (c) 2019, 2021, 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#import <stdlib.h>2627#import "sun_java2d_metal_MTLSurfaceData.h"2829#import "jni_util.h"30#import "MTLGraphicsConfig.h"31#import "MTLSurfaceData.h"32#include "jlong.h"3334jboolean MTLSD_InitMTLWindow(JNIEnv *env, BMTLSDOps *bmtlsdo);35void MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *bmtlsdo, jint w, jint h);3637static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque, jboolean rtt, jint width, jint height) {38@autoreleasepool {39if (bmtlsdo == NULL) {40J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: ops are null");41return JNI_FALSE;42}43if (width <= 0 || height <= 0) {44J2dRlsTraceLn2(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions is incorrect, w=%d, h=%d", width, height);45return JNI_FALSE;46}4748MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;4950if (mtlsdo == NULL) {51J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps are null");52return JNI_FALSE;53}54if (mtlsdo->configInfo == NULL || mtlsdo->configInfo->context == NULL) {55J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: MTLSDOps wasn't initialized (context is null)");56return JNI_FALSE;57}5859MTLContext* ctx = mtlsdo->configInfo->context;6061width = (width <= MTL_GPU_FAMILY_MAC_TXT_SIZE) ? width : 0;62height = (height <= MTL_GPU_FAMILY_MAC_TXT_SIZE) ? height : 0;6364J2dTraceLn3(J2D_TRACE_VERBOSE, " desired texture dimensions: w=%d h=%d max=%d",65width, height, MTL_GPU_FAMILY_MAC_TXT_SIZE);6667// if either dimension is 0, we cannot allocate a texture with the68// requested dimensions69if ((width == 0 || height == 0)) {70J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions too large");71return JNI_FALSE;72}7374MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatBGRA8Unorm width: width height: height mipmapped: NO];75textureDescriptor.usage = MTLTextureUsageUnknown;76textureDescriptor.storageMode = MTLStorageModePrivate;77bmtlsdo->pTexture = [ctx.device newTextureWithDescriptor: textureDescriptor];7879MTLTextureDescriptor *stencilDataDescriptor =80[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:width height:height mipmapped:NO];81stencilDataDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;82stencilDataDescriptor.storageMode = MTLStorageModePrivate;83bmtlsdo->pStencilData = [ctx.device newTextureWithDescriptor:stencilDataDescriptor];8485MTLTextureDescriptor *stencilTextureDescriptor =86[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatStencil8 width:width height:height mipmapped:NO];87stencilTextureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;88stencilTextureDescriptor.storageMode = MTLStorageModePrivate;89bmtlsdo->pStencilTexture = [ctx.device newTextureWithDescriptor:stencilTextureDescriptor];90bmtlsdo->isOpaque = isOpaque;91bmtlsdo->width = width;92bmtlsdo->height = height;93bmtlsdo->drawableType = rtt ? MTLSD_RT_TEXTURE : MTLSD_TEXTURE;9495J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLSurfaceData_initTexture: w=%d h=%d bp=%p [tex=%p] opaque=%d rtt=%d", width, height, bmtlsdo, bmtlsdo->pTexture, isOpaque, rtt);96return JNI_TRUE;97}98}99100/**101* Initializes an MTL texture, using the given width and height as102* a guide.103*/104JNIEXPORT jboolean JNICALL105Java_sun_java2d_metal_MTLSurfaceData_initTexture(106JNIEnv *env, jobject mtlsd,107jlong pData, jboolean isOpaque,108jint width, jint height109) {110if (!MTLSurfaceData_initTexture((BMTLSDOps *)pData, isOpaque, JNI_FALSE, width, height))111return JNI_FALSE;112MTLSD_SetNativeDimensions(env, (BMTLSDOps *)pData, width, height);113return JNI_TRUE;114}115116/**117* Initializes a framebuffer object, using the given width and height as118* a guide. See MTLSD_InitTextureObject() and MTLSD_initRTexture()119* for more information.120*/121JNIEXPORT jboolean JNICALL122Java_sun_java2d_metal_MTLSurfaceData_initRTexture123(JNIEnv *env, jobject mtlsd,124jlong pData, jboolean isOpaque,125jint width, jint height)126{127if (!MTLSurfaceData_initTexture((BMTLSDOps *)pData, isOpaque, JNI_TRUE, width, height))128return JNI_FALSE;129MTLSD_SetNativeDimensions(env, (BMTLSDOps *)pData, width, height);130return JNI_TRUE;131}132133JNIEXPORT jlong JNICALL134Java_sun_java2d_metal_MTLSurfaceData_getMTLTexturePointer(JNIEnv *env, jobject mtlsd, jlong pData) {135if (pData == 0)136return 0;137return ptr_to_jlong(((BMTLSDOps *)pData)->pTexture);138}139140/**141* Initializes nativeWidth/Height fields of the surfaceData object with142* passed arguments.143*/144void145MTLSD_SetNativeDimensions(JNIEnv *env, BMTLSDOps *mtlsdo,146jint width, jint height)147{148jobject sdObject;149150sdObject = (*env)->NewLocalRef(env, mtlsdo->sdOps.sdObject);151if (sdObject == NULL) {152return;153}154155JNU_SetFieldByName(env, NULL, sdObject, "nativeWidth", "I", width);156if (!((*env)->ExceptionOccurred(env))) {157JNU_SetFieldByName(env, NULL, sdObject, "nativeHeight", "I", height);158}159160(*env)->DeleteLocalRef(env, sdObject);161}162163/**164* Deletes native Metal resources associated with this surface.165*/166void167MTLSD_Delete(JNIEnv *env, BMTLSDOps *bmtlsdo)168{169J2dTraceLn3(J2D_TRACE_VERBOSE, "MTLSD_Delete: type=%d %p [tex=%p]", bmtlsdo->drawableType, bmtlsdo, bmtlsdo->pTexture);170if (bmtlsdo->drawableType == MTLSD_WINDOW) {171bmtlsdo->drawableType = MTLSD_UNDEFINED;172} else if (173bmtlsdo->drawableType == MTLSD_RT_TEXTURE174|| bmtlsdo->drawableType == MTLSD_TEXTURE175|| bmtlsdo->drawableType == MTLSD_FLIP_BACKBUFFER176) {177[(NSObject *)bmtlsdo->pTexture release];178[(NSObject *)bmtlsdo->pStencilTexture release];179[(NSObject *)bmtlsdo->pStencilData release];180bmtlsdo->pTexture = NULL;181bmtlsdo->drawableType = MTLSD_UNDEFINED;182}183}184185/**186* This is the implementation of the general DisposeFunc defined in187* SurfaceData.h and used by the Disposer mechanism. It first flushes all188* native Metal resources and then frees any memory allocated within the189* native MTLSDOps structure.190*/191void192MTLSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)193{194BMTLSDOps *bmtlsdo = (BMTLSDOps *)ops;195jobject graphicsConfig = bmtlsdo->graphicsConfig;196197JNU_CallStaticMethodByName(env, NULL, "sun/java2d/metal/MTLSurfaceData",198"dispose",199"(JLsun/java2d/metal/MTLGraphicsConfig;)V",200ptr_to_jlong(ops), graphicsConfig);201(*env)->DeleteGlobalRef(env, graphicsConfig);202bmtlsdo->graphicsConfig = NULL;203}204205/**206* This is the implementation of the general surface LockFunc defined in207* SurfaceData.h.208*/209jint210MTLSD_Lock(JNIEnv *env,211SurfaceDataOps *ops,212SurfaceDataRasInfo *pRasInfo,213jint lockflags)214{215JNU_ThrowInternalError(env, "MTLSD_Lock not implemented!");216return SD_FAILURE;217}218219/**220* This is the implementation of the general GetRasInfoFunc defined in221* SurfaceData.h.222*/223void224MTLSD_GetRasInfo(JNIEnv *env,225SurfaceDataOps *ops,226SurfaceDataRasInfo *pRasInfo)227{228JNU_ThrowInternalError(env, "MTLSD_GetRasInfo not implemented!");229}230231/**232* This is the implementation of the general surface UnlockFunc defined in233* SurfaceData.h.234*/235void236MTLSD_Unlock(JNIEnv *env,237SurfaceDataOps *ops,238SurfaceDataRasInfo *pRasInfo)239{240JNU_ThrowInternalError(env, "MTLSD_Unlock not implemented!");241}242243244/**245* This function initializes a native window surface and caches the window246* bounds in the given BMTLSDOps. Returns JNI_TRUE if the operation was247* successful; JNI_FALSE otherwise.248*/249jboolean250MTLSD_InitMTLWindow(JNIEnv *env, BMTLSDOps *bmtlsdo)251{252if (bmtlsdo == NULL) {253J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSD_InitMTLWindow: ops are null");254return JNI_FALSE;255}256257MTLSDOps *mtlsdo = (MTLSDOps *)bmtlsdo->privOps;258if (mtlsdo == NULL) {259J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSD_InitMTLWindow: priv ops are null");260return JNI_FALSE;261}262263AWTView *v = mtlsdo->peerData;264if (v == NULL) {265J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLSD_InitMTLWindow: view is invalid");266return JNI_FALSE;267}268269JNI_COCOA_ENTER(env);270NSRect surfaceBounds = [v bounds];271bmtlsdo->drawableType = MTLSD_WINDOW;272bmtlsdo->isOpaque = JNI_TRUE;273bmtlsdo->width = surfaceBounds.size.width;274bmtlsdo->height = surfaceBounds.size.height;275JNI_COCOA_EXIT(env);276277J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", bmtlsdo->width, bmtlsdo->height);278return JNI_TRUE;279}280281#pragma mark -282#pragma mark "--- MTLSurfaceData methods ---"283284extern LockFunc MTLSD_Lock;285extern GetRasInfoFunc MTLSD_GetRasInfo;286extern UnlockFunc MTLSD_Unlock;287288289JNIEXPORT void JNICALL290Java_sun_java2d_metal_MTLSurfaceData_initOps291(JNIEnv *env, jobject mtlsd, jobject gc,292jlong pConfigInfo, jlong pPeerData, jlong layerPtr,293jint xoff, jint yoff, jboolean isOpaque)294{295BMTLSDOps *bmtlsdo = (BMTLSDOps *)SurfaceData_InitOps(env, mtlsd, sizeof(BMTLSDOps));296MTLSDOps *mtlsdo = (MTLSDOps *)malloc(sizeof(MTLSDOps));297298J2dTraceLn1(J2D_TRACE_INFO, "MTLSurfaceData_initOps p=%p", bmtlsdo);299J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData));300J2dTraceLn1(J2D_TRACE_INFO, " layerPtr=%p", jlong_to_ptr(layerPtr));301J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff);302303gc = (*env)->NewGlobalRef(env, gc);304if (gc == NULL) {305JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");306return;307}308309if (mtlsdo == NULL) {310(*env)->DeleteGlobalRef(env, gc);311JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");312return;313}314315// later the graphicsConfig will be used for deallocation of mtlsdo316bmtlsdo->privOps = mtlsdo;317bmtlsdo->graphicsConfig = gc;318319bmtlsdo->sdOps.Lock = MTLSD_Lock;320bmtlsdo->sdOps.GetRasInfo = MTLSD_GetRasInfo;321bmtlsdo->sdOps.Unlock = MTLSD_Unlock;322bmtlsdo->sdOps.Dispose = MTLSD_Dispose;323bmtlsdo->drawableType = MTLSD_UNDEFINED;324325bmtlsdo->isOpaque = isOpaque;326327mtlsdo->peerData = (AWTView *)jlong_to_ptr(pPeerData);328mtlsdo->layer = (MTLLayer *)jlong_to_ptr(layerPtr);329mtlsdo->configInfo = (MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);330331if (mtlsdo->configInfo == NULL) {332free(mtlsdo);333JNU_ThrowNullPointerException(env, "Config info is null in initOps");334}335}336337JNIEXPORT void JNICALL338Java_sun_java2d_metal_MTLSurfaceData_clearWindow339(JNIEnv *env, jobject mtlsd)340{341J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_clearWindow");342343BMTLSDOps *bmtlsdo = (MTLSDOps*) SurfaceData_GetOps(env, mtlsd);344MTLSDOps *mtlsdo = (MTLSDOps*) bmtlsdo->privOps;345346mtlsdo->peerData = NULL;347mtlsdo->layer = NULL;348}349350NSString * getSurfaceDescription(const BMTLSDOps * bmtlsdOps) {351if (bmtlsdOps == NULL)352return @"NULL";353return [NSString stringWithFormat:@"%p [tex=%p, %dx%d, O=%d]", bmtlsdOps, bmtlsdOps->pTexture, bmtlsdOps->width, bmtlsdOps->height, bmtlsdOps->isOpaque];354}355356357