8298217: Regressions 30-110% in SwingMark on MacOS, more so on aarch64

Reviewed-by: avu, prr, jdv
This commit is contained in:
Ajit Ghaisas 2022-12-17 06:37:18 +00:00
parent 0ecad28daa
commit 3b7970cab3
5 changed files with 106 additions and 381 deletions

View File

@ -51,11 +51,6 @@ enum {
MTL_OP_SYNC,
MTL_OP_SHAPE_CLIP_SPANS,
MTL_OP_MASK_OP,
MTL_OP_FILL_PARALLELOGRAM,
MTL_OP_FILL_RECT,
MTL_OP_DRAW_LINE,
MTL_OP_DRAW_RECT,
MTL_OP_DRAW_PARALLELOGRAM,
MTL_OP_OTHER
};
/*

View File

@ -48,18 +48,6 @@ jint mtlPreviousOp = MTL_OP_INIT;
extern void MTLGC_DestroyMTLGraphicsConfig(jlong pConfigInfo);
bool isDrawOp (jint op) {
switch(op) {
case MTL_OP_DRAW_LINE:
case MTL_OP_DRAW_RECT:
case MTL_OP_DRAW_PARALLELOGRAM:
case MTL_OP_FILL_RECT:
case MTL_OP_FILL_PARALLELOGRAM:
return true;
default: return false;
}
}
void MTLRenderQueue_CheckPreviousOp(jint op) {
if (mtlPreviousOp == op) {
@ -67,16 +55,6 @@ void MTLRenderQueue_CheckPreviousOp(jint op) {
return;
}
if (isDrawOp(mtlPreviousOp)) {
// submit the vertex batch
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
if (isDrawOp(op)) {
// Do not cause endEncoder if we continue with Draw operations
mtlPreviousOp = op;
return;
}
}
if (op == MTL_OP_SET_COLOR) {
if (mtlPreviousOp != MTL_OP_MASK_OP) {
return; // SET_COLOR should not cause endEncoder
@ -150,7 +128,7 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
// draw ops
case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
{
CHECK_PREVIOUS_OP(MTL_OP_DRAW_LINE);
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
if ([mtlc useXORComposite]) {
commitEncodedCommands();
@ -166,10 +144,9 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
}
case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT:
{
CHECK_PREVIOUS_OP(MTL_OP_DRAW_RECT);
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
if ([mtlc useXORComposite]) {
commitEncodedCommands();
J2dTraceLn(J2D_TRACE_VERBOSE,
"DRAW_RECT in XOR mode - Force commit earlier draw calls before DRAW_RECT.");
@ -251,7 +228,7 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
}
case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
{
CHECK_PREVIOUS_OP(MTL_OP_DRAW_PARALLELOGRAM);
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
if ([mtlc useXORComposite]) {
commitEncodedCommands();
@ -299,7 +276,7 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
// fill ops
case sun_java2d_pipe_BufferedOpCodes_FILL_RECT:
{
CHECK_PREVIOUS_OP(MTL_OP_FILL_RECT);
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
if ([mtlc useXORComposite]) {
commitEncodedCommands();
@ -331,7 +308,7 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
}
case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
{
CHECK_PREVIOUS_OP(MTL_OP_FILL_PARALLELOGRAM);
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
if ([mtlc useXORComposite]) {
commitEncodedCommands();
@ -605,7 +582,6 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
jlong pDst = NEXT_LONG(b);
if (mtlc != NULL) {
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
[mtlc.encoderManager endEncoder];
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
@ -633,7 +609,6 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
} else {
if (mtlc != NULL) {
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
[mtlc.encoderManager endEncoder];
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
@ -903,8 +878,6 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
if (mtlPreviousOp == MTL_OP_MASK_OP) {
MTLVertexCache_DisableMaskCache(mtlc);
}
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
[mtlc.encoderManager endEncoder];
MTLCommandBufferWrapper * cbwrapper = [mtlc pullCommandBufferWrapper];
id<MTLCommandBuffer> commandbuf = [cbwrapper getCommandBuffer];
@ -950,9 +923,6 @@ MTLRenderQueue_GetCurrentDestination()
* these would be rendered to the back-buffer - which is read in shader while rendering in XOR mode
*/
void commitEncodedCommands() {
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
[mtlc.encoderManager endEncoder];
MTLCommandBufferWrapper *cbwrapper = [mtlc pullCommandBufferWrapper];

View File

@ -72,9 +72,5 @@ void MTLRenderer_FillAAParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
jfloat fx11, jfloat fy11,
jfloat dx21, jfloat dy21,
jfloat dx12, jfloat dy12);
void MTLRenderer_AddVertexToBatch(float x, float y);
void MTLRenderer_SubmitVertexBatch(MTLContext* mtlc, BMTLSDOps* dstOps);
void MTLRenderer_SetPrimitiveType(MTLPrimitiveType type);
#endif /* MTLRenderer_h_Included */

View File

@ -35,95 +35,6 @@
#include "MTLUtils.h"
#import "MTLLayer.h"
/**
* The max size of the vertex batch.
*
* Note:
* This is the max number of vertices (of struct Vertex - 8 bytes)
* that can be accommodated in 4KB.
*
* [MTLRenderCommandEncoder setVertexBytes] expects the data size
* to be less than or equal to 4KB.
*/
static const int VERTEX_BATCH_SIZE = 510;
static const int MAX_NO_OF_BATCHES = 20;
struct primDetail {
MTLPrimitiveType type;
int vertexStart;
int vertexEnd;
};
static struct Vertex vertexBatch[VERTEX_BATCH_SIZE];
static struct primDetail PrimitivesBatch[MAX_NO_OF_BATCHES];
static int currentIndexInBatch = 0;
static MTLPrimitiveType currentMTLPrimitiveType = MTLPrimitiveTypeTriangleStrip; // invalid type that we do not use in this renderer
static int currentBatchNo = -1;
void MTLRenderer_SetPrimitiveType(MTLPrimitiveType type) {
if (type != currentMTLPrimitiveType) {
if (currentBatchNo != -1) {
// close the current batch
PrimitivesBatch[currentBatchNo].vertexEnd = currentIndexInBatch - 1;
}
// Start a new batch
currentBatchNo++;
PrimitivesBatch[currentBatchNo].type = type;
PrimitivesBatch[currentBatchNo].vertexStart = currentIndexInBatch;
PrimitivesBatch[currentBatchNo].vertexEnd = currentIndexInBatch;
J2dRlsTraceLn1(J2D_TRACE_ERROR, "MTLRenderer_SetPrimitiveType: starting a new batch : batch %d", currentBatchNo);
currentMTLPrimitiveType = type;
}
}
inline void MTLRenderer_AddVertexToBatch(float x, float y)
{
vertexBatch[currentIndexInBatch].position[0] = x;
vertexBatch[currentIndexInBatch].position[1] = y;
currentIndexInBatch++;
}
void MTLRenderer_SubmitVertexBatch(MTLContext *mtlc, BMTLSDOps * dstOps)
{
if (currentIndexInBatch == 0) return;
if (currentBatchNo == -1) return;
// close the current batch
PrimitivesBatch[currentBatchNo].vertexEnd = currentIndexInBatch - 1;
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
if (mtlEncoder == nil) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_SubmitVertexBatch: error creating MTLRenderCommandEncoder.");
return;
}
[mtlEncoder setVertexBytes:vertexBatch length:currentIndexInBatch * sizeof(struct Vertex) atIndex:MeshVertexBuffer];
// Iterate through PrimitivesBatch array
for (int i = 0; i <= currentBatchNo; i++) {
int numVertices = PrimitivesBatch[i].vertexEnd - PrimitivesBatch[i].vertexStart + 1;
J2dRlsTraceLn2(J2D_TRACE_ERROR, "MTLRenderer_SubmitVertexBatch: total vertices in batch %d = %d", i, numVertices);
[mtlEncoder drawPrimitives: PrimitivesBatch[i].type
vertexStart: PrimitivesBatch[i].vertexStart
vertexCount: numVertices];
}
// Reset the index
currentIndexInBatch = 0;
// Reset the batches
currentBatchNo = -1;
// Reset to type that we do not use in this renderer
currentMTLPrimitiveType = MTLPrimitiveTypeTriangleStrip;
}
/**
* Note: Some of the methods in this file apply a "magic number"
* translation to line segments. It is same as what we have in
@ -154,16 +65,12 @@ void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1
J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawLine (x1=%d y1=%d x2=%d y2=%d), dst tex=%p", x1, y1, x2, y2, dstOps->pTexture);
// Make sure we have space for 2 more vertices in the batch
if (((currentIndexInBatch + 2) > VERTEX_BATCH_SIZE) ||
(currentBatchNo == (MAX_NO_OF_BATCHES - 1))) {
// encode the vertex batch
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
}
MTLRenderer_SetPrimitiveType(MTLPrimitiveTypeLine);
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
if (mtlEncoder == nil)
return;
// DrawLine implementation same as in OGLRenderer.c
struct Vertex verts[2];
if (y1 == y2) {
// horizontal
float fx1 = (float)x1;
@ -173,8 +80,11 @@ void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1
if (x1 > x2) {
float t = fx1; fx1 = fx2; fx2 = t;
}
MTLRenderer_AddVertexToBatch(fx1 + 0.2f, fy);
MTLRenderer_AddVertexToBatch(fx2 + 1.2f, fy);
verts[0].position[0] = fx1 + 0.2f;
verts[0].position[1] = fy;
verts[1].position[0] = fx2 + 1.2f;
verts[1].position[1] = fy;
} else if (x1 == x2) {
// vertical
float fx = ((float)x1) + 0.2f;
@ -184,8 +94,11 @@ void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1
if (y1 > y2) {
float t = fy1; fy1 = fy2; fy2 = t;
}
MTLRenderer_AddVertexToBatch(fx, fy1 + 0.2f);
MTLRenderer_AddVertexToBatch(fx, fy2 + 1.2f);
verts[0].position[0] = fx;
verts[0].position[1] = fy1 + 0.2f;
verts[1].position[0] = fx;
verts[1].position[1] = fy2 + 1.2f;
} else {
// diagonal
float fx1 = (float)x1;
@ -208,10 +121,14 @@ void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1
fy1 += 0.8f;
fy2 -= 0.2f;
}
MTLRenderer_AddVertexToBatch(fx1, fy1);
MTLRenderer_AddVertexToBatch(fx2, fy2);
verts[0].position[0] = fx1;
verts[0].position[1] = fy1;
verts[1].position[0] = fx2;
verts[1].position[1] = fy2;
}
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:2];
}
void MTLRenderer_DrawPixel(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y) {
@ -245,35 +162,27 @@ void MTLRenderer_DrawRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y,
id<MTLTexture> dest = dstOps->pTexture;
J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest);
// Make sure we have space for 8 more vertices in the batch
if ( ((currentIndexInBatch + 8) > VERTEX_BATCH_SIZE) ||
(currentBatchNo == (MAX_NO_OF_BATCHES - 1))) {
// encode the vertex batch
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
}
MTLRenderer_SetPrimitiveType(MTLPrimitiveTypeLine);
// TODO: use DrawParallelogram(x, y, w, h, lw=1, lh=1)
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
if (mtlEncoder == nil)
return;
// Translate each vertex by a fraction so
// that we hit pixel centers.
const int verticesCount = 5;
float fx = (float)x + 0.2f;
float fy = (float)y + 0.5f;
float fw = (float)w;
float fh = (float)h;
MTLRenderer_AddVertexToBatch(fx, fy);
MTLRenderer_AddVertexToBatch(fx+fw, fy);
MTLRenderer_AddVertexToBatch(fx+fw, fy);
MTLRenderer_AddVertexToBatch(fx+fw, fy+fh);
MTLRenderer_AddVertexToBatch(fx+fw, fy+fh);
MTLRenderer_AddVertexToBatch(fx, fy+fh);
MTLRenderer_AddVertexToBatch(fx, fy+fh);
MTLRenderer_AddVertexToBatch(fx, fy);
struct Vertex vertices[5] = {
{{fx, fy}},
{{fx + fw, fy}},
{{fx + fw, fy + fh}},
{{fx, fy + fh}},
{{fx, fy}},
};
[mtlEncoder setVertexBytes:vertices length:sizeof(vertices) atIndex:MeshVertexBuffer];
[mtlEncoder drawPrimitives:MTLPrimitiveTypeLineStrip vertexStart:0 vertexCount:verticesCount];
}
const int POLYLINE_BUF_SIZE = 64;
@ -506,23 +415,24 @@ MTLRenderer_FillRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y, jint
return;
}
// Make sure we have space for 6 more vertices in the batch
if ( ((currentIndexInBatch + 6) > VERTEX_BATCH_SIZE) ||
(currentBatchNo == (MAX_NO_OF_BATCHES - 1))) {
// encode the vertex batch
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
}
MTLRenderer_SetPrimitiveType(MTLPrimitiveTypeTriangle);
struct Vertex verts[QUAD_VERTEX_COUNT] = {
{ {x, y}},
{ {x, y+h}},
{ {x+w, y}},
{ {x+w, y+h}
}};
MTLRenderer_AddVertexToBatch(x, y);
MTLRenderer_AddVertexToBatch(x, y+h);
MTLRenderer_AddVertexToBatch(x+w, y);
id<MTLTexture> dest = dstOps->pTexture;
J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_FillRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest);
MTLRenderer_AddVertexToBatch(x, y+h);
MTLRenderer_AddVertexToBatch(x+w, y);
MTLRenderer_AddVertexToBatch(x+w, y+h);
// Encode render command.
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
if (mtlEncoder == nil)
return;
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount: QUAD_VERTEX_COUNT];
}
void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, jint *spans)
@ -643,22 +553,23 @@ MTLRenderer_FillParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
dx21, dy21,
dx12, dy12, dest);
// Make sure we have space for 6 more vertices in the batch
if ( ((currentIndexInBatch + 6) > VERTEX_BATCH_SIZE) ||
(currentBatchNo == (MAX_NO_OF_BATCHES - 1))) {
// encode the vertex batch
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
struct Vertex verts[QUAD_VERTEX_COUNT] = {
{ {fx11, fy11}},
{ {fx11+dx21, fy11+dy21}},
{ {fx11+dx12, fy11+dy12}},
{ {fx11 + dx21 + dx12, fy11+ dy21 + dy12}
}};
// Encode render command.
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];;
if (mtlEncoder == nil) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_FillParallelogram: error creating MTLRenderCommandEncoder.");
return;
}
MTLRenderer_SetPrimitiveType(MTLPrimitiveTypeTriangle);
MTLRenderer_AddVertexToBatch(fx11, fy11);
MTLRenderer_AddVertexToBatch(fx11+dx21, fy11+dy21);
MTLRenderer_AddVertexToBatch(fx11 + dx21 + dx12, fy11+ dy21 + dy12);
MTLRenderer_AddVertexToBatch(fx11 + dx21 + dx12, fy11+ dy21 + dy12);
MTLRenderer_AddVertexToBatch(fx11 + dx12, fy11+dy12);
MTLRenderer_AddVertexToBatch(fx11, fy11);
[mtlEncoder setVertexBytes:verts length:sizeof(verts) atIndex:MeshVertexBuffer];
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount: QUAD_VERTEX_COUNT];
}
void
@ -720,66 +631,69 @@ MTLRenderer_DrawParallelogram(MTLContext *mtlc, BMTLSDOps * dstOps,
// Each quad is encoded using two triangles
// For 4 segments - there are 8 triangles in total
// Each triangle has 3 vertices
const int TOTAL_VERTICES = 8 * 3;
// Make sure we have space for 24 more vertices in the batch
if ( ((currentIndexInBatch + TOTAL_VERTICES) > VERTEX_BATCH_SIZE) ||
(currentBatchNo == (MAX_NO_OF_BATCHES - 1))) {
// encode the vertex batch
MTLRenderer_SubmitVertexBatch(mtlc, dstOps);
}
MTLRenderer_SetPrimitiveType(MTLPrimitiveTypeTriangle);
struct Vertex vertexList[TOTAL_VERTICES];
int i = 0;
// TOP segment, to left side of RIGHT edge
// "width" of original pgram, "height" of hor. line size
fx11 = ox11;
fy11 = oy11;
MTLRenderer_AddVertexToBatch(fx11, fy11);
MTLRenderer_AddVertexToBatch(fx11 + dx21, fy11 + dy21);
MTLRenderer_AddVertexToBatch(fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
fillVertex(vertexList + (i++), fx11, fy11);
fillVertex(vertexList + (i++), fx11 + dx21, fy11 + dy21);
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
MTLRenderer_AddVertexToBatch(fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
MTLRenderer_AddVertexToBatch(fx11 + ldx12, fy11 + ldy12);
MTLRenderer_AddVertexToBatch(fx11, fy11);
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
fillVertex(vertexList + (i++), fx11 + ldx12, fy11 + ldy12);
fillVertex(vertexList + (i++), fx11, fy11);
// RIGHT segment, to top of BOTTOM edge
// "width" of vert. line size , "height" of original pgram
fx11 = ox11 + dx21;
fy11 = oy11 + dy21;
MTLRenderer_AddVertexToBatch(fx11, fy11);
MTLRenderer_AddVertexToBatch(fx11 + ldx21, fy11 + ldy21);
MTLRenderer_AddVertexToBatch(fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
fillVertex(vertexList + (i++), fx11, fy11);
fillVertex(vertexList + (i++), fx11 + ldx21, fy11 + ldy21);
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
MTLRenderer_AddVertexToBatch(fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
MTLRenderer_AddVertexToBatch(fx11 + dx12, fy11 + dy12);
MTLRenderer_AddVertexToBatch(fx11, fy11);
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
fillVertex(vertexList + (i++), fx11 + dx12, fy11 + dy12);
fillVertex(vertexList + (i++), fx11, fy11);
// BOTTOM segment, from right side of LEFT edge
// "width" of original pgram, "height" of hor. line size
fx11 = ox11 + dx12 + ldx21;
fy11 = oy11 + dy12 + ldy21;
MTLRenderer_AddVertexToBatch(fx11, fy11);
MTLRenderer_AddVertexToBatch(fx11 + dx21, fy11 + dy21);
MTLRenderer_AddVertexToBatch(fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
fillVertex(vertexList + (i++), fx11, fy11);
fillVertex(vertexList + (i++), fx11 + dx21, fy11 + dy21);
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
MTLRenderer_AddVertexToBatch(fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
MTLRenderer_AddVertexToBatch(fx11 + ldx12, fy11 + ldy12);
MTLRenderer_AddVertexToBatch(fx11, fy11);
fillVertex(vertexList + (i++), fx11 + dx21 + ldx12, fy11 + dy21 + ldy12);
fillVertex(vertexList + (i++), fx11 + ldx12, fy11 + ldy12);
fillVertex(vertexList + (i++), fx11, fy11);
// LEFT segment, from bottom of TOP edge
// "width" of vert. line size , "height" of inner pgram
fx11 = ox11 + ldx12;
fy11 = oy11 + ldy12;
MTLRenderer_AddVertexToBatch(fx11, fy11);
MTLRenderer_AddVertexToBatch(fx11 + ldx21, fy11 + ldy21);
MTLRenderer_AddVertexToBatch(fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
fillVertex(vertexList + (i++), fx11, fy11);
fillVertex(vertexList + (i++), fx11 + ldx21, fy11 + ldy21);
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
MTLRenderer_AddVertexToBatch(fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
MTLRenderer_AddVertexToBatch(fx11 + dx12, fy11 + dy12);
MTLRenderer_AddVertexToBatch(fx11, fy11);
fillVertex(vertexList + (i++), fx11 + ldx21 + dx12, fy11 + ldy21 + dy12);
fillVertex(vertexList + (i++), fx11 + dx12, fy11 + dy12);
fillVertex(vertexList + (i++), fx11, fy11);
// Encode render command.
id<MTLRenderCommandEncoder> mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps];
if (mtlEncoder == nil) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawParallelogram: error creating MTLRenderCommandEncoder.");
return;
}
[mtlEncoder setVertexBytes:vertexList length:sizeof(vertexList) atIndex:MeshVertexBuffer];
[mtlEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:TOTAL_VERTICES];
} else {
// The line width ratios were large enough to consume
// the entire hole in the middle of the parallelogram

View File

@ -1,150 +0,0 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, JetBrains s.r.o.. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @key headful
* @bug 8287600 8291266
* @requires os.family == "mac"
* @summary [macosx] Some primitives do not render in metal pipeline
* @run main DrawPrimitivesTest
*/
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CountDownLatch;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public abstract class DrawPrimitivesTest extends JFrame {
private final static int W = 800;
private final static int H = 800;
private final static Color[] color = { Color.RED, Color.BLUE, Color.GREEN};
private final static int COLOR_TOLERANCE = 10;
private final CountDownLatch latchRender = new CountDownLatch(1);
private volatile int frameX0 = 0;
private volatile int frameY0 = 0;
private final String name;
private static boolean isAlmostEqual(Color c1, Color c2) {
return Math.abs(c1.getRed() - c2.getRed()) < COLOR_TOLERANCE &&
Math.abs(c1.getGreen() - c2.getGreen()) < COLOR_TOLERANCE &&
Math.abs(c1.getBlue() - c2.getBlue()) < COLOR_TOLERANCE;
}
public static void main(String[] args) throws InterruptedException, AWTException, InvocationTargetException {
new DrawPrimitivesTest("drawLine") {
public void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h) {
g2d.drawLine(x0, y0, x0+w, y0+h);
}
}.runTest();
new DrawPrimitivesTest("fillRect") {
public void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h) {
g2d.fillRect(x0, y0, w, h);
}
}.runTest();
new DrawPrimitivesTest("fillOvalAA") {
public void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x0, y0, w, h);
}
}.runTest();
}
public abstract void renderPrimitive(Graphics2D g2d, int x0, int y0, int w, int h);
public DrawPrimitivesTest(String name) {
super();
this.name = name;
}
public void runTest() throws InterruptedException, InvocationTargetException, AWTException {
SwingUtilities.invokeLater(() -> {
add(new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.YELLOW);
int c = 0;
for (int i = 0; i < W; i += 10) {
for (int j = 0; j < H; j += 10) {
c = (c + 1) % color.length;
g2d.setColor(color[c]);
renderPrimitive(g2d, i, j, 10, 10);
}
}
Point p = getLocationOnScreen();
frameX0 = p.x;
frameY0 = p.y - getInsets().top;
latchRender.countDown();
}
});
setPreferredSize(new Dimension(W, H));
pack();
setVisible(true);
});
latchRender.await();
Thread.sleep(1000);
Robot robot = new Robot();
boolean hasEmptyContent = true;
l:for (int i = frameX0 + W/3; i < frameX0 + (2*W)/3; i++) {
for (int j = 0; j < 10; j += 2) {
if (isAlmostEqual(robot.getPixelColor(i, frameY0 + H / 2 + j), Color.RED)) {
hasEmptyContent = false;
break l;
}
}
}
SwingUtilities.invokeAndWait(() -> {
setVisible(false);
dispose();
});
if (hasEmptyContent) {
throw new RuntimeException(name + ": Empty content");
}
}
}