125 txQuadVerts[3].position[0] = dx2;
126 txQuadVerts[3].position[1] = dy2;
127 txQuadVerts[3].txtpos[0] = nsx2;
128 txQuadVerts[3].txtpos[1] = nsy2;
129
130 txQuadVerts[4].position[0] = dx1;
131 txQuadVerts[4].position[1] = dy2;
132 txQuadVerts[4].txtpos[0] = nsx1;
133 txQuadVerts[4].txtpos[1] = nsy2;
134
135 txQuadVerts[5].position[0] = dx1;
136 txQuadVerts[5].position[1] = dy1;
137 txQuadVerts[5].txtpos[0] = nsx1;
138 txQuadVerts[5].txtpos[1] = nsy1;
139 }
140
141 //#define TRACE_drawTex2Tex
142
143 void drawTex2Tex(MTLContext *mtlc,
144 id<MTLTexture> src, id<MTLTexture> dst,
145 jboolean isSrcOpaque, jboolean isDstOpaque,
146 jint sx1, jint sy1, jint sx2, jint sy2,
147 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
148 {
149 #ifdef TRACE_drawTex2Tex
150 J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "drawTex2Tex: src tex=%p, dst tex=%p", src, dst);
151 J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sw=%d sh=%d dw=%d dh=%d", src.width, src.height, dst.width, dst.height);
152 J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", sx1, sy1, sx2, sy2);
153 J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2);
154 #endif //TRACE_drawTex2Tex
155
156 id<MTLRenderCommandEncoder> encoder = [mtlc.encoderManager getTextureEncoder:dst
157 isSrcOpaque:isSrcOpaque
158 isDstOpaque:isDstOpaque];
159
160 struct TxtVertex quadTxVerticesBuffer[6];
161 fillTxQuad(quadTxVerticesBuffer, sx1, sy1, sx2, sy2, src.width, src.height, dx1, dy1, dx2, dy2, dst.width, dst.height);
162
163 [encoder setVertexBytes:quadTxVerticesBuffer length:sizeof(quadTxVerticesBuffer) atIndex:MeshVertexBuffer];
164 [encoder setFragmentTexture:src atIndex: 0];
165 [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
166 }
167
168 static
169 id<MTLTexture> replaceTextureRegion(id<MTLTexture> dest, const SurfaceDataRasInfo * srcInfo, const MTLRasterFormatInfo * rfi, int dx1, int dy1, int dx2, int dy2) {
170 const int dw = dx2 - dx1;
171 const int dh = dy2 - dy1;
172
173 const void * raster = srcInfo->rasBase;
174 id<MTLTexture> result = nil;
175 if (rfi->permuteMap != NULL) {
176 #if defined(__MAC_10_15) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15
177 if (@available(macOS 10.15, *)) {
178 @autoreleasepool {
232 rfi->permuteMap[0], rfi->permuteMap[1], rfi->permuteMap[2], rfi->permuteMap[3], rfi->hasAlpha);
233 }
234 }
235
236 MTLRegion region = MTLRegionMake2D(dx1, dy1, dw, dh);
237 if (result != nil)
238 dest = result;
239 [dest replaceRegion:region mipmapLevel:0 withBytes:raster bytesPerRow:srcInfo->scanStride];
240 return result;
241 }
242
243 /**
244 * Inner loop used for copying a source system memory ("Sw") surface to a
245 * destination MTL "Surface". This method is invoked from
246 * MTLBlitLoops_Blit().
247 */
248
249 static void
250 MTLBlitSwToTextureViaPooledTexture(
251 MTLContext *mtlc, SurfaceDataRasInfo *srcInfo, BMTLSDOps * bmtlsdOps,
252 MTLRasterFormatInfo * rfi, jboolean useBlitEncoder,
253 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
254 {
255 const int sw = srcInfo->bounds.x2 - srcInfo->bounds.x1;
256 const int sh = srcInfo->bounds.y2 - srcInfo->bounds.y1;
257 id<MTLTexture> dest = bmtlsdOps->pTexture;
258
259 MTLPooledTextureHandle * texHandle = [mtlc.texturePool getTexture:sw height:sh format:rfi->format];
260 if (texHandle == nil) {
261 J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitSwToTextureViaPooledTexture: can't obtain temporary texture object from pool");
262 return;
263 }
264 [[mtlc getCommandBufferWrapper] registerPooledTexture:texHandle];
265 [texHandle release];
266
267 id<MTLTexture> texBuff = texHandle.texture;
268 id<MTLTexture> swizzledTexture = replaceTextureRegion(texBuff, srcInfo, rfi, 0, 0, sw, sh);
269 if (useBlitEncoder) {
270 id <MTLBlitCommandEncoder> blitEncoder = [mtlc.encoderManager createBlitEncoder];
271 [blitEncoder copyFromTexture:swizzledTexture != nil ? swizzledTexture : texBuff
272 sourceSlice:0
273 sourceLevel:0
274 sourceOrigin:MTLOriginMake(0, 0, 0)
275 sourceSize:MTLSizeMake(sw, sh, 1)
276 toTexture:dest
277 destinationSlice:0
278 destinationLevel:0
279 destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
280 [blitEncoder endEncoding];
281 } else {
282 drawTex2Tex(mtlc, swizzledTexture != nil ? swizzledTexture : texBuff, dest, !rfi->hasAlpha, bmtlsdOps->isOpaque,
283 0, 0, sw, sh, dx1, dy1, dx2, dy2);
284 }
285
286 if (swizzledTexture != nil) {
287 [swizzledTexture release];
288 }
289 }
290
291 static
292 jboolean isIntegerAndUnscaled(
293 jint sx1, jint sy1, jint sx2, jint sy2,
294 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2
295 ) {
296 const jdouble epsilon = 0.0001f;
297
298 // check that dx1,dy1 is integer
299 if (fabs(dx1 - (int)dx1) > epsilon || fabs(dy1 - (int)dy1) > epsilon) {
300 return JNI_FALSE;
301 }
302 // check that destSize equals srcSize
468 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via blitEncoder]");
469 #endif //TRACE_ISOBLIT
470
471 id <MTLBlitCommandEncoder> blitEncoder = [mtlc.encoderManager createBlitEncoder];
472 [blitEncoder copyFromTexture:srcTex
473 sourceSlice:0
474 sourceLevel:0
475 sourceOrigin:MTLOriginMake(sx1, sy1, 0)
476 sourceSize:MTLSizeMake(sx2 - sx1, sy2 - sy1, 1)
477 toTexture:dstTex
478 destinationSlice:0
479 destinationLevel:0
480 destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
481 [blitEncoder endEncoding];
482 return;
483 }
484
485 #ifdef TRACE_ISOBLIT
486 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via sampling]");
487 #endif //TRACE_ISOBLIT
488 drawTex2Tex(mtlc, srcTex, dstTex, srcOps->isOpaque, dstOps->isOpaque, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
489 }
490
491 /**
492 * General blit method for copying a system memory ("Sw") surface to a native MTL surface.
493 * Parameter texture == true only in SwToTextureBlit (straight copy from sw to texture), dest coordinates will always be integers.
494 * Parameter xform == true only when AffineTransform is used (invoked only from TransformBlit, dest coordinates will always be integers).
495 */
496 void
497 MTLBlitLoops_Blit(JNIEnv *env,
498 MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
499 jboolean xform, jint hint,
500 jint srctype, jboolean texture,
501 jint sx1, jint sy1, jint sx2, jint sy2,
502 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
503 {
504 SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
505 BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDstOps);
506
507 RETURN_IF_NULL(mtlc);
508 RETURN_IF_NULL(srcOps);
596 sx1, sy1, sx2, sy2,
597 dx1, dy1, dx2, dy2);
598 #endif //TRACE_BLIT
599
600 MTLRasterFormatInfo rfi = RasterFormatInfos[srctype];
601 const jboolean useReplaceRegion = texture ||
602 ([mtlc isBlendingDisabled:!rfi.hasAlpha]
603 && !xform
604 && isIntegerAndUnscaled(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2));
605
606 if (useReplaceRegion) {
607 if (dstOps->isOpaque || rfi.hasAlpha) {
608 #ifdef TRACE_BLIT
609 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [replaceTextureRegion]");
610 #endif //TRACE_BLIT
611 replaceTextureRegion(dest, &srcInfo, &rfi, (int) dx1, (int) dy1, (int) dx2, (int) dy2);
612 } else {
613 #ifdef TRACE_BLIT
614 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via pooled + blit]");
615 #endif //TRACE_BLIT
616 MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, true, dx1, dy1, dx2, dy2);
617 }
618 } else { // !useReplaceRegion
619 #ifdef TRACE_BLIT
620 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via pooled texture]");
621 #endif //TRACE_BLIT
622 MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, false, dx1, dy1, dx2, dy2);
623 }
624 }
625 SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
626 }
627 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
628 }
629
630 /**
631 * Specialized blit method for copying a native MTL "Surface" (pbuffer,
632 * window, etc.) to a system memory ("Sw") surface.
633 */
634 void
635 MTLBlitLoops_SurfaceToSwBlit(JNIEnv *env, MTLContext *mtlc,
636 jlong pSrcOps, jlong pDstOps, jint dsttype,
637 jint srcx, jint srcy, jint dstx, jint dsty,
638 jint width, jint height)
639 {
640 J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: sx=%d sy=%d w=%d h=%d dx=%d dy=%d", srcx, srcy, width, height, dstx, dsty);
641
642 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
|
125 txQuadVerts[3].position[0] = dx2;
126 txQuadVerts[3].position[1] = dy2;
127 txQuadVerts[3].txtpos[0] = nsx2;
128 txQuadVerts[3].txtpos[1] = nsy2;
129
130 txQuadVerts[4].position[0] = dx1;
131 txQuadVerts[4].position[1] = dy2;
132 txQuadVerts[4].txtpos[0] = nsx1;
133 txQuadVerts[4].txtpos[1] = nsy2;
134
135 txQuadVerts[5].position[0] = dx1;
136 txQuadVerts[5].position[1] = dy1;
137 txQuadVerts[5].txtpos[0] = nsx1;
138 txQuadVerts[5].txtpos[1] = nsy1;
139 }
140
141 //#define TRACE_drawTex2Tex
142
143 void drawTex2Tex(MTLContext *mtlc,
144 id<MTLTexture> src, id<MTLTexture> dst,
145 jboolean isSrcOpaque, jboolean isDstOpaque, jint hint,
146 jint sx1, jint sy1, jint sx2, jint sy2,
147 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
148 {
149 #ifdef TRACE_drawTex2Tex
150 J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "drawTex2Tex: src tex=%p, dst tex=%p", src, dst);
151 J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sw=%d sh=%d dw=%d dh=%d", src.width, src.height, dst.width, dst.height);
152 J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", sx1, sy1, sx2, sy2);
153 J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2);
154 #endif //TRACE_drawTex2Tex
155
156 id<MTLRenderCommandEncoder> encoder = [mtlc.encoderManager getTextureEncoder:dst
157 isSrcOpaque:isSrcOpaque
158 isDstOpaque:isDstOpaque
159 interpolation:hint
160 ];
161
162 struct TxtVertex quadTxVerticesBuffer[6];
163 fillTxQuad(quadTxVerticesBuffer, sx1, sy1, sx2, sy2, src.width, src.height, dx1, dy1, dx2, dy2, dst.width, dst.height);
164
165 [encoder setVertexBytes:quadTxVerticesBuffer length:sizeof(quadTxVerticesBuffer) atIndex:MeshVertexBuffer];
166 [encoder setFragmentTexture:src atIndex: 0];
167 [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
168 }
169
170 static
171 id<MTLTexture> replaceTextureRegion(id<MTLTexture> dest, const SurfaceDataRasInfo * srcInfo, const MTLRasterFormatInfo * rfi, int dx1, int dy1, int dx2, int dy2) {
172 const int dw = dx2 - dx1;
173 const int dh = dy2 - dy1;
174
175 const void * raster = srcInfo->rasBase;
176 id<MTLTexture> result = nil;
177 if (rfi->permuteMap != NULL) {
178 #if defined(__MAC_10_15) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15
179 if (@available(macOS 10.15, *)) {
180 @autoreleasepool {
234 rfi->permuteMap[0], rfi->permuteMap[1], rfi->permuteMap[2], rfi->permuteMap[3], rfi->hasAlpha);
235 }
236 }
237
238 MTLRegion region = MTLRegionMake2D(dx1, dy1, dw, dh);
239 if (result != nil)
240 dest = result;
241 [dest replaceRegion:region mipmapLevel:0 withBytes:raster bytesPerRow:srcInfo->scanStride];
242 return result;
243 }
244
245 /**
246 * Inner loop used for copying a source system memory ("Sw") surface to a
247 * destination MTL "Surface". This method is invoked from
248 * MTLBlitLoops_Blit().
249 */
250
251 static void
252 MTLBlitSwToTextureViaPooledTexture(
253 MTLContext *mtlc, SurfaceDataRasInfo *srcInfo, BMTLSDOps * bmtlsdOps,
254 MTLRasterFormatInfo * rfi, jboolean useBlitEncoder, jint hint,
255 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
256 {
257 const int sw = srcInfo->bounds.x2 - srcInfo->bounds.x1;
258 const int sh = srcInfo->bounds.y2 - srcInfo->bounds.y1;
259 id<MTLTexture> dest = bmtlsdOps->pTexture;
260
261 MTLPooledTextureHandle * texHandle = [mtlc.texturePool getTexture:sw height:sh format:rfi->format];
262 if (texHandle == nil) {
263 J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitSwToTextureViaPooledTexture: can't obtain temporary texture object from pool");
264 return;
265 }
266 [[mtlc getCommandBufferWrapper] registerPooledTexture:texHandle];
267 [texHandle release];
268
269 id<MTLTexture> texBuff = texHandle.texture;
270 id<MTLTexture> swizzledTexture = replaceTextureRegion(texBuff, srcInfo, rfi, 0, 0, sw, sh);
271 if (useBlitEncoder) {
272 id <MTLBlitCommandEncoder> blitEncoder = [mtlc.encoderManager createBlitEncoder];
273 [blitEncoder copyFromTexture:swizzledTexture != nil ? swizzledTexture : texBuff
274 sourceSlice:0
275 sourceLevel:0
276 sourceOrigin:MTLOriginMake(0, 0, 0)
277 sourceSize:MTLSizeMake(sw, sh, 1)
278 toTexture:dest
279 destinationSlice:0
280 destinationLevel:0
281 destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
282 [blitEncoder endEncoding];
283 } else {
284 drawTex2Tex(mtlc, swizzledTexture != nil ? swizzledTexture : texBuff, dest, !rfi->hasAlpha, bmtlsdOps->isOpaque, hint,
285 0, 0, sw, sh, dx1, dy1, dx2, dy2);
286 }
287
288 if (swizzledTexture != nil) {
289 [swizzledTexture release];
290 }
291 }
292
293 static
294 jboolean isIntegerAndUnscaled(
295 jint sx1, jint sy1, jint sx2, jint sy2,
296 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2
297 ) {
298 const jdouble epsilon = 0.0001f;
299
300 // check that dx1,dy1 is integer
301 if (fabs(dx1 - (int)dx1) > epsilon || fabs(dy1 - (int)dy1) > epsilon) {
302 return JNI_FALSE;
303 }
304 // check that destSize equals srcSize
470 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via blitEncoder]");
471 #endif //TRACE_ISOBLIT
472
473 id <MTLBlitCommandEncoder> blitEncoder = [mtlc.encoderManager createBlitEncoder];
474 [blitEncoder copyFromTexture:srcTex
475 sourceSlice:0
476 sourceLevel:0
477 sourceOrigin:MTLOriginMake(sx1, sy1, 0)
478 sourceSize:MTLSizeMake(sx2 - sx1, sy2 - sy1, 1)
479 toTexture:dstTex
480 destinationSlice:0
481 destinationLevel:0
482 destinationOrigin:MTLOriginMake(dx1, dy1, 0)];
483 [blitEncoder endEncoding];
484 return;
485 }
486
487 #ifdef TRACE_ISOBLIT
488 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via sampling]");
489 #endif //TRACE_ISOBLIT
490 drawTex2Tex(mtlc, srcTex, dstTex, srcOps->isOpaque, dstOps->isOpaque, hint, sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
491 }
492
493 /**
494 * General blit method for copying a system memory ("Sw") surface to a native MTL surface.
495 * Parameter texture == true only in SwToTextureBlit (straight copy from sw to texture), dest coordinates will always be integers.
496 * Parameter xform == true only when AffineTransform is used (invoked only from TransformBlit, dest coordinates will always be integers).
497 */
498 void
499 MTLBlitLoops_Blit(JNIEnv *env,
500 MTLContext *mtlc, jlong pSrcOps, jlong pDstOps,
501 jboolean xform, jint hint,
502 jint srctype, jboolean texture,
503 jint sx1, jint sy1, jint sx2, jint sy2,
504 jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
505 {
506 SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
507 BMTLSDOps *dstOps = (BMTLSDOps *)jlong_to_ptr(pDstOps);
508
509 RETURN_IF_NULL(mtlc);
510 RETURN_IF_NULL(srcOps);
598 sx1, sy1, sx2, sy2,
599 dx1, dy1, dx2, dy2);
600 #endif //TRACE_BLIT
601
602 MTLRasterFormatInfo rfi = RasterFormatInfos[srctype];
603 const jboolean useReplaceRegion = texture ||
604 ([mtlc isBlendingDisabled:!rfi.hasAlpha]
605 && !xform
606 && isIntegerAndUnscaled(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2));
607
608 if (useReplaceRegion) {
609 if (dstOps->isOpaque || rfi.hasAlpha) {
610 #ifdef TRACE_BLIT
611 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [replaceTextureRegion]");
612 #endif //TRACE_BLIT
613 replaceTextureRegion(dest, &srcInfo, &rfi, (int) dx1, (int) dy1, (int) dx2, (int) dy2);
614 } else {
615 #ifdef TRACE_BLIT
616 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via pooled + blit]");
617 #endif //TRACE_BLIT
618 MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, true, hint, dx1, dy1, dx2, dy2);
619 }
620 } else { // !useReplaceRegion
621 #ifdef TRACE_BLIT
622 J2dTraceImpl(J2D_TRACE_VERBOSE, JNI_TRUE," [via pooled texture]");
623 #endif //TRACE_BLIT
624 MTLBlitSwToTextureViaPooledTexture(mtlc, &srcInfo, dstOps, &rfi, false, hint, dx1, dy1, dx2, dy2);
625 }
626 }
627 SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
628 }
629 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
630 }
631
632 /**
633 * Specialized blit method for copying a native MTL "Surface" (pbuffer,
634 * window, etc.) to a system memory ("Sw") surface.
635 */
636 void
637 MTLBlitLoops_SurfaceToSwBlit(JNIEnv *env, MTLContext *mtlc,
638 jlong pSrcOps, jlong pDstOps, jint dsttype,
639 jint srcx, jint srcy, jint dstx, jint dsty,
640 jint width, jint height)
641 {
642 J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: sx=%d sy=%d w=%d h=%d dx=%d dy=%d", srcx, srcy, width, height, dstx, dsty);
643
644 BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps);
|