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 */