Initial implementation of vertex cache for text rendering metal-prototype-branch
authorjdv
Tue, 25 Jun 2019 16:21:42 +0530
branchmetal-prototype-branch
changeset 57426 68ec5c5ae381
parent 57424 a327727090c7
child 57429 6c1c6874a144
Initial implementation of vertex cache for text rendering
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.h
src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m	Tue Jun 25 15:24:41 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m	Tue Jun 25 16:21:42 2019 +0530
@@ -321,8 +321,8 @@
 
     J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawGrayscaleGlyphNoCache");
     /*
-     * TODO : We dont have vertex cache implementation or
-     * mask cache as we have in OpenGL. That needs to be done.
+     * TODO : Glyph caching is not used yet we need to
+     * implement it.
      */
     if (glyphMode != MODE_NO_CACHE_GRAY) {
         glyphMode = MODE_NO_CACHE_GRAY;
@@ -332,59 +332,10 @@
     dy1 = (jfloat)y;
     dx2 = x + width;
     dy2 = y + height;
-    printf("Destination coordinates dx1 = %f dy1 = %f dx2 = %f dy2 = %f \n", dx1, dy1, dx2, dy2);fflush(stdout);
-    id<MTLTexture> texture = [mtlc.texturePool getTexture:width height:height format:MTLPixelFormatA8Unorm];
-    NSUInteger bytesPerRow = 1 * width;
-
-    MTLRegion region = {
-        { 0, 0, 0 },
-        {width, height, 1}
-    };
-    [texture replaceRegion:region
-             mipmapLevel:0
-             withBytes:ginfo->image
-             bytesPerRow:bytesPerRow];
-    id<MTLRenderCommandEncoder> encoder = [mtlc createSamplingEncoderForDest:dstOps->pTexture];
-    struct TxtVertex txQuadVerts[6];
-    txQuadVerts[0].position[0] = dx1;
-    txQuadVerts[0].position[1] = dy1;
-    txQuadVerts[0].position[2] = 0;
-    txQuadVerts[0].txtpos[0]   = 0;
-    txQuadVerts[0].txtpos[1]   = 0;
-
-    txQuadVerts[1].position[0] = dx2;
-    txQuadVerts[1].position[1] = dy1;
-    txQuadVerts[1].position[2] = 0;
-    txQuadVerts[1].txtpos[0]   = 1;
-    txQuadVerts[1].txtpos[1]   = 0;
-
-    txQuadVerts[2].position[0] = dx2;
-    txQuadVerts[2].position[1] = dy2;
-    txQuadVerts[2].position[2] = 0;
-    txQuadVerts[2].txtpos[0]   = 1;
-    txQuadVerts[2].txtpos[1]   = 1;
-
-    txQuadVerts[3].position[0] = dx2;
-    txQuadVerts[3].position[1] = dy2;
-    txQuadVerts[3].position[2] = 0;
-    txQuadVerts[3].txtpos[0]   = 1;
-    txQuadVerts[3].txtpos[1]   = 1;
-
-    txQuadVerts[4].position[0] = dx1;
-    txQuadVerts[4].position[1] = dy2;
-    txQuadVerts[4].position[2] = 0;
-    txQuadVerts[4].txtpos[0]   = 0;
-    txQuadVerts[4].txtpos[1]   = 1;
-
-    txQuadVerts[5].position[0] = dx1;
-    txQuadVerts[5].position[1] = dy1;
-    txQuadVerts[5].position[2] = 0;
-    txQuadVerts[5].txtpos[0]   = 0;
-    txQuadVerts[5].txtpos[1]   = 0;
-    [encoder setVertexBytes:txQuadVerts length:sizeof(txQuadVerts) atIndex:MeshVertexBuffer];
-    [encoder setFragmentTexture:texture atIndex: 0];
-    [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
-    [encoder endEncoding];
+    J2dTraceLn4(J2D_TRACE_INFO,
+        "Destination coordinates dx1 = %f dy1 = %f dx2 = %f dy2 = %f", dx1, dy1, dx2, dy2);
+    MTLVertexCache_AddGlyphTexture(mtlc, width, height, ginfo);
+    MTLVertexCache_AddVertexTriangles(dx1, dy1, dx2, dy2);
     return JNI_TRUE;
 }
 
@@ -431,6 +382,9 @@
 
     glyphMode = MODE_NOT_INITED;
     isCachedDestValid = JNI_FALSE;
+    J2dTraceLn1(J2D_TRACE_INFO, "totalGlyphs = %d", totalGlyphs);
+
+    MTLVertexCache_CreateSamplingEncoder(mtlc, dstOps);
 
     for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) {
         J2dTraceLn(J2D_TRACE_INFO, "Entered for loop for glyph list");
@@ -472,11 +426,12 @@
         // as we implement LCD, cache usage add new selection condition.
 
         if (grayscale) {
+            MTLVertexCache_InitVertexCache(mtlc);
             // grayscale or monochrome glyph data
             if (ginfo->width <= MTLTR_CACHE_CELL_WIDTH &&
                 ginfo->height <= MTLTR_CACHE_CELL_HEIGHT)
             {
-                J2dTraceLn(J2D_TRACE_INFO, "Grayscale cache");
+                J2dTraceLn(J2D_TRACE_INFO, "Forced Grayscale no cache");
                 //ok = MTLTR_DrawGrayscaleGlyphViaCache(oglc, ginfo, x, y);
                 // TODO: Replace no cache with cache rendering
                 ok = MTLTR_DrawGrayscaleGlyphNoCache(mtlc, ginfo, x, y, dstOps);
@@ -524,6 +479,8 @@
         }
     }
 
+    MTLVertexCache_FlushVertexCache(mtlc);
+
     // TODO : Disable glyph state.
 }
 
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.h	Tue Jun 25 15:24:41 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.h	Tue Jun 25 16:21:42 2019 +0530
@@ -25,14 +25,19 @@
 
 #ifndef MTLVertexCache_h_Included
 #define MTLVertexCache_h_Included
