src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m
branchmetal-prototype-branch
changeset 57462 db2be8544d10
parent 57441 ee34e24af607
child 57469 c43fb5314415
equal deleted inserted replaced
57458:3a7c29ba6b1c 57462:db2be8544d10
    40 } J2DVertex;
    40 } J2DVertex;
    41 
    41 
    42 static J2DVertex *vertexCache = NULL;
    42 static J2DVertex *vertexCache = NULL;
    43 static jint vertexCacheIndex = 0;
    43 static jint vertexCacheIndex = 0;
    44 
    44 
    45 static jint maskCacheTexID = 0;
    45 id<MTLTexture> maskCacheTex = NULL;
    46 static jint maskCacheIndex = 0;
    46 static jint maskCacheIndex = 0;
    47 
    47 
    48 id<MTLRenderCommandEncoder> encoder;
    48 id<MTLRenderCommandEncoder> encoder = NULL;
    49 id<MTLTexture> texturePool[MTLVC_MAX_TEX_INDEX];
       
    50 static jint texturePoolIndex = 0;
       
    51 
    49 
    52 #define MTLVC_ADD_VERTEX(TX, TY, DX, DY, DZ) \
    50 #define MTLVC_ADD_VERTEX(TX, TY, DX, DY, DZ) \
    53     do { \
    51     do { \
    54         J2DVertex *v = &vertexCache[vertexCacheIndex++]; \
    52         J2DVertex *v = &vertexCache[vertexCacheIndex++]; \
    55         v->txtpos[0] = TX; \
    53         v->txtpos[0] = TX; \
    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
   145         [mtlc setColor:mtlc.pixel];
   145         [mtlc setColor:mtlc.pixel];
   146     }
   146     }
   147 }
   147 }
   148 
   148 
   149 static jboolean
   149 static jboolean
   150 MTLVertexCache_InitMaskCache()
   150 MTLVertexCache_InitMaskCache(MTLContext *mtlc)
   151 {
   151 {
   152     // TODO
   152     J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_InitMaskCache");
   153     J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_InitMaskCache");
   153     MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatA8Unorm width:MTLVC_MASK_CACHE_WIDTH_IN_TEXELS height:MTLVC_MASK_CACHE_HEIGHT_IN_TEXELS mipmapped:NO];
       
   154     maskCacheTex = [mtlc.device newTextureWithDescriptor:textureDescriptor];
   154     return JNI_TRUE;
   155     return JNI_TRUE;
   155 }
   156 }
   156 
   157 
   157 void
   158 void
   158 MTLVertexCache_EnableMaskCache(MTLContext *mtlc)
   159 MTLVertexCache_EnableMaskCache(MTLContext *mtlc)
   159 {
   160 {
   160     // TODO
       
   161     J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_EnableMaskCache");
   161     J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_EnableMaskCache");
       
   162 
       
   163     if (!MTLVertexCache_InitVertexCache()) {
       
   164         return;
       
   165     }
       
   166 
       
   167     if (maskCacheTex == NULL) {
       
   168         if (!MTLVertexCache_InitMaskCache(mtlc)) {
       
   169             return;
       
   170         }
       
   171     }
   162 }
   172 }
   163 
   173 
   164 void
   174 void
   165 MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
   175 MTLVertexCache_DisableMaskCache(MTLContext *mtlc)
   166 {
   176 {
   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 */