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