< prev index next >

src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m

Print this page

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);
< prev index next >