57 v->position[0]= DX; \ |
55 v->position[0]= DX; \ |
58 v->position[1] = DY; \ |
56 v->position[1] = DY; \ |
59 v->position[2] = DZ; \ |
57 v->position[2] = DZ; \ |
60 } while (0) |
58 } while (0) |
61 |
59 |
62 #define MTLVC_ADD_TRIANGLES(DX1, DY1, DX2, DY2) \ |
60 #define MTLVC_ADD_TRIANGLES(TX1, TY1, TX2, TY2, DX1, DY1, DX2, DY2) \ |
63 do { \ |
61 do { \ |
64 MTLVC_ADD_VERTEX(0, 0, DX1, DY1, 0); \ |
62 MTLVC_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \ |
65 MTLVC_ADD_VERTEX(1, 0, DX2, DY1, 0); \ |
63 MTLVC_ADD_VERTEX(TX2, TY1, DX2, DY1, 0); \ |
66 MTLVC_ADD_VERTEX(1, 1, DX2, DY2, 0); \ |
64 MTLVC_ADD_VERTEX(TX2, TY2, DX2, DY2, 0); \ |
67 MTLVC_ADD_VERTEX(1, 1, DX2, DY2, 0); \ |
65 MTLVC_ADD_VERTEX(TX2, TY2, DX2, DY2, 0); \ |
68 MTLVC_ADD_VERTEX(0, 1, DX1, DY2, 0); \ |
66 MTLVC_ADD_VERTEX(TX1, TY2, DX1, DY2, 0); \ |
69 MTLVC_ADD_VERTEX(0, 0, DX1, DY1, 0); \ |
67 MTLVC_ADD_VERTEX(TX1, TY1, DX1, DY1, 0); \ |
70 } while (0) |
68 } while (0) |
71 |
69 |
72 jboolean |
70 jboolean |
73 MTLVertexCache_InitVertexCache() |
71 MTLVertexCache_InitVertexCache() |
74 { |
72 { |
88 MTLVertexCache_FlushVertexCache(MTLContext *mtlc) |
86 MTLVertexCache_FlushVertexCache(MTLContext *mtlc) |
89 { |
87 { |
90 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache"); |
88 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache"); |
91 |
89 |
92 if (vertexCacheIndex > 0 || |
90 if (vertexCacheIndex > 0 || |
93 texturePoolIndex > 0) { |
91 maskCacheIndex > 0) { |
94 id<MTLBuffer>vertexBuffer = [mtlc.device newBufferWithBytes:vertexCache |
92 id<MTLBuffer>vertexBuffer = [mtlc.device newBufferWithBytes:vertexCache |
95 length:vertexCacheIndex * sizeof(J2DVertex) |
93 length:vertexCacheIndex * sizeof(J2DVertex) |
96 options:MTLResourceOptionCPUCacheModeDefault]; |
94 options:MTLResourceOptionCPUCacheModeDefault]; |
97 [encoder setVertexBuffer:vertexBuffer offset:0 atIndex:MeshVertexBuffer]; |
95 [encoder setVertexBuffer:vertexBuffer offset:0 atIndex:MeshVertexBuffer]; |
98 for (int i = 0; i < texturePoolIndex; i++) { |
96 for (int i = 0; i < maskCacheIndex; i++) { |
99 J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache : draw texture at index %d", i); |
97 J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache : draw texture at index %d", i); |
100 [encoder setFragmentTexture:texturePool[i] atIndex: 0]; |
98 [encoder setFragmentTexture:maskCacheTex atIndex: 0]; |
101 [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:i*6 vertexCount:6]; |
99 [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:i*6 vertexCount:6]; |
102 } |
100 } |
103 [encoder endEncoding]; |
101 [encoder endEncoding]; |
104 } |
102 } |
105 vertexCacheIndex = 0; |
103 vertexCacheIndex = 0; |
106 texturePoolIndex = 0; |
104 maskCacheIndex = 0; |
|
105 encoder = NULL; |
|
106 maskCacheTex = NULL; |
107 } |
107 } |
108 |
108 |
109 /** |
109 /** |
110 * This method is somewhat hacky, but necessary for the foreseeable future. |
110 * This method is somewhat hacky, but necessary for the foreseeable future. |
111 * The problem is the way OpenGL handles color values in vertex arrays. When |
111 * The problem is the way OpenGL handles color values in vertex arrays. When |
168 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_DisableMaskCache"); |
178 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_DisableMaskCache"); |
169 maskCacheIndex = 0; |
179 maskCacheIndex = 0; |
170 } |
180 } |
171 |
181 |
172 void |
182 void |
173 MTLVertexCache_AddVertexTriangles(jfloat dx1, jfloat dy1, |
183 MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps) { |
174 jfloat dx2, jfloat dy2) |
184 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_CreateSamplingEncoder"); |
175 { |
185 encoder = [mtlc createSamplingEncoderForDest:dstOps->pTexture]; |
176 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddVertexTriangles"); |
186 } |
177 MTLVC_ADD_TRIANGLES(dx1, dy1, dx2, dy2); |
187 |
178 } |
188 void |
179 |
189 MTLVertexCache_AddMaskQuad(MTLContext *mtlc, |
180 void |
190 jint srcx, jint srcy, |
181 MTLVertexCache_AddGlyphTexture(MTLContext *mtlc, |
191 jint dstx, jint dsty, |
182 jint width, jint height, |
192 jint width, jint height, |
183 GlyphInfo *ginfo, |
193 jint maskscan, void *mask, |
184 BMTLSDOps *dstOps) |
194 BMTLSDOps *dstOps, |
185 { |
195 jint fullwidth) |
186 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphTexture"); |
196 { |
187 J2dTraceLn2(J2D_TRACE_INFO, "Glyph width = %d Glyph height = %d", width, height); |
197 jfloat tx1, ty1, tx2, ty2; |
188 if (texturePoolIndex >= MTLVC_MAX_TEX_INDEX || |
198 jfloat dx1, dy1, dx2, dy2; |
|
199 |
|
200 J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_AddMaskQuad: %d", |
|
201 maskCacheIndex); |
|
202 |
|
203 if (maskCacheIndex >= MTLVC_MASK_CACHE_MAX_INDEX || |
189 vertexCacheIndex >= MTLVC_MAX_INDEX) |
204 vertexCacheIndex >= MTLVC_MAX_INDEX) |
190 { |
205 { |
191 MTLVertexCache_FlushVertexCache(mtlc); |
206 MTLVertexCache_FlushVertexCache(mtlc); |
192 MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps); |
207 MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps); |
193 } |
208 // TODO : Since we are not committing command buffer |
194 MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatA8Unorm width:width height:height mipmapped:NO]; |
209 // in FlushVertexCache we need to create new maskcache |
195 id <MTLTexture> texture = [mtlc.device newTextureWithDescriptor:textureDescriptor]; |
210 // after present cache is full. Check whether we can |
196 J2dTraceLn3(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphTexture: created texture: tex=%p, w=%d h=%d", texture, width, height); |
211 // avoid multiple cache creation. |
|
212 MTLVertexCache_EnableMaskCache(mtlc); |
|
213 } |
|
214 |
|
215 // TODO : Implement mask == null use case also |
|
216 jint texx = MTLVC_MASK_CACHE_TILE_WIDTH * |
|
217 (maskCacheIndex % MTLVC_MASK_CACHE_WIDTH_IN_TILES); |
|
218 jint texy = MTLVC_MASK_CACHE_TILE_HEIGHT * |
|
219 (maskCacheIndex / MTLVC_MASK_CACHE_WIDTH_IN_TILES); |
|
220 J2dTraceLn5(J2D_TRACE_INFO, "texx = %d texy = %d width = %d height = %d fullwidth = %d", texx, texy, width, height, fullwidth); |
197 NSUInteger bytesPerRow = 1 * width; |
221 NSUInteger bytesPerRow = 1 * width; |
198 |
222 NSUInteger slice = bytesPerRow * srcy + srcx; |
199 MTLRegion region = { |
223 MTLRegion region = { |
200 { 0, 0, 0 }, |
224 {texx, texy, 0 }, |
201 {width, height, 1} |
225 {width, height, 1} |
202 }; |
226 }; |
203 [texture replaceRegion:region |
227 |
204 mipmapLevel:0 |
228 // Whenever we have source stride bigger that destination stride |
205 withBytes:ginfo->image |
229 // we need to pick appropriate source subtexture. In repalceRegion |
206 bytesPerRow:bytesPerRow]; |
230 // we can give destination subtexturing properly but we can't |
207 texturePool[texturePoolIndex] = texture; |
231 // subtexture from system memory glyph we have. So in such |
208 texturePoolIndex++; |
232 // cases we are creating seperate tile and scan the source |
209 } |
233 // stride into destination using memcpy. In case of OpenGL we |
210 |
234 // can update source pointers, in case of D3D we ar doing memcpy. |
211 void |
235 // We can use MTLBuffer and then copy source subtexture but that |
212 MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps) { |
236 // adds extra blitting logic. |
213 J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_CreateSamplingEncoder"); |
237 // TODO : Research more and try removing memcpy logic. |
214 encoder = [mtlc createSamplingEncoderForDest:dstOps->pTexture]; |
238 if (fullwidth <= width) { |
|
239 int height_offset = bytesPerRow * srcy; |
|
240 [maskCacheTex replaceRegion:region |
|
241 mipmapLevel:0 |
|
242 withBytes:mask + height_offset |
|
243 bytesPerRow:bytesPerRow]; |
|
244 } else { |
|
245 int dst_offset, src_offset; |
|
246 int size = 1 * width * height; |
|
247 void* tile = malloc(size); |
|
248 dst_offset = 0; |
|
249 for (int i = srcy ; i < srcy + height; i++) { |
|
250 J2dTraceLn2(J2D_TRACE_INFO, "srcx = %d srcy = %d", srcx, srcy); |
|
251 src_offset = fullwidth * i + srcx; |
|
252 J2dTraceLn2(J2D_TRACE_INFO, "src_offset = %d dst_offset = %d", src_offset, dst_offset); |
|
253 memcpy(tile + dst_offset, mask + src_offset, width); |
|
254 dst_offset = dst_offset + width; |
|
255 } |
|
256 [maskCacheTex replaceRegion:region |
|
257 mipmapLevel:0 |
|
258 withBytes:tile |
|
259 bytesPerRow:bytesPerRow]; |
|
260 } |
|
261 |
|
262 tx1 = ((jfloat)texx) / MTLVC_MASK_CACHE_WIDTH_IN_TEXELS; |
|
263 ty1 = ((jfloat)texy) / MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS; |
|
264 |
|
265 maskCacheIndex++; |
|
266 |
|
267 tx2 = tx1 + (((jfloat)width) / MTLVC_MASK_CACHE_WIDTH_IN_TEXELS); |
|
268 ty2 = ty1 + (((jfloat)height) / MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS); |
|
269 |
|
270 dx1 = (jfloat)dstx; |
|
271 dy1 = (jfloat)dsty; |
|
272 dx2 = dx1 + width; |
|
273 dy2 = dy1 + height; |
|
274 |
|
275 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); |
|
276 MTLVC_ADD_TRIANGLES(tx1, ty1, tx2, ty2, |
|
277 dx1, dy1, dx2, dy2); |
215 } |
278 } |
216 |
279 |
217 #endif /* !HEADLESS */ |
280 #endif /* !HEADLESS */ |