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_SunGraphics2D.h"
31
32 #include "jlong.h"
33 #import "MTLContext.h"
34 #include "MTLRenderQueue.h"
35
36
37 extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo);
38
39 static struct TxtVertex verts[PGRAM_VERTEX_COUNT] = {
40 {{-1.0, 1.0}, {0.0, 0.0}},
41 {{1.0, 1.0}, {1.0, 0.0}},
42 {{1.0, -1.0}, {1.0, 1.0}},
43 {{1.0, -1.0}, {1.0, 1.0}},
44 {{-1.0, -1.0}, {0.0, 1.0}},
45 {{-1.0, 1.0}, {0.0, 0.0}}
46 };
47
48 @implementation MTLCommandBufferWrapper {
49 id<MTLCommandBuffer> _commandBuffer;
50 NSMutableArray * _pooledTextures;
51 }
52
53 - (id) initWithCommandBuffer:(id<MTLCommandBuffer>)cmdBuf {
54 self = [super init];
55 if (self) {
56 _commandBuffer = [cmdBuf retain];
57 _pooledTextures = [[NSMutableArray alloc] init];
58 }
59 return self;
60 }
61
62 - (id<MTLCommandBuffer>) getCommandBuffer {
63 return _commandBuffer;
64 }
65
66 - (void) onComplete { // invoked from completion handler in some pooled thread
67 for (int c = 0; c < [_pooledTextures count]; ++c)
68 [[_pooledTextures objectAtIndex:c] releaseTexture];
69 [_pooledTextures removeAllObjects];
70 }
71
72 - (void) registerPooledTexture:(MTLPooledTextureHandle *)handle {
73 [_pooledTextures addObject:handle];
74 }
75
76 - (void) dealloc {
77 [self onComplete];
78
79 [self->_pooledTextures release];
80 [self->_commandBuffer release];
81 [super dealloc];
82 }
83
84 @end
85
86 @implementation MTLContext {
87 MTLCommandBufferWrapper * _commandBufferWrapper;
88
89 MTLComposite * _composite;
90 MTLPaint * _paint;
91 MTLTransform * _transform;
92 MTLClip * _clip;
93
94 EncoderManager * _encoderManager;
95 }
96
97 @synthesize textureFunction,
98 vertexCacheEnabled, aaEnabled, device, library, pipelineStateStorage,
99 commandQueue, vertexBuffer,
100 texturePool;
101
102 - (id)initWithDevice:(id<MTLDevice>)d shadersLib:(NSString*)shadersLib {
103 self = [super init];
104 if (self) {
105 // Initialization code here.
106 device = d;
107
108 texturePool = [[MTLTexturePool alloc] initWithDevice:device];
109 pipelineStateStorage = [[MTLPipelineStatesStorage alloc] initWithDevice:device shaderLibPath:shadersLib];
110
111 vertexBuffer = [device newBufferWithBytes:verts
112 length:sizeof(verts)
113 options:MTLResourceCPUCacheModeDefaultCache];
114
115 NSError *error = nil;
116
117 library = [device newLibraryWithFile:shadersLib error:&error];
118 if (!library) {
119 NSLog(@"Failed to load library. error %@", error);
120 exit(0);
121 }
122
123 _encoderManager = [[EncoderManager alloc] init];
124 [_encoderManager setContext:self];
125 _composite = [[MTLComposite alloc] init];
126 _paint = [[MTLPaint alloc] init];
127 _transform = [[MTLTransform alloc] init];
128 _clip = [[MTLClip alloc] init];
129
130 _commandBufferWrapper = nil;
131
132 // Create command queue
133 commandQueue = [device newCommandQueue];
134 }
135 return self;
136 }
137
138 - (void)dealloc {
139 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.dealloc");
140
141 self.texturePool = nil;
142 self.library = nil;
143 self.vertexBuffer = nil;
144 self.commandQueue = nil;
145 self.pipelineStateStorage = nil;
146 [_encoderManager release];
147 [_composite release];
148 [_paint release];
149 [_transform release];
150 [_clip release];
151 [super dealloc];
152 }
153
154 - (MTLCommandBufferWrapper *) getCommandBufferWrapper {
155 if (_commandBufferWrapper == nil) {
156 J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext : commandBuffer is NULL");
157 // NOTE: Command queues are thread-safe and allow multiple outstanding command buffers to be encoded simultaneously.
158 _commandBufferWrapper = [[MTLCommandBufferWrapper alloc] initWithCommandBuffer:[self.commandQueue commandBuffer]];// released in [layer blitTexture]
159 }
160 return _commandBufferWrapper;
161 }
162
163 - (MTLCommandBufferWrapper *) pullCommandBufferWrapper {
164 MTLCommandBufferWrapper * result = _commandBufferWrapper;
165 _commandBufferWrapper = nil;
166 return result;
167 }
168
169 + (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst {
170 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrc);
171 BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDst);
172 MTLContext *mtlc = NULL;
173
174 if (srcOps == NULL || dstOps == NULL) {
175 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_SetSurfaces: ops are null");
176 return NULL;
177 }
178
179 J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLContext_SetSurfaces: bsrc=%p (tex=%p type=%d), bdst=%p (tex=%p type=%d)", srcOps, srcOps->pTexture, srcOps->drawableType, dstOps, dstOps->pTexture, dstOps->drawableType);
180
181 if (dstOps->drawableType == MTLSD_TEXTURE) {
182 J2dRlsTraceLn(J2D_TRACE_ERROR,
183 "MTLContext_SetSurfaces: texture cannot be used as destination");
184 return NULL;
185 }
186
187 if (dstOps->drawableType == MTLSD_UNDEFINED) {
188 // initialize the surface as an OGLSD_WINDOW
189 if (!MTLSD_InitMTLWindow(env, dstOps)) {
190 J2dRlsTraceLn(J2D_TRACE_ERROR,
191 "MTLContext_SetSurfaces: could not init OGL window");
192 return NULL;
193 }
194 }
195
196 // make the context current
197 MTLSDOps *dstCGLOps = (MTLSDOps *)dstOps->privOps;
198 mtlc = dstCGLOps->configInfo->context;
199
200 if (mtlc == NULL) {
201 J2dRlsTraceLn(J2D_TRACE_ERROR,
202 "MTLContext_SetSurfaces: could not make context current");
203 return NULL;
204 }
205
206 // perform additional one-time initialization, if necessary
207 if (dstOps->needsInit) {
208 if (dstOps->isOpaque) {
209 // in this case we are treating the destination as opaque, but
210 // to do so, first we need to ensure that the alpha channel
211 // is filled with fully opaque values (see 6319663)
212 //MTLContext_InitAlphaChannel();
213 }
214 dstOps->needsInit = JNI_FALSE;
215 }
216
217 return mtlc;
218 }
219
220 - (void)resetClip {
221 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetClip");
222 [_clip reset];
223 }
224
225 - (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 {
226 [_clip setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2];
227 }
228
229 - (void)beginShapeClip:(BMTLSDOps *)dstOps {
230 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.beginShapeClip");
231 [_clip beginShapeClip:dstOps context:self];
232 }
233
234 - (void)endShapeClip:(BMTLSDOps *)dstOps {
235 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.endShapeClip");
236 [_clip endShapeClip:dstOps context:self];
237 }
238
239 - (void)resetComposite {
240 J2dTraceLn(J2D_TRACE_VERBOSE, "MTLContext_ResetComposite");
241 [_composite reset];
242 }
243
244 - (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha
245 flags:(jint)flags {
246 J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags);
247
248 [_composite setRule:rule extraAlpha:extraAlpha];
249 }
250
251 - (NSString*)getCompositeDescription {
252 return [_composite getDescription];
253 }
254
255 - (NSString*)getPaintDescription {
256 return [_paint getDescription];
257 }
258
259 - (void)setXorComposite:(jint)xp {
260 J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setXorComposite: xorPixel=%08x", xp);
261
262 [_composite setXORComposite:xp];
263 }
264
265 - (jboolean)isBlendingDisabled:(jboolean) isSrcOpaque {
266 return [_composite isBlendingDisabled:isSrcOpaque];
267 }
268
269
270 - (void)resetTransform {
271 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_ResetTransform");
272 [_transform resetTransform];
273 }
274
275 - (void)setTransformM00:(jdouble) m00 M10:(jdouble) m10
276 M01:(jdouble) m01 M11:(jdouble) m11
277 M02:(jdouble) m02 M12:(jdouble) m12 {
278 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_SetTransform");
279 [_transform setTransformM00:m00 M10:m10 M01:m01 M11:m11 M02:m02 M12:m12];
280 }
281
282 - (jboolean)initBlitTileTexture {
283 //TODO
284 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_InitBlitTileTexture -- :TODO");
285
286 return JNI_TRUE;
287 }
288
289 - (jint)createBlitTextureFormat:(jint)internalFormat pixelFormat:(jint)pixelFormat
290 width:(jint)width height:(jint)height {
291 J2dTraceLn(J2D_TRACE_INFO, "MTLContext_InitBlitTileTexture -- :TODO");
292
293 //TODO
294 return 0;
295 }
296
297 - (void)resetPaint {
298 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.resetPaint");
299 [_paint reset];
300 }
301
302 - (void)setColorPaint:(int)pixel {
303 J2dTraceLn5(J2D_TRACE_INFO, "MTLContext.setColorPaint: pixel=%08x [r=%d g=%d b=%d a=%d]", pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, (pixel) & 0xFF, (pixel >> 24) & 0xFF);
304 [_paint setColor:pixel];
305 }
306
307 - (void)setGradientPaintUseMask:(jboolean)useMask
308 cyclic:(jboolean)cyclic
309 p0:(jdouble)p0
310 p1:(jdouble)p1
311 p3:(jdouble)p3
312 pixel1:(jint)pixel1
313 pixel2:(jint) pixel2
314 {
315 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setGradientPaintUseMask");
316 [_paint setGradientUseMask:useMask
317 cyclic:cyclic
318 p0:p0
319 p1:p1
320 p3:p3
321 pixel1:pixel1
322 pixel2:pixel2];
323 }
324
325 - (void)setLinearGradientPaint:(jboolean)useMask
326 linear:(jboolean)linear
327 cycleMethod:(jboolean)cycleMethod
328 numStops:(jint)numStops
329 p0:(jfloat)p0
330 p1:(jfloat)p1
331 p3:(jfloat)p3
332 fractions:(void *)fractions
333 pixels:(void *)pixels
334 {
335 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setLinearGradientPaint");
336 [_paint setLinearGradient:useMask
337 linear:linear
338 cycleMethod:cycleMethod
339 numStops:numStops
340 p0:p0
341 p1:p1
342 p3:p3
343 fractions:fractions
344 pixels:pixels];
345 }
346
347 - (void)setRadialGradientPaint:(jboolean)useMask
348 linear:(jboolean)linear
349 cycleMethod:(jboolean)cycleMethod
350 numStops:(jint)numStops
351 m00:(jfloat)m00
352 m01:(jfloat)m01
353 m02:(jfloat)m02
354 m10:(jfloat)m10
355 m11:(jfloat)m11
356 m12:(jfloat)m12
357 focusX:(jfloat)focusX
358 fractions:(void *)fractions
359 pixels:(void *)pixels
360 {
361 J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setRadialGradientPaint");
362 [_paint setRadialGradient:useMask
363 linear:linear
364 cycleMethod:cycleMethod
365 numStops:numStops
366 m00:m00
367 m01:m01
368 m02:m02
369 m10:m10
370 m11:m11
371 m12:m12
372 focusX:focusX
373 fractions:fractions
374 pixels:pixels];
375 }
376
377 - (void)setTexturePaint:(jboolean)useMask
378 pSrcOps:(jlong)pSrcOps
379 filter:(jboolean)filter
380 xp0:(jdouble)xp0
381 xp1:(jdouble)xp1
382 xp3:(jdouble)xp3
383 yp0:(jdouble)yp0
384 yp1:(jdouble)yp1
385 yp3:(jdouble)yp3
386 {
387 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
388
389 if (srcOps == NULL || srcOps->pTexture == NULL) {
390 J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_setTexturePaint: texture paint - texture is null");
391 return;
392 }
393
394 J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setTexturePaint [tex=%p]", srcOps->pTexture);
395
396
397 [_paint setTexture:useMask
398 textureID:srcOps->pTexture
399 filter:filter
400 xp0:xp0
401 xp1:xp1
402 xp3:xp3
403 yp0:yp0
404 yp1:yp1
405 yp3:yp3];
406 }
407
408 - (id<MTLCommandBuffer>)createBlitCommandBuffer {
409 return [self.commandQueue commandBuffer];
410 }
411
412 @end
413
414 /*
415 * Class: sun_java2d_metal_MTLContext
416 * Method: getMTLIdString
417 * Signature: ()Ljava/lang/String;
418 */
419 JNIEXPORT jstring JNICALL Java_sun_java2d_metal_MTLContext_getMTLIdString
420 (JNIEnv *env, jclass mtlcc)
421 {
422 char *vendor, *renderer, *version;
423 char *pAdapterId;
424 jobject ret = NULL;
425 int len;
426
427 return NULL;
428 }
429
430 #endif /* !HEADLESS */