-
 #include "j2d_md.h"
 #include "MTLContext.h"
+#include "fontscalerdefs.h"
 
 /**
  * Constants that control the size of the vertex cache.
  */
-#define MTLVC_MAX_INDEX         1024
+#define MTLVC_MAX_INDEX         960
+
+/**
+ * Constants that control the size of the texture pool.
+ */
+#define MTLVC_MAX_TEX_INDEX     32
 
 /**
  * Constants that control the size of the texture tile cache used for
@@ -66,7 +71,7 @@
  * Exported methods.
  */
 jboolean MTLVertexCache_InitVertexCache(MTLContext *mtlc);
-void MTLVertexCache_FlushVertexCache();
+void MTLVertexCache_FlushVertexCache(MTLContext *mtlc);
 void MTLVertexCache_RestoreColorState(MTLContext *mtlc);
 
 void MTLVertexCache_EnableMaskCache(MTLContext *mtlc);
@@ -77,10 +82,11 @@
                                 jint width, jint height,
                                 jint maskscan, void *mask);
 
-void MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
-                                 jfloat tx1, jfloat ty1,
-                                 jfloat tx2, jfloat ty2,
-                                 jfloat dx1, jfloat dy1,
-                                 jfloat dx2, jfloat dy2);
+void MTLVertexCache_AddGlyphTexture(MTLContext *mtlc,
+                                    jint width, jint height,
+                                    GlyphInfo *ginfo);
+void MTLVertexCache_AddVertexTriangles(jfloat dx1, jfloat dy1,
+                                       jfloat dx2, jfloat dy2);
+void MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps);
 
 #endif /* MTLVertexCache_h_Included */
--- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m	Tue Jun 25 15:24:41 2019 +0530
+++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m	Tue Jun 25 16:21:42 2019 +0530
@@ -32,11 +32,11 @@
 
 #include "MTLPaints.h"
 #include "MTLVertexCache.h"
+#include "common.h"
 
 typedef struct _J2DVertex {
-    jfloat tx, ty;
-    jubyte r, g, b, a;
-    jfloat dx, dy;
+    float position[3];
+    float txtpos[2];
 } J2DVertex;
 
 static J2DVertex *vertexCache = NULL;
@@ -45,41 +45,65 @@
 static jint maskCacheTexID = 0;
 static jint maskCacheIndex = 0;
 
-#define MTLVC_ADD_VERTEX(TX, TY, R, G, B, A, DX, DY) \
+id<MTLRenderCommandEncoder> encoder;
+id<MTLTexture> texturePool[MTLVC_MAX_TEX_INDEX];
+static jint texturePoolIndex = 0;
+
+#define MTLVC_ADD_VERTEX(TX, TY, DX, DY, DZ) \
     do { \
         J2DVertex *v = &vertexCache[vertexCacheIndex++]; \
-        v->tx = TX; \
-        v->ty = TY; \
-        v->r  = R;  \
-        v->g  = G;  \
-        v->b  = B;  \
-        v->a  = A;  \
-        v->dx = DX; \
-        v->dy = DY; \
+        v->txtpos[0] = TX; \
+        v->txtpos[1] = TY; \
+        v->position[0]= DX; \
+        v->position[1] = DY; \
+        v->position[2] = DZ; \
     } while (0)
 
-#define MTLVC_ADD_QUAD(TX1, TY1, TX2, TY2, DX1, DY1, DX2, DY2, R, G, B, A) \
+#define MTLVC_ADD_TRIANGLES(DX1, DY1, DX2, DY2) \
     do { \
-        MTLVC_ADD_VERTEX(TX1, TY1, R, G, B, A, DX1, DY1); \
-        MTLVC_ADD_VERTEX(TX2, TY1, R, G, B, A, DX2, DY1); \
-        MTLVC_ADD_VERTEX(TX2, TY2, R, G, B, A, DX2, DY2); \
-        MTLVC_ADD_VERTEX(TX1, TY2, R, G, B, A, DX1, DY2); \
+        MTLVC_ADD_VERTEX(0, 0, DX1, DY1, 0); \
+        MTLVC_ADD_VERTEX(1, 0, DX2, DY1, 0); \
+        MTLVC_ADD_VERTEX(1, 1, DX2, DY2, 0); \
+        MTLVC_ADD_VERTEX(1, 1, DX2, DY2, 0); \
+        MTLVC_ADD_VERTEX(0, 1, DX1, DY2, 0); \
+        MTLVC_ADD_VERTEX(0, 0, DX1, DY1, 0); \
     } while (0)
 
 jboolean
 MTLVertexCache_InitVertexCache(MTLContext *mtlc)
 {
-    //TODO
     J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitVertexCache");
+
+    if (vertexCache == NULL) {
+        vertexCache = (J2DVertex *)malloc(MTLVC_MAX_INDEX * sizeof(J2DVertex));
+        if (vertexCache == NULL) {
+            return JNI_FALSE;
+        }
+    }
+
     return JNI_TRUE;
 }
 
 void
-MTLVertexCache_FlushVertexCache()
+MTLVertexCache_FlushVertexCache(MTLContext *mtlc)
 {
-    // TODO
     J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache");
+
+    if (vertexCacheIndex > 0 ||
+        texturePoolIndex > 0) {
+        id<MTLBuffer>vertexBuffer = [mtlc.device newBufferWithBytes:vertexCache
+                                                 length:vertexCacheIndex * sizeof(J2DVertex)
+                                                 options:MTLResourceOptionCPUCacheModeDefault];
+        [encoder setVertexBuffer:vertexBuffer offset:0 atIndex:MeshVertexBuffer];
+        for (int i = 0; i < texturePoolIndex; i++) {
+            J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_FlushVertexCache : draw texture at index %d", i);
+            [encoder setFragmentTexture:texturePool[i] atIndex: 0];
+            [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:i*6 vertexCount:6];
+        }
+        [encoder endEncoding];
+    }
     vertexCacheIndex = 0;
+    texturePoolIndex = 0;
 }
 
 /**
@@ -146,22 +170,43 @@
 }
 
 void
-MTLVertexCache_AddMaskQuad(MTLContext *mtlc,
-                           jint srcx, jint srcy,
-                           jint dstx, jint dsty,
-                           jint width, jint height,
-                           jint maskscan, void *mask)
+MTLVertexCache_AddVertexTriangles(jfloat dx1, jfloat dy1,
+                                  jfloat dx2, jfloat dy2)
 {
-    // TODO
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddVertexTriangles");
+    MTLVC_ADD_TRIANGLES(dx1, dy1, dx2, dy2);
 }
 
 void
-MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
-                            jfloat tx1, jfloat ty1, jfloat tx2, jfloat ty2,
-                            jfloat dx1, jfloat dy1, jfloat dx2, jfloat dy2)
+MTLVertexCache_AddGlyphTexture(MTLContext *mtlc,
+                               jint width, jint height,
+                               GlyphInfo *ginfo)
 {
-    // TODO
-    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphQuad");
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddGlyphTexture");
+    if (texturePoolIndex >= MTLVC_MAX_TEX_INDEX ||
+        vertexCacheIndex >= MTLVC_MAX_INDEX)
+    {
+        MTLVertexCache_FlushVertexCache(mtlc);
+    }
+    id<MTLTexture> texture = [mtlc.texturePool getTexture:width height:height format:MTLPixelFormatA8Unorm];
+    NSUInteger bytesPerRow = 1 * width;
+
+    MTLRegion region = {
+        { 0, 0, 0 },
+        {width, height, 1}
+    };
+    [texture replaceRegion:region
+             mipmapLevel:0
+             withBytes:ginfo->image
+             bytesPerRow:bytesPerRow];
+    texturePool[texturePoolIndex] = texture;
+    texturePoolIndex++;
+}
+
+void
+MTLVertexCache_CreateSamplingEncoder(MTLContext *mtlc, BMTLSDOps *dstOps) {
+    J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_CreateSamplingEncoder");
+    encoder = [mtlc createSamplingEncoderForDest:dstOps->pTexture];
 }
 
 #endif /* !HEADLESS */