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/MTLClip.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 "MTLClip.h"
27
28
#include "MTLContext.h"
29
#include "MTLStencilManager.h"
30
#include "common.h"
31
32
static MTLRenderPipelineDescriptor * templateStencilPipelineDesc = nil;
33
34
static void initTemplatePipelineDescriptors() {
35
if (templateStencilPipelineDesc != nil)
36
return;
37
38
MTLVertexDescriptor *vertDesc = [[MTLVertexDescriptor new] autorelease];
39
vertDesc.attributes[VertexAttributePosition].format = MTLVertexFormatFloat2;
40
vertDesc.attributes[VertexAttributePosition].offset = 0;
41
vertDesc.attributes[VertexAttributePosition].bufferIndex = MeshVertexBuffer;
42
vertDesc.layouts[MeshVertexBuffer].stride = sizeof(struct Vertex);
43
vertDesc.layouts[MeshVertexBuffer].stepRate = 1;
44
vertDesc.layouts[MeshVertexBuffer].stepFunction = MTLVertexStepFunctionPerVertex;
45
46
templateStencilPipelineDesc = [MTLRenderPipelineDescriptor new];
47
templateStencilPipelineDesc.sampleCount = 1;
48
templateStencilPipelineDesc.vertexDescriptor = vertDesc;
49
templateStencilPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatR8Uint; // A byte buffer format
50
templateStencilPipelineDesc.stencilAttachmentPixelFormat = MTLPixelFormatStencil8;
51
templateStencilPipelineDesc.label = @"template_stencil";
52
}
53
54
@implementation MTLClip {
55
jint _clipType;
56
MTLScissorRect _clipRect;
57
MTLContext* _mtlc;
58
BMTLSDOps* _dstOps;
59
BOOL _stencilMaskGenerationInProgress;
60
BOOL _stencilMaskGenerationStarted;
61
BOOL _clipReady;
62
MTLOrigin _clipShapeOrigin;
63
MTLSize _clipShapeSize;
64
}
65
66
@synthesize dstOps = _dstOps;
67
68
- (id)init {
69
self = [super init];
70
if (self) {
71
_clipType = NO_CLIP;
72
_mtlc = nil;
73
_dstOps = NULL;
74
_stencilMaskGenerationInProgress = NO;
75
_stencilMaskGenerationStarted = NO;
76
_clipReady = NO;
77
}
78
return self;
79
}
80
81
- (BOOL)isEqual:(MTLClip *)other {
82
if (self == other)
83
return YES;
84
if (_stencilMaskGenerationInProgress == JNI_TRUE)
85
return other->_stencilMaskGenerationInProgress == JNI_TRUE;
86
if (_clipType != other->_clipType)
87
return NO;
88
if (_clipType == NO_CLIP)
89
return YES;
90
if (_clipType == RECT_CLIP) {
91
return _clipRect.x == other->_clipRect.x && _clipRect.y == other->_clipRect.y
92
&& _clipRect.width == other->_clipRect.width && _clipRect.height == other->_clipRect.height;
93
}
94
95
// NOTE: can compare stencil-data pointers here
96
return YES;
97
}
98
99
- (BOOL)isShape {
100
return _clipType == SHAPE_CLIP;
101
}
102
103
- (BOOL)isRect __unused {
104
return _clipType == RECT_CLIP;
105
}
106
107
- (const MTLScissorRect * _Nullable) getRect {
108
return _clipType == RECT_CLIP ? &_clipRect : NULL;
109
}
110
111
- (void)copyFrom:(MTLClip *)other {
112
_clipType = other->_clipType;
113
_stencilMaskGenerationInProgress = other->_stencilMaskGenerationInProgress;
114
_dstOps = other->_dstOps;
115
_mtlc = other->_mtlc;
116
if (other->_clipType == RECT_CLIP) {
117
_clipRect = other->_clipRect;
118
}
119
}
120
121
- (void)reset {
122
_clipType = NO_CLIP;
123
_stencilMaskGenerationInProgress = JNI_FALSE;
124
}
125
126
127
- (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 {
128
if (_clipType == SHAPE_CLIP) {
129
_dstOps = NULL;
130
}
131
132
if (x1 >= x2 || y1 >= y2) {
133
J2dTraceLn4(J2D_TRACE_ERROR, "MTLClip.setClipRect: invalid rect: x1=%d y1=%d x2=%d y2=%d", x1, y1, x2, y2);
134
_clipType = NO_CLIP;
135
}
136
137
const jint width = x2 - x1;
138
const jint height = y2 - y1;
139
140
J2dTraceLn4(J2D_TRACE_INFO, "MTLClip.setClipRect: x=%d y=%d w=%d h=%d", x1, y1, width, height);
141
142
_clipRect.x = (NSUInteger)((x1 >= 0) ? x1 : 0);
143
_clipRect.y = (NSUInteger)((y1 >= 0) ? y1 : 0);
144
_clipRect.width = (NSUInteger)((width >= 0) ? width : 0);
145
_clipRect.height = (NSUInteger)((height >= 0) ? height : 0);
146
_clipType = RECT_CLIP;
147
}
148
149
- (void)beginShapeClip:(BMTLSDOps *)dstOps context:(MTLContext *)mtlc {
150
_stencilMaskGenerationInProgress = YES;
151
_mtlc = mtlc;
152
if ((dstOps == NULL) || (dstOps->pStencilData == NULL) || (dstOps->pStencilTexture == NULL)) {
153
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_beginShapeClip: stencil render target or stencil texture is NULL");
154
return;
155
}
156
157
// Clear the stencil render buffer & stencil texture
158
@autoreleasepool {
159
if (dstOps->width <= 0 || dstOps->height <= 0) {
160
return;
161
}
162
163
_clipShapeSize = MTLSizeMake(0, 0, 1);
164
// Use out of bounds origin to correctly calculate shape boundaries
165
_clipShapeOrigin = MTLOriginMake((NSUInteger) dstOps->width, (NSUInteger) dstOps->height, 0);
166
_dstOps = dstOps;
167
}
168
}
169
170
- (void)endShapeClip:(BMTLSDOps *)dstOps context:(MTLContext *)mtlc {
171
172
if ((dstOps == NULL) || (dstOps->pStencilData == NULL) || (dstOps->pStencilTexture == NULL)) {
173
J2dRlsTraceLn(J2D_TRACE_ERROR, "MTLContext_endShapeClip: stencil render target or stencil texture is NULL");
174
return;
175
}
176
177
// Complete the rendering to the stencil buffer ------------
178
[mtlc.encoderManager endEncoder];
179
180
MTLCommandBufferWrapper* cbWrapper = [mtlc pullCommandBufferWrapper];
181
182
id<MTLCommandBuffer> commandBuffer = [cbWrapper getCommandBuffer];
183
[commandBuffer addCompletedHandler:^(id <MTLCommandBuffer> c) {
184
[cbWrapper release];
185
}];
186
187
[commandBuffer commit];
188
_stencilMaskGenerationInProgress = NO;
189
_stencilMaskGenerationStarted = NO;
190
_dstOps = dstOps;
191
_clipType = SHAPE_CLIP;
192
_clipReady = NO;
193
}
194
195
- (void)setMaskGenerationPipelineState:(id<MTLRenderCommandEncoder>)encoder
196
destWidth:(NSUInteger)dw
197
destHeight:(NSUInteger)dh
198
pipelineStateStorage:(MTLPipelineStatesStorage *)pipelineStateStorage
199
{
200
initTemplatePipelineDescriptors();
201
202
// A PipelineState for rendering to a byte-buffered texture that will be used as a stencil
203
id <MTLRenderPipelineState> pipelineState = [pipelineStateStorage getPipelineState:templateStencilPipelineDesc
204
vertexShaderId:@"vert_stencil"
205
fragmentShaderId:@"frag_stencil"
206
stencilNeeded:YES];
207
[encoder setRenderPipelineState:pipelineState];
208
209
struct FrameUniforms uf; // color is ignored while writing to stencil buffer
210
memset(&uf, 0, sizeof(uf));
211
[encoder setVertexBytes:&uf length:sizeof(uf) atIndex:FrameUniformBuffer];
212
213
_clipRect.x = 0;
214
_clipRect.y = 0;
215
_clipRect.width = dw;
216
_clipRect.height = dh;
217
218
[encoder setDepthStencilState: _mtlc.stencilManager.genStencilState];
219
[encoder setStencilReferenceValue:255];
220
[encoder setScissorRect:_clipRect]; // just for insurance (to reset possible clip from previous drawing)
221
}
222
223
- (void)setScissorOrStencil:(id<MTLRenderCommandEncoder>)encoder
224
destWidth:(NSUInteger)dw
225
destHeight:(NSUInteger)dh
226
device:(id<MTLDevice>)device
227
{
228
if (_clipType == NO_CLIP || _clipType == SHAPE_CLIP) {
229
_clipRect.x = 0;
230
_clipRect.y = 0;
231
_clipRect.width = dw;
232
_clipRect.height = dh;
233
}
234
235
// Clamping clip rect to the destination area
236
MTLScissorRect rect = _clipRect;
237
238
if (rect.x > dw) {
239
rect.x = dw;
240
}
241
242
if (rect.y > dh) {
243
rect.y = dh;
244
}
245
246
if (rect.x + rect.width > dw) {
247
rect.width = dw - rect.x;
248
}
249
250
if (rect.y + rect.height > dh) {
251
rect.height = dh - rect.y;
252
}
253
254
[encoder setScissorRect:rect];
255
if (_clipType == NO_CLIP || _clipType == RECT_CLIP) {
256
// NOTE: It seems that we can use the same encoder (with disabled stencil test) when mode changes from SHAPE to RECT.
257
// But [encoder setDepthStencilState:nil] causes crash, so we have to recreate encoder in such case.
258
// So we can omit [encoder setDepthStencilState:nil] here.
259
return;
260
}
261
262
if (_clipType == SHAPE_CLIP) {
263
// Enable stencil test
264
[encoder setDepthStencilState:_mtlc.stencilManager.stencilState];
265
[encoder setStencilReferenceValue:0xFF];
266
}
267
}
268
269
- (NSString *)getDescription __unused {
270
if (_clipType == NO_CLIP) {
271
return @"NO_CLIP";
272
}
273
if (_clipType == RECT_CLIP) {
274
return [NSString stringWithFormat:@"RECT_CLIP [%lu,%lu - %lux%lu]", _clipRect.x, _clipRect.y, _clipRect.width, _clipRect.height];
275
}
276
return [NSString stringWithFormat:@"SHAPE_CLIP"];
277
}
278
279
- (id<MTLTexture>) stencilTextureRef {
280
if (_dstOps == NULL) return nil;
281
282
return _dstOps->pStencilTexture;;
283
}
284
285
- (NSUInteger)shapeX {
286
return _clipShapeOrigin.x;
287
}
288
289
- (void)setShapeX:(NSUInteger)shapeX {
290
_clipShapeOrigin.x = shapeX;
291
}
292
293
- (NSUInteger)shapeY {
294
return _clipShapeOrigin.y;
295
}
296
297
- (void)setShapeY:(NSUInteger)shapeY {
298
_clipShapeOrigin.y = shapeY;
299
}
300
301
- (NSUInteger)shapeWidth {
302
return _clipShapeSize.width;
303
}
304
305
- (void)setShapeWidth:(NSUInteger)shapeWidth {
306
_clipShapeSize.width = shapeWidth;
307
}
308
309
- (NSUInteger)shapeHeight {
310
return _clipShapeSize.height;
311
}
312
313
- (void)setShapeHeight:(NSUInteger)shapeHeight {
314
_clipShapeSize.height = shapeHeight;
315
}
316
317
318
@end
319
320