Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m
41159 views
1
/*
2
* Copyright (c) 2019, 2021, 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
#include <stdlib.h>
27
#include <string.h>
28
29
#include "sun_java2d_SunGraphics2D.h"
30
31
#include "MTLPaints.h"
32
#include "MTLVertexCache.h"
33
#include "MTLTexturePool.h"
34
#include "MTLTextRenderer.h"
35
#include "common.h"
36
37
typedef struct _J2DVertex {
38
float position[2];
39
float txtpos[2];
40
} J2DVertex;
41
42
static J2DVertex *vertexCache = NULL;
43
static jint vertexCacheIndex = 0;
44
45
static MTLPooledTextureHandle * maskCacheTex = NULL;
46
static jint maskCacheIndex = 0;
47
static id<MTLRenderCommandEncoder> encoder = NULL;
48
49
#define MTLVC_ADD_VERTEX(TX, TY, DX, DY, DZ) \
50
do { \
51
J2DVertex *v = &vertexCache[vertexCacheIndex++]; \
52
v->txtpos[0] = TX; \
53
v->txtpos[1] = TY; \
54
v->position[0]= DX; \
55
v->position[1] = DY; \
56
} while (0)
57
58
#define MTLVC_ADD_TRIANGLES(TX1, TY1, TX2, TY2, DX1, DY1, DX2, DY2) \
59
do { \
60
MTLVC_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \
61
MTLVC_ADD_VERTEX(TX2, TY1, DX2, DY1, 0); \
62
MTLVC_ADD_VERTEX(TX2, TY2, DX2, DY2, 0); \
63
MTLVC_ADD_VERTEX(TX2, TY2, DX2, DY2, 0); \
64
MTLVC_ADD_VERTEX(TX1, TY2, DX1, DY2, 0); \
65
MTLVC_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \
66
} while (0)
67
68
jboolean
69
MTLVertexCache_InitVertexCache()
70
{
71
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitVertexCache");
72
73
if (vertexCache == NULL) {
74
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitVertexCache : vertexCache == NULL");
75
vertexCache = (J2DVertex *)malloc(MTLVC_MAX_INDEX * sizeof(J2DVertex));
76
if (vertexCache == NULL) {
77
return JNI_FALSE;
78
}
79
}
80
81
return JNI_TRUE;
82
}
83
84
void
85
MTLVertexCache_FlushVertexCache(MTLContext *mtlc)
86
{
87
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache");
88
89
if (vertexCacheIndex > 0) {
90
[encoder setVertexBytes: vertexCache length:vertexCacheIndex * sizeof(J2DVertex)
91
atIndex:MeshVertexBuffer];
92
93
[encoder setFragmentTexture:maskCacheTex.texture atIndex: 0];
94
J2dTraceLn1(J2D_TRACE_INFO,
95
"MTLVertexCache_FlushVertexCache : encode %d characters", (vertexCacheIndex / 6));
96
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:vertexCacheIndex];
97
}
98
vertexCacheIndex = 0;
99
maskCacheIndex = 0;
100
101
if (maskCacheTex != nil) {
102
[[mtlc getCommandBufferWrapper] registerPooledTexture:maskCacheTex];
103
[maskCacheTex release];
104
maskCacheTex = nil;
105
}
106
}
107
108
void
109
MTLVertexCache_FlushGlyphVertexCache()
110
{
111
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushGlyphVertexCache");
112
113
if (vertexCacheIndex > 0) {
114
[encoder setVertexBytes: vertexCache length:vertexCacheIndex * sizeof(J2DVertex)
115
atIndex:MeshVertexBuffer];
116
id<MTLTexture> glyphCacheTex = MTLTR_GetGlyphCacheTexture();
117
[encoder setFragmentTexture:glyphCacheTex atIndex: 0];
118
J2dTraceLn1(J2D_TRACE_INFO,
119
"MTLVertexCache_FlushGlyphVertexCache : encode %d characters", (vertexCacheIndex / 6));
120
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:vertexCacheIndex];
121
}
122
vertexCacheIndex = 0;
123
}
124
125
void MTLVertexCache_FreeVertexCache()
126
{
127
free(vertexCache);
128
vertexCache = NULL;
129
}
130
131
static jboolean
132
MTLVertexCache_InitMaskCache(MTLContext *mtlc) {
133
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitMaskCache");
134
if (maskCacheTex == NULL) {
135
maskCacheTex = [mtlc.texturePool getTexture:MTLVC_MASK_CACHE_WIDTH_IN_TEXELS
136
height:MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS
137
format:MTLPixelFormatA8Unorm];
138
[maskCacheTex retain];
139
if (maskCacheTex == nil) {
140
J2dTraceLn(J2D_TRACE_ERROR, "MTLVertexCache_InitMaskCache: can't obtain temporary texture object from pool");
141
return JNI_FALSE;
142
}
143
}
144
// init special fully opaque tile in the upper-right corner of
145
// the mask cache texture
146
147
char tile[MTLVC_MASK_CACHE_TILE_SIZE];
148
memset(tile, 0xff, MTLVC_MASK_CACHE_TILE_SIZE);
149
150
jint texx = MTLVC_MASK_CACHE_TILE_WIDTH * (MTLVC_MASK_CACHE_WIDTH_IN_TILES - 1);
151
152
jint texy = MTLVC_MASK_CACHE_TILE_HEIGHT * (MTLVC_MASK_CACHE_HEIGHT_IN_TILES - 1);
153
154
NSUInteger bytesPerRow = 1 * MTLVC_MASK_CACHE_TILE_WIDTH;
155
156
MTLRegion region = {
157
{texx, texy, 0},
158
{MTLVC_MASK_CACHE_TILE_WIDTH, MTLVC_MASK_CACHE_TILE_HEIGHT, 1}
159
};
160
161
162
// do we really need this??
163
[maskCacheTex.texture replaceRegion:region
164
mipmapLevel:0
165
withBytes:tile
166
bytesPerRow:bytesPerRow];
167
168
return JNI_TRUE;
169
}
170
171
void
172
MTLVertexCache_EnableMaskCache(MTLContext *mtlc, BMTLSDOps *dstOps)
173
{
174
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_EnableMaskCache");
175
176
if (!MTLVertexCache_InitVertexCache()) {
177
return;
178
}
179
180
if (maskCacheTex == NULL) {
181
if (!MTLVertexCache_InitMaskCache(mtlc)) {
182
return;
183
}
184
}
185
MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps);
186
}
187
188
void
189
MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
190
{
191
// TODO : Once we enable check_previous_op
192
// we will start using DisableMaskCache until then
193
// we are force flushing vertexcache.
194
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_DisableMaskCache");
195
MTLVertexCache_FlushVertexCache(mtlc);
196
maskCacheIndex = 0;
197
free(vertexCache);
198
vertexCache = NULL;
199
}
200
201
void
202
MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps) {
203
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_CreateSamplingEncoder");
204
encoder = [mtlc.encoderManager getTextEncoder:dstOps
205
isSrcOpaque:NO];
206
}
207
208
void
209
MTLVertexCache_AddMaskQuad(MTLContext *mtlc,
210
jint srcx, jint srcy,
211
jint dstx, jint dsty,
212
jint width, jint height,
213
jint maskscan, void *mask,
214
BMTLSDOps *dstOps)
215
{
216
jfloat tx1, ty1, tx2, ty2;
217
jfloat dx1, dy1, dx2, dy2;
218
219
J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_AddMaskQuad: %d",
220
maskCacheIndex);
221
222
if (maskCacheIndex >= MTLVC_MASK_CACHE_MAX_INDEX)
223
{
224
J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex);
225
MTLVertexCache_FlushVertexCache(mtlc);
226
MTLVertexCache_EnableMaskCache(mtlc, dstOps);
227
maskCacheIndex = 0;
228
}
229
230
if (mask != NULL) {
231
jint texx = MTLVC_MASK_CACHE_TILE_WIDTH *
232
(maskCacheIndex % MTLVC_MASK_CACHE_WIDTH_IN_TILES);
233
jint texy = MTLVC_MASK_CACHE_TILE_HEIGHT *
234
(maskCacheIndex / MTLVC_MASK_CACHE_WIDTH_IN_TILES);
235
J2dTraceLn5(J2D_TRACE_INFO, "texx = %d texy = %d width = %d height = %d maskscan = %d", texx, texy, width,
236
height, maskscan);
237
NSUInteger bytesPerRow = 1 * width;
238
NSUInteger slice = bytesPerRow * srcy + srcx;
239
MTLRegion region = {
240
{texx, texy, 0},
241
{width, height, 1}
242
};
243
244
// Whenever we have source stride bigger that destination stride
245
// we need to pick appropriate source subtexture. In repalceRegion
246
// we can give destination subtexturing properly but we can't
247
// subtexture from system memory glyph we have. So in such
248
// cases we are creating seperate tile and scan the source
249
// stride into destination using memcpy. In case of OpenGL we
250
// can update source pointers, in case of D3D we ar doing memcpy.
251
// We can use MTLBuffer and then copy source subtexture but that
252
// adds extra blitting logic.
253
// TODO : Research more and try removing memcpy logic.
254
if (maskscan <= width) {
255
int height_offset = bytesPerRow * srcy;
256
[maskCacheTex.texture replaceRegion:region
257
mipmapLevel:0
258
withBytes:mask + height_offset
259
bytesPerRow:bytesPerRow];
260
} else {
261
int dst_offset, src_offset;
262
int size = 1 * width * height;
263
char tile[size];
264
dst_offset = 0;
265
for (int i = srcy; i < srcy + height; i++) {
266
J2dTraceLn2(J2D_TRACE_INFO, "srcx = %d srcy = %d", srcx, srcy);
267
src_offset = maskscan * i + srcx;
268
J2dTraceLn2(J2D_TRACE_INFO, "src_offset = %d dst_offset = %d", src_offset, dst_offset);
269
memcpy(tile + dst_offset, mask + src_offset, width);
270
dst_offset = dst_offset + width;
271
}
272
[maskCacheTex.texture replaceRegion:region
273
mipmapLevel:0
274
withBytes:tile
275
bytesPerRow:bytesPerRow];
276
}
277
278
tx1 = ((jfloat) texx) / MTLVC_MASK_CACHE_WIDTH_IN_TEXELS;
279
ty1 = ((jfloat) texy) / MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS;
280
} else {
281
tx1 = ((jfloat)MTLVC_MASK_CACHE_SPECIAL_TILE_X) /
282
MTLVC_MASK_CACHE_WIDTH_IN_TEXELS;
283
ty1 = ((jfloat)MTLVC_MASK_CACHE_SPECIAL_TILE_Y) /
284
MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS;
285
}
286
maskCacheIndex++;
287
288
tx2 = tx1 + (((jfloat)width) / MTLVC_MASK_CACHE_WIDTH_IN_TEXELS);
289
ty2 = ty1 + (((jfloat)height) / MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS);
290
291
dx1 = (jfloat)dstx;
292
dy1 = (jfloat)dsty;
293
dx2 = dx1 + width;
294
dy2 = dy1 + height;
295
296
J2dTraceLn8(J2D_TRACE_INFO, "tx1 = %f ty1 = %f tx2 = %f ty2 = %f dx1 = %f dy1 = %f dx2 = %f dy2 = %f", tx1, ty1, tx2, ty2, dx1, dy1, dx2, dy2);
297
MTLVC_ADD_TRIANGLES(tx1, ty1, tx2, ty2,
298
dx1, dy1, dx2, dy2);
299
}
300
301
void
302
MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
303
jfloat tx1, jfloat ty1, jfloat tx2, jfloat ty2,
304
jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2)
305
{
306
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphQuad");
307
308
if (vertexCacheIndex >= MTLVC_MAX_INDEX)
309
{
310
J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex);
311
MTLVertexCache_FlushGlyphVertexCache();
312
}
313
314
MTLVC_ADD_TRIANGLES(tx1, ty1, tx2, ty2,
315
dx1, dy1, dx2, dy2);
316
}
317
318