1 /* |
|
2 * Copyright (c) 2019, 2019, 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 #ifndef HEADLESS |
|
27 |
|
28 #include <jlong.h> |
|
29 #include <jni_util.h> |
|
30 #include <math.h> |
|
31 #include <Foundation/NSObjCRuntime.h> |
|
32 |
|
33 #include "sun_java2d_metal_MetalRenderer.h" |
|
34 |
|
35 #include "MetalRenderer.h" |
|
36 #include "MetalRenderQueue.h" |
|
37 #include "MetalSurfaceData.h" |
|
38 #import "shaders/MetalShaderTypes.h" |
|
39 #include "Trace.h" |
|
40 #include "MetalLayer.h" |
|
41 #import "VertexDataManager.h" |
|
42 |
|
43 |
|
44 // TODO : Current Color, Gradient etc should have its own class |
|
45 static float drawColor[4] = {0.0, 0.0, 0.0, 0.0}; |
|
46 static int ClipRectangle[4] = {0, 0, 0, 0}; |
|
47 // The current size of our view so we can use this in our render pipeline |
|
48 // static unsigned int viewportSize[2] = {0, 0}; |
|
49 |
|
50 void |
|
51 MetalRenderer_DrawLine(MetalContext *mtlc, jint x1, jint y1, jint x2, jint y2) |
|
52 { |
|
53 //J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawLine"); |
|
54 |
|
55 //RETURN_IF_NULL(mtlc); |
|
56 |
|
57 //CHECK_PREVIOUS_OP(GL_LINES); |
|
58 |
|
59 float P1_X, P1_Y; |
|
60 float P2_X, P2_Y; |
|
61 |
|
62 if (y1 == y2) { |
|
63 // horizontal |
|
64 float fx1 = (float)x1; |
|
65 float fx2 = (float)x2; |
|
66 float fy = ((float)y1) + 0.2f; |
|
67 |
|
68 if (x1 > x2) { |
|
69 float t = fx1; fx1 = fx2; fx2 = t; |
|
70 } |
|
71 |
|
72 P1_X = fx1+0.2f; |
|
73 P1_Y = fy; |
|
74 P2_X = fx2+1.2f; |
|
75 P2_Y = fy; |
|
76 } else if (x1 == x2) { |
|
77 // vertical |
|
78 float fx = ((float)x1) + 0.2f; |
|
79 float fy1 = (float)y1; |
|
80 float fy2 = (float)y2; |
|
81 |
|
82 if (y1 > y2) { |
|
83 float t = fy1; fy1 = fy2; fy2 = t; |
|
84 } |
|
85 |
|
86 P1_X = fx; |
|
87 P1_Y = fy1+0.2f; |
|
88 P2_X = fx; |
|
89 P2_Y = fy2+1.2f; |
|
90 } else { |
|
91 // diagonal |
|
92 float fx1 = (float)x1; |
|
93 float fy1 = (float)y1; |
|
94 float fx2 = (float)x2; |
|
95 float fy2 = (float)y2; |
|
96 |
|
97 if (x1 < x2) { |
|
98 fx1 += 0.2f; |
|
99 fx2 += 1.0f; |
|
100 } else { |
|
101 fx1 += 0.8f; |
|
102 fx2 -= 0.2f; |
|
103 } |
|
104 |
|
105 if (y1 < y2) { |
|
106 fy1 += 0.2f; |
|
107 fy2 += 1.0f; |
|
108 } else { |
|
109 fy1 += 0.8f; |
|
110 fy2 -= 0.2f; |
|
111 } |
|
112 |
|
113 P1_X = fx1; |
|
114 P1_Y = fy1; |
|
115 P2_X = fx2; |
|
116 P2_Y = fy2; |
|
117 } |
|
118 |
|
119 // The (x1, y1) & (x2, y2) are in coordinate system : |
|
120 // Top Left (0, 0) : Bottom Right (width and height) |
|
121 // |
|
122 // Metal rendering coordinate system is : |
|
123 // Top Left (-1.0, 1.0) : Bottom Right (1.0, -1.0) |
|
124 // |
|
125 // This coordinate transformation happens in shader code. |
|
126 |
|
127 MetalVertex lineVertexData[] = |
|
128 { |
|
129 { {P1_X, P1_Y, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} }, |
|
130 { {P2_X, P2_Y, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} } |
|
131 }; |
|
132 |
|
133 //NSLog(@"Drawline ----- x1 : %f, y1 : %f------ x2 : %f, y2 = %f", x1/halfWidth, y1/halfHeight, x2/halfWidth, y2/halfHeight); |
|
134 |
|
135 VertexDataManager_addLineVertexData(lineVertexData[0], lineVertexData[1]); |
|
136 } |
|
137 |
|
138 |
|
139 |
|
140 void |
|
141 MetalRenderer_DrawParallelogram(MetalContext *mtlc, |
|
142 jfloat fx11, jfloat fy11, |
|
143 jfloat dx21, jfloat dy21, |
|
144 jfloat dx12, jfloat dy12, |
|
145 jfloat lwr21, jfloat lwr12) |
|
146 { |
|
147 // dx,dy for line width in the "21" and "12" directions. |
|
148 jfloat ldx21 = dx21 * lwr21; |
|
149 jfloat ldy21 = dy21 * lwr21; |
|
150 jfloat ldx12 = dx12 * lwr12; |
|
151 jfloat ldy12 = dy12 * lwr12; |
|
152 |
|
153 // calculate origin of the outer parallelogram |
|
154 jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f; |
|
155 jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f; |
|
156 |
|
157 /*J2dTraceLn8(J2D_TRACE_INFO, |
|
158 "OGLRenderer_DrawParallelogram " |
|
159 "(x=%6.2f y=%6.2f " |
|
160 "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " |
|
161 "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", |
|
162 fx11, fy11, |
|
163 dx21, dy21, lwr21, |
|
164 dx12, dy12, lwr12);*/ |
|
165 |
|
166 // RETURN_IF_NULL(oglc); |
|
167 |
|
168 // CHECK_PREVIOUS_OP(GL_QUADS); |
|
169 |
|
170 // Only need to generate 4 quads if the interior still |
|
171 // has a hole in it (i.e. if the line width ratio was |
|
172 // less than 1.0) |
|
173 if (lwr21 < 1.0f && lwr12 < 1.0f) { |
|
174 |
|
175 // Note: "TOP", "BOTTOM", "LEFT" and "RIGHT" here are |
|
176 // relative to whether the dxNN variables are positive |
|
177 // and negative. The math works fine regardless of |
|
178 // their signs, but for conceptual simplicity the |
|
179 // comments will refer to the sides as if the dxNN |
|
180 // were all positive. "TOP" and "BOTTOM" segments |
|
181 // are defined by the dxy21 deltas. "LEFT" and "RIGHT" |
|
182 // segments are defined by the dxy12 deltas. |
|
183 |
|
184 // Each segment includes its starting corner and comes |
|
185 // to just short of the following corner. Thus, each |
|
186 // corner is included just once and the only lengths |
|
187 // needed are the original parallelogram delta lengths |
|
188 // and the "line width deltas". The sides will cover |
|
189 // the following relative territories: |
|
190 // |
|
191 // T T T T T R |
|
192 // L R |
|
193 // L R |
|
194 // L R |
|
195 // L R |
|
196 // L B B B B B |
|
197 |
|
198 // TOP segment, to left side of RIGHT edge |
|
199 // "width" of original pgram, "height" of hor. line size |
|
200 fx11 = ox11; |
|
201 fy11 = oy11; |
|
202 FILL_PGRAM(fx11, fy11, dx21, dy21, ldx12, ldy12); |
|
203 |
|
204 // RIGHT segment, to top of BOTTOM edge |
|
205 // "width" of vert. line size , "height" of original pgram |
|
206 fx11 = ox11 + dx21; |
|
207 fy11 = oy11 + dy21; |
|
208 FILL_PGRAM(fx11, fy11, ldx21, ldy21, dx12, dy12); |
|
209 |
|
210 // BOTTOM segment, from right side of LEFT edge |
|
211 // "width" of original pgram, "height" of hor. line size |
|
212 fx11 = ox11 + dx12 + ldx21; |
|
213 fy11 = oy11 + dy12 + ldy21; |
|
214 FILL_PGRAM(fx11, fy11, dx21, dy21, ldx12, ldy12); |
|
215 |
|
216 // LEFT segment, from bottom of TOP edge |
|
217 // "width" of vert. line size , "height" of inner pgram |
|
218 fx11 = ox11 + ldx12; |
|
219 fy11 = oy11 + ldy12; |
|
220 FILL_PGRAM(fx11, fy11, ldx21, ldy21, dx12, dy12); |
|
221 } else { |
|
222 // The line width ratios were large enough to consume |
|
223 // the entire hole in the middle of the parallelogram |
|
224 // so we can just issue one large quad for the outer |
|
225 // parallelogram. |
|
226 dx21 += ldx21; |
|
227 dy21 += ldy21; |
|
228 dx12 += ldx12; |
|
229 dy12 += ldy12; |
|
230 FILL_PGRAM(ox11, oy11, dx21, dy21, dx12, dy12); |
|
231 } |
|
232 } |
|
233 |
|
234 |
|
235 void |
|
236 MetalRenderer_FillParallelogram(MetalContext *mtlc, |
|
237 jfloat fx11, jfloat fy11, |
|
238 jfloat dx21, jfloat dy21, |
|
239 jfloat dx12, jfloat dy12) |
|
240 { |
|
241 /*J2dTraceLn6(J2D_TRACE_INFO, |
|
242 "OGLRenderer_FillParallelogram " |
|
243 "(x=%6.2f y=%6.2f " |
|
244 "dx1=%6.2f dy1=%6.2f " |
|
245 "dx2=%6.2f dy2=%6.2f)", |
|
246 fx11, fy11, |
|
247 dx21, dy21, |
|
248 dx12, dy12); |
|
249 |
|
250 RETURN_IF_NULL(oglc); |
|
251 |
|
252 CHECK_PREVIOUS_OP(GL_QUADS);*/ |
|
253 |
|
254 FILL_PGRAM(fx11, fy11, dx21, dy21, dx12, dy12); |
|
255 } |
|
256 |
|
257 |
|
258 void FILL_PGRAM(float fx11, float fy11, float dx21, float dy21, float dx12, float dy12) { |
|
259 |
|
260 MetalRenderer_DrawQuad(fx11, fy11, |
|
261 fx11 + dx21, fy11 + dy21, |
|
262 fx11 + dx21 + dx12, fy11 + dy21 + dy12, |
|
263 fx11 + dx12, fy11 + dy12); |
|
264 } |
|
265 |
|
266 |
|
267 |
|
268 void MetalRenderer_DrawQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) { |
|
269 |
|
270 // Draw two triangles with given 4 vertices |
|
271 |
|
272 // The (x1, y1) & (x2, y2) are in coordinate system : |
|
273 // Top Left (0, 0) : Bottom Right (width and height) |
|
274 // |
|
275 // Metal rendering coordinate system is : |
|
276 // Top Left (-1.0, 1.0) : Bottom Right (1.0, -1.0) |
|
277 // |
|
278 // This coordinate transformation happens in shader code. |
|
279 |
|
280 MetalVertex QuadVertexData[] = |
|
281 { |
|
282 { {x1, y1, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} }, |
|
283 { {x2, y2, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} }, |
|
284 { {x3, y3, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} }, |
|
285 { {x4, y4, 0.0, 1.0}, {drawColor[0], drawColor[1], drawColor[2], drawColor[3]} }, |
|
286 }; |
|
287 |
|
288 VertexDataManager_addQuadVertexData(QuadVertexData[0], QuadVertexData[1], QuadVertexData[2], QuadVertexData[3]); |
|
289 } |
|
290 |
|
291 |
|
292 void MetalRenderer_SetColor(MetalContext *mtlc, jint color) { |
|
293 //J2dTraceLn(J2D_TRACE_INFO, "MetalRenderer_SetColor"); |
|
294 unsigned char r = (unsigned char)(color >> 16); |
|
295 unsigned char g = (unsigned char)(color >> 8); |
|
296 unsigned char b = (unsigned char)(color >> 0); |
|
297 unsigned char a = 0xff; |
|
298 |
|
299 drawColor[0] = r/255.0; |
|
300 drawColor[1] = g/255.0; |
|
301 drawColor[2] = b/255.0; |
|
302 drawColor[3] = 1.0; |
|
303 |
|
304 NSLog(@"MetalRenderer SetColor ----- (%d, %d, %d, %d)", r, g, b, a); |
|
305 } |
|
306 |
|
307 |
|
308 void MetalRenderer_DrawRect(MetalContext *mtlc, |
|
309 jint x, jint y, jint w, jint h) { |
|
310 //J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawRect"); |
|
311 |
|
312 if (w < 0 || h < 0) { |
|
313 return; |
|
314 } |
|
315 |
|
316 //RETURN_IF_NULL(oglc); |
|
317 |
|
318 if (w < 2 || h < 2) { |
|
319 // If one dimension is less than 2 then there is no |
|
320 // gap in the middle - draw a solid filled rectangle. |
|
321 //CHECK_PREVIOUS_OP(GL_QUADS); |
|
322 //GLRECT_BODY_XYWH(x, y, w+1, h+1); |
|
323 MetalRenderer_FillRect(mtlc, x, y, w+1, h+1); |
|
324 } else { |
|
325 jint fx1 = (jint) (((float)x) + 0.2f); |
|
326 jint fy1 = (jint) (((float)y) + 0.2f); |
|
327 jint fx2 = fx1 + w; |
|
328 jint fy2 = fy1 + h; |
|
329 |
|
330 // Avoid drawing the endpoints twice. |
|
331 // Also prefer including the endpoints in the |
|
332 // horizontal sections which draw pixels faster. |
|
333 |
|
334 // top |
|
335 MetalRenderer_DrawLine(mtlc, fx1, fy1, fx2+1, fy1); |
|
336 |
|
337 // right |
|
338 MetalRenderer_DrawLine(mtlc, fx2, fy1+1, fx2, fy2); |
|
339 |
|
340 // bottom |
|
341 MetalRenderer_DrawLine(mtlc, fx1, fy2, fx2+1, fy2); |
|
342 |
|
343 |
|
344 // left |
|
345 MetalRenderer_DrawLine(mtlc, fx1, fy1+1, fx1, fy2); |
|
346 } |
|
347 } |
|
348 |
|
349 |
|
350 void |
|
351 MetalRenderer_FillRect(MetalContext *mtlc, jint x, jint y, jint w, jint h) |
|
352 { |
|
353 //J2dTraceLn(J2D_TRACE_INFO, "MetalRenderer_FillRect"); |
|
354 |
|
355 if (w <= 0 || h <= 0) { |
|
356 return; |
|
357 } |
|
358 |
|
359 //RETURN_IF_NULL(oglc); |
|
360 |
|
361 //CHECK_PREVIOUS_OP(GL_QUADS); |
|
362 //GLRECT_BODY_XYWH(x, y, w, h); |
|
363 |
|
364 |
|
365 MetalRenderer_DrawQuad(x, y, x, y+h, x+w, y+h, x+w, y); |
|
366 |
|
367 //NSLog(@"MetalRenderer_FillRect: X, Y(%f, %f) with width, height(%f, %f)", (float)x, (float)y, (float)w, (float)h); |
|
368 } |
|
369 |
|
370 // TODO : I think, this should go to metal context |
|
371 void MetalRenderer_SetRectClip(MetalContext *mtlc, jint x1, jint y1, jint x2, jint y2) { |
|
372 |
|
373 jint width = x2 - x1; |
|
374 jint height = y2 - y1; |
|
375 |
|
376 J2dTraceLn4(J2D_TRACE_INFO, |
|
377 "MetalRenderer_SetRectClip: x=%d y=%d w=%d h=%d", |
|
378 x1, y1, width, height); |
|
379 |
|
380 //RETURN_IF_NULL(dstOps); |
|
381 //RETURN_IF_NULL(oglc); |
|
382 //CHECK_PREVIOUS_OP(OGL_STATE_CHANGE); |
|
383 |
|
384 if ((width < 0) || (height < 0)) { |
|
385 // use an empty scissor rectangle when the region is empty |
|
386 width = 0; |
|
387 height = 0; |
|
388 } |
|
389 |
|
390 //j2d_glDisable(GL_DEPTH_TEST); |
|
391 //j2d_glEnable(GL_SCISSOR_TEST); |
|
392 |
|
393 // the scissor rectangle is specified using the lower-left |
|
394 // origin of the clip region (in the framebuffer's coordinate |
|
395 // space), so we must account for the x/y offsets of the |
|
396 // destination surface |
|
397 /*j2d_glScissor(dstOps->xOffset + x1, |
|
398 dstOps->yOffset + dstOps->height - (y1 + height), |
|
399 width, height);*/ |
|
400 |
|
401 MetalSDOps *dstOps = MetalRenderQueue_GetCurrentDestination(); |
|
402 |
|
403 ClipRectangle[0] = x1;//dstOps->xOffset + x1; |
|
404 ClipRectangle[1] = y1;//dstOps->yOffset + dstOps->height - (y1 + height); |
|
405 ClipRectangle[2] = width; |
|
406 ClipRectangle[3] = height; |
|
407 |
|
408 } |
|
409 |
|
410 void MetalRenderer_Flush() { |
|
411 |
|
412 MetalSDOps* dstOps = MetalRenderQueue_GetCurrentDestination(); |
|
413 MetalLayer* mtlLayer = dstOps->layer; |
|
414 |
|
415 unsigned int viewportSize[2] = {mtlLayer.textureWidth, mtlLayer.textureHeight}; |
|
416 |
|
417 //Create a render pass descriptor |
|
418 MTLRenderPassDescriptor* mtlRenderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; |
|
419 |
|
420 //Set the SurfaceData offscreen texture as target texture for the rendering pipeline |
|
421 mtlRenderPassDescriptor.colorAttachments[0].texture = dstOps->mtlTexture; |
|
422 |
|
423 mtlRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; |
|
424 mtlRenderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.8, 0.8, 0.8, 1.0); |
|
425 mtlRenderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; |
|
426 |
|
427 id<MTLCommandBuffer> mtlCommandBuffer = [dstOps->configInfo->commandQueue commandBuffer]; |
|
428 id<MTLRenderCommandEncoder> renderEncoder = [mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlRenderPassDescriptor]; |
|
429 |
|
430 // Configure render enconder with the pipeline state |
|
431 [renderEncoder setRenderPipelineState:mtlLayer.renderPipelineState]; |
|
432 |
|
433 // Whatever outside this rectangle won't be drawn |
|
434 // TODO : ClipRectangle should be part of MetalContext or some state maintaining class |
|
435 NSLog(@"Setting Rect Clip : %d, %d, %d, %d", ClipRectangle[0], ClipRectangle[1], ClipRectangle[2], ClipRectangle[3]); |
|
436 MTLScissorRect clip = {ClipRectangle[0], ClipRectangle[1], ClipRectangle[2], ClipRectangle[3]}; |
|
437 [renderEncoder setScissorRect:clip]; |
|
438 |
|
439 // --------------------------------------------------------- |
|
440 // DRAW primitives from VertexDataManager |
|
441 // --------------------------------------------------------- |
|
442 [renderEncoder setVertexBuffer:VertexDataManager_getVertexBuffer() offset:0 atIndex:0]; // 0th index |
|
443 |
|
444 [renderEncoder setVertexBytes: &viewportSize |
|
445 length: sizeof(viewportSize) |
|
446 atIndex: 1]; // 1st index |
|
447 |
|
448 MetalPrimitiveData** allPrimitives = VertexDataManager_getAllPrimitives(); |
|
449 |
|
450 int totalPrimitives = VertexDataManager_getNoOfPrimitives(); |
|
451 for (int i = 0; i < totalPrimitives; i++ ) { |
|
452 MetalPrimitiveData* p = allPrimitives[i]; |
|
453 |
|
454 NSLog(@"----------------------------------------------"); |
|
455 NSLog(@"Encoding primitive %d", i); |
|
456 NSLog(@"indexCount %d", p->no_of_indices); |
|
457 NSLog(@"indexBufferOffset %d", p->offset_in_index_buffer); |
|
458 NSLog(@"primitiveInstances %d", p->primitiveInstances); |
|
459 NSLog(@"----------------------------------------------"); |
|
460 |
|
461 |
|
462 [renderEncoder drawIndexedPrimitives: p->type |
|
463 indexCount: (NSUInteger)p->no_of_indices |
|
464 indexType: (MTLIndexType)MTLIndexTypeUInt16 |
|
465 indexBuffer: (id<MTLBuffer>)VertexDataManager_getIndexBuffer() |
|
466 indexBufferOffset: (NSUInteger)p->offset_in_index_buffer |
|
467 instanceCount: (NSUInteger)p->primitiveInstances]; |
|
468 } |
|
469 |
|
470 //-------------------------------------------------- |
|
471 |
|
472 [renderEncoder endEncoding]; |
|
473 |
|
474 [mtlCommandBuffer commit]; |
|
475 |
|
476 [mtlCommandBuffer waitUntilCompleted]; |
|
477 } |
|
478 |
|
479 |
|
480 void MetalRenderer_blitToScreenDrawable() { |
|
481 |
|
482 MetalSDOps* dstOps = MetalRenderQueue_GetCurrentDestination(); |
|
483 MetalLayer* mtlLayer = dstOps->layer; |
|
484 |
|
485 @autoreleasepool { |
|
486 id <CAMetalDrawable> frameDrawable = [mtlLayer nextDrawable]; |
|
487 |
|
488 id<MTLCommandBuffer> commandBuffer = [dstOps->configInfo->commandQueue commandBuffer]; |
|
489 |
|
490 id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder]; |
|
491 |
|
492 //[blitEncoder synchronizeResource:_texture]; |
|
493 |
|
494 [blitEncoder copyFromTexture:dstOps->mtlTexture |
|
495 sourceSlice:0 |
|
496 sourceLevel:0 |
|
497 sourceOrigin:MTLOriginMake(ClipRectangle[0], ClipRectangle[1], 0) |
|
498 sourceSize:MTLSizeMake(dstOps->mtlTexture.width - ClipRectangle[0], dstOps->mtlTexture.height - ClipRectangle[1], 1) |
|
499 toTexture:frameDrawable.texture |
|
500 destinationSlice:0 |
|
501 destinationLevel:0 |
|
502 destinationOrigin:MTLOriginMake(0, 0, 0)]; |
|
503 |
|
504 [blitEncoder endEncoding]; |
|
505 |
|
506 [commandBuffer presentDrawable:frameDrawable]; |
|
507 |
|
508 [commandBuffer commit]; |
|
509 |
|
510 [commandBuffer waitUntilCompleted]; |
|
511 } |
|
512 } |
|
513 |
|
514 #endif |
|