mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JBR-4883 macOS: SIGSEGV at MTLVertexCache_FlushGlyphVertexCache
Use separate glyph cache for each MTLContext instance. Refactored MTLGlyphCache
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
#include "MTLClip.h"
|
||||
#include "EncoderManager.h"
|
||||
#include "MTLSamplerManager.h"
|
||||
#import "MTLGlyphCache.h"
|
||||
|
||||
@class MTLStencilManager;
|
||||
@class MTLLayer;
|
||||
@@ -68,6 +69,16 @@
|
||||
@property (readonly) MTLTransform * transform;
|
||||
@property (readonly) MTLClip * clip;
|
||||
|
||||
/**
|
||||
* There are two separate glyph caches: for AA and for LCD.
|
||||
* Once one of them is initialized as either GRAY or LCD, it
|
||||
* stays in that mode for the duration of the MTLContext (it is not safe
|
||||
* to use this one glyph cache for all screens in a multi-monitor
|
||||
* environment)
|
||||
*/
|
||||
@property (readonly) MTLGlyphCache *glyphCacheLCD;
|
||||
@property (readonly) MTLGlyphCache *glyphCacheAA;
|
||||
|
||||
@property jint textureFunction;
|
||||
@property jboolean vertexCacheEnabled;
|
||||
@property jboolean aaEnabled;
|
||||
|
||||
@@ -181,6 +181,8 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
CVDisplayLinkCreateWithCGDisplay(displayID, &_displayLink);
|
||||
CVDisplayLinkSetOutputCallback(_displayLink, &mtlDisplayLinkCallback, (__bridge void *) self);
|
||||
}
|
||||
_glyphCacheLCD = [[MTLGlyphCache alloc] initWithContext:self];
|
||||
_glyphCacheAA = [[MTLGlyphCache alloc] initWithContext:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -191,6 +193,9 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
// TODO : Check that texturePool is completely released.
|
||||
// texturePool content is released in MTLCommandBufferWrapper.onComplete()
|
||||
//self.texturePool = nil;
|
||||
[_glyphCacheLCD release];
|
||||
[_glyphCacheAA release];
|
||||
|
||||
self.vertexBuffer = nil;
|
||||
self.commandQueue = nil;
|
||||
self.pipelineStateStorage = nil;
|
||||
|
||||
@@ -35,12 +35,13 @@ extern "C" {
|
||||
#import <Metal/Metal.h>
|
||||
@class MTLContext;
|
||||
|
||||
typedef void (MTLFlushFunc)();
|
||||
typedef void (MTLFlushFunc)(MTLContext* mtlc);
|
||||
|
||||
typedef struct _MTLCacheCellInfo MTLCacheCellInfo;
|
||||
|
||||
typedef struct {
|
||||
MTLContext* mtlc;
|
||||
id<MTLRenderCommandEncoder> encoder;
|
||||
MTLCacheCellInfo *head;
|
||||
MTLCacheCellInfo *tail;
|
||||
id<MTLTexture> texture;
|
||||
@@ -72,26 +73,29 @@ struct _MTLCacheCellInfo {
|
||||
jfloat ty2;
|
||||
};
|
||||
|
||||
MTLGlyphCacheInfo *
|
||||
MTLGlyphCache_Init(MTLContext* mtlc, jint width, jint height,
|
||||
jint cellWidth, jint cellHeight, MTLFlushFunc *func);
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_AddGlyph(MTLGlyphCacheInfo *cache, struct GlyphInfo *glyph);
|
||||
bool
|
||||
MTLGlyphCache_IsCacheFull(MTLGlyphCacheInfo *cache, GlyphInfo *glyph);
|
||||
void
|
||||
MTLGlyphCache_Invalidate(MTLGlyphCacheInfo *cache);
|
||||
void
|
||||
MTLGlyphCache_AddCellInfo(struct GlyphInfo *glyph, MTLCacheCellInfo *cellInfo);
|
||||
void
|
||||
MTLGlyphCache_RemoveCellInfo(struct GlyphInfo *glyph, MTLCacheCellInfo *cellInfo);
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_GetCellInfoForCache(struct GlyphInfo *glyph,
|
||||
MTLGlyphCacheInfo *cache);
|
||||
JNIEXPORT void
|
||||
MTLGlyphCache_RemoveAllCellInfos(struct GlyphInfo *glyph);
|
||||
void
|
||||
MTLGlyphCache_Free(MTLGlyphCacheInfo *cache);
|
||||
|
||||
@interface MTLGlyphCache : NSObject
|
||||
- (id)initWithContext:(MTLContext*)ctx;
|
||||
- (void) dealloc;
|
||||
- (BOOL) glyphCacheInitWidth:(jint)width
|
||||
height:(jint)height
|
||||
cellWidth:(jint)cellWidth
|
||||
cellHeight:(jint)cellHeight
|
||||
pixelFormat:(NSUInteger)pixelFormat
|
||||
func:(MTLFlushFunc*)func;
|
||||
- (MTLCacheCellInfo*) addGlyph:(GlyphInfo*)glyph;
|
||||
- (BOOL) isCacheFull:(GlyphInfo*)glyph;
|
||||
- (void) invalidate;
|
||||
- (void) free;
|
||||
|
||||
@property (readwrite) MTLGlyphCacheInfo *cacheInfo;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -36,6 +36,19 @@
|
||||
*/
|
||||
#define TIMES_RENDERED_THRESHOLD 5
|
||||
|
||||
@implementation MTLGlyphCache {
|
||||
MTLContext* _ctx;
|
||||
}
|
||||
|
||||
- (id) initWithContext:(MTLContext*) ctx {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_ctx = ctx;
|
||||
_cacheInfo = NULL;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GlyphCacheInfo structure, fills in the initial values, and
|
||||
* then returns a pointer to the GlyphCacheInfo record.
|
||||
@@ -60,32 +73,40 @@
|
||||
* for retrieving cell info for the glyph, but instead just use the struct's
|
||||
* field directly.
|
||||
*/
|
||||
MTLGlyphCacheInfo *
|
||||
MTLGlyphCache_Init(MTLContext* mtlc, jint width, jint height,
|
||||
jint cellWidth, jint cellHeight,
|
||||
MTLFlushFunc *func)
|
||||
|
||||
- (BOOL) glyphCacheInitWidth:(jint)width
|
||||
height:(jint)height
|
||||
cellWidth:(jint)cellWidth
|
||||
cellHeight:(jint)cellHeight
|
||||
pixelFormat:(NSUInteger)pixelFormat
|
||||
func:(MTLFlushFunc *)func
|
||||
{
|
||||
MTLGlyphCacheInfo *gcinfo;
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache.glyphCacheInitWidth");
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_Init");
|
||||
|
||||
gcinfo = (MTLGlyphCacheInfo *)malloc(sizeof(MTLGlyphCacheInfo));
|
||||
if (gcinfo == NULL) {
|
||||
_cacheInfo = (MTLGlyphCacheInfo *)malloc(sizeof(MTLGlyphCacheInfo));
|
||||
if (_cacheInfo == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLGlyphCache_Init: could not allocate MTLGlyphCacheInfo");
|
||||
return NULL;
|
||||
"MTLGlyphCache.glyphCacheInitWidth: could not allocate MTLGlyphCacheInfo");
|
||||
return NO;
|
||||
}
|
||||
|
||||
gcinfo->head = NULL;
|
||||
gcinfo->tail = NULL;
|
||||
gcinfo->width = width;
|
||||
gcinfo->height = height;
|
||||
gcinfo->cellWidth = cellWidth;
|
||||
gcinfo->cellHeight = cellHeight;
|
||||
gcinfo->Flush = func;
|
||||
gcinfo->mtlc = mtlc;
|
||||
_cacheInfo->head = NULL;
|
||||
_cacheInfo->tail = NULL;
|
||||
_cacheInfo->width = width;
|
||||
_cacheInfo->height = height;
|
||||
_cacheInfo->cellWidth = cellWidth;
|
||||
_cacheInfo->cellHeight = cellHeight;
|
||||
_cacheInfo->Flush = func;
|
||||
_cacheInfo->mtlc = _ctx;
|
||||
_cacheInfo->encoder = nil;
|
||||
MTLTextureDescriptor *textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat
|
||||
width:width
|
||||
height:height
|
||||
mipmapped:NO];
|
||||
_cacheInfo->texture = [_ctx.device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
return gcinfo;
|
||||
return YES;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,32 +125,31 @@ MTLGlyphCache_Init(MTLContext* mtlc, jint width, jint height,
|
||||
* Returns created cell info if it was successfully created and added to the
|
||||
* cache and glyph's cell lists, NULL otherwise.
|
||||
*/
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_AddGlyph(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
- (MTLCacheCellInfo*) addGlyph:(GlyphInfo*) glyph
|
||||
{
|
||||
MTLCacheCellInfo *cellinfo = NULL;
|
||||
jint w = glyph->width;
|
||||
jint h = glyph->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_AddGlyph");
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache.addGlyph");
|
||||
|
||||
if ((glyph->width > cache->cellWidth) ||
|
||||
(glyph->height > cache->cellHeight))
|
||||
if ((glyph->width > _cacheInfo->cellWidth) ||
|
||||
(glyph->height > _cacheInfo->cellHeight))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jint x, y;
|
||||
|
||||
if (cache->head == NULL) {
|
||||
if (_cacheInfo->head == NULL) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else {
|
||||
x = cache->tail->x + cache->cellWidth;
|
||||
y = cache->tail->y;
|
||||
if ((x + cache->cellWidth) > cache->width) {
|
||||
x = _cacheInfo->tail->x + _cacheInfo->cellWidth;
|
||||
y = _cacheInfo->tail->y;
|
||||
if ((x + _cacheInfo->cellWidth) > _cacheInfo->width) {
|
||||
x = 0;
|
||||
y += cache->cellHeight;
|
||||
y += _cacheInfo->cellHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,28 +160,28 @@ MTLGlyphCache_AddGlyph(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cellinfo->cacheInfo = cache;
|
||||
cellinfo->cacheInfo = _cacheInfo;
|
||||
cellinfo->glyphInfo = glyph;
|
||||
cellinfo->timesRendered = 0;
|
||||
cellinfo->x = x;
|
||||
cellinfo->y = y;
|
||||
cellinfo->leftOff = 0;
|
||||
cellinfo->rightOff = 0;
|
||||
cellinfo->tx1 = (jfloat)cellinfo->x / cache->width;
|
||||
cellinfo->ty1 = (jfloat)cellinfo->y / cache->height;
|
||||
cellinfo->tx2 = cellinfo->tx1 + ((jfloat)w / cache->width);
|
||||
cellinfo->ty2 = cellinfo->ty1 + ((jfloat)h / cache->height);
|
||||
cellinfo->tx1 = (jfloat)cellinfo->x / _cacheInfo->width;
|
||||
cellinfo->ty1 = (jfloat)cellinfo->y / _cacheInfo->height;
|
||||
cellinfo->tx2 = cellinfo->tx1 + ((jfloat)w / _cacheInfo->width);
|
||||
cellinfo->ty2 = cellinfo->ty1 + ((jfloat)h / _cacheInfo->height);
|
||||
|
||||
if (cache->head == NULL) {
|
||||
if (_cacheInfo->head == NULL) {
|
||||
// initialize the head cell
|
||||
cache->head = cellinfo;
|
||||
_cacheInfo->head = cellinfo;
|
||||
} else {
|
||||
// update existing tail cell
|
||||
cache->tail->next = cellinfo;
|
||||
_cacheInfo->tail->next = cellinfo;
|
||||
}
|
||||
|
||||
// add the new cell to the end of the list
|
||||
cache->tail = cellinfo;
|
||||
_cacheInfo->tail = cellinfo;
|
||||
cellinfo->next = NULL;
|
||||
cellinfo->nextGCI = NULL;
|
||||
|
||||
@@ -170,26 +190,24 @@ MTLGlyphCache_AddGlyph(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
return cellinfo;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MTLGlyphCache_IsCacheFull(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
- (BOOL) isCacheFull:(GlyphInfo*) glyph
|
||||
{
|
||||
jint w = glyph->width;
|
||||
jint h = glyph->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_IsCacheFull");
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache.isCacheFull");
|
||||
|
||||
jint x, y;
|
||||
|
||||
if (cache->head == NULL) {
|
||||
if (_cacheInfo->head == NULL) {
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
x = cache->tail->x + cache->cellWidth;
|
||||
y = cache->tail->y;
|
||||
if ((x + cache->cellWidth) > cache->width) {
|
||||
x = _cacheInfo->tail->x + _cacheInfo->cellWidth;
|
||||
y = _cacheInfo->tail->y;
|
||||
if ((x + _cacheInfo->cellWidth) > _cacheInfo->width) {
|
||||
x = 0;
|
||||
y += cache->cellHeight;
|
||||
if ((y + cache->cellHeight) > cache->height) {
|
||||
y += _cacheInfo->cellHeight;
|
||||
if ((y + _cacheInfo->cellHeight) > _cacheInfo->height) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
}
|
||||
@@ -201,24 +219,23 @@ MTLGlyphCache_IsCacheFull(MTLGlyphCacheInfo *cache, GlyphInfo *glyph)
|
||||
* attempt to compact the cache in any way; it just invalidates any cells
|
||||
* that already exist.
|
||||
*/
|
||||
void
|
||||
MTLGlyphCache_Invalidate(MTLGlyphCacheInfo *cache)
|
||||
- (void) invalidate
|
||||
{
|
||||
MTLCacheCellInfo *cellinfo;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_Invalidate");
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache.invalidate");
|
||||
|
||||
if (cache == NULL) {
|
||||
if (_cacheInfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// flush any pending vertices that may be depending on the current
|
||||
// glyph cache layout
|
||||
if (cache->Flush != NULL) {
|
||||
cache->Flush();
|
||||
if (_cacheInfo->Flush != NULL) {
|
||||
_cacheInfo->Flush(_cacheInfo->mtlc);
|
||||
}
|
||||
|
||||
cellinfo = cache->head;
|
||||
cellinfo = _cacheInfo->head;
|
||||
while (cellinfo != NULL) {
|
||||
if (cellinfo->glyphInfo != NULL) {
|
||||
// if the cell is occupied, notify the base glyph that its
|
||||
@@ -233,36 +250,40 @@ MTLGlyphCache_Invalidate(MTLGlyphCacheInfo *cache)
|
||||
* Invalidates and frees all cells and the cache itself. The "cache" pointer
|
||||
* becomes invalid after this function returns.
|
||||
*/
|
||||
void
|
||||
MTLGlyphCache_Free(MTLGlyphCacheInfo *cache)
|
||||
- (void) free
|
||||
{
|
||||
MTLCacheCellInfo *cellinfo;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_Free");
|
||||
|
||||
if (cache == NULL) {
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache.free");
|
||||
if (_cacheInfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// flush any pending vertices that may be depending on the current
|
||||
// glyph cache
|
||||
if (cache->Flush != NULL) {
|
||||
cache->Flush();
|
||||
if (_cacheInfo->Flush != NULL) {
|
||||
_cacheInfo->Flush(_cacheInfo->mtlc);
|
||||
}
|
||||
[_cacheInfo->texture release];
|
||||
|
||||
while (cache->head != NULL) {
|
||||
cellinfo = cache->head;
|
||||
while (_cacheInfo->head != NULL) {
|
||||
MTLCacheCellInfo *cellinfo = _cacheInfo->head;
|
||||
if (cellinfo->glyphInfo != NULL) {
|
||||
// if the cell is occupied, notify the base glyph that its
|
||||
// cached version for this cache is about to be invalidated
|
||||
MTLGlyphCache_RemoveCellInfo(cellinfo->glyphInfo, cellinfo);
|
||||
}
|
||||
cache->head = cellinfo->next;
|
||||
_cacheInfo->head = cellinfo->next;
|
||||
free(cellinfo);
|
||||
}
|
||||
free(cache);
|
||||
free(_cacheInfo);
|
||||
_cacheInfo = NULL;
|
||||
}
|
||||
|
||||
- (void) dealloc {
|
||||
[self free];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
/**
|
||||
* Add cell info to the head of the glyph's list of cached cells.
|
||||
*/
|
||||
@@ -310,57 +331,4 @@ MTLGlyphCache_RemoveCellInfo(GlyphInfo *glyph, MTLCacheCellInfo *cellInfo)
|
||||
J2dTraceLn2(J2D_TRACE_WARNING, "MTLGlyphCache_RemoveCellInfo: "\
|
||||
"no cell 0x%x in glyph 0x%x's cell list",
|
||||
cellInfo, glyph);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes cell info from the glyph's list of cached cells.
|
||||
*/
|
||||
JNIEXPORT void
|
||||
MTLGlyphCache_RemoveAllCellInfos(GlyphInfo *glyph)
|
||||
{
|
||||
MTLCacheCellInfo *currCell, *prevCell;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_RemoveAllCellInfos");
|
||||
|
||||
if (glyph == NULL || glyph->cellInfo == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// invalidate all of this glyph's accelerated cache cells
|
||||
currCell = glyph->cellInfo;
|
||||
do {
|
||||
currCell->glyphInfo = NULL;
|
||||
prevCell = currCell;
|
||||
currCell = currCell->nextGCI;
|
||||
prevCell->nextGCI = NULL;
|
||||
} while (currCell != NULL);
|
||||
|
||||
glyph->cellInfo = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns cell info associated with particular cache from the glyph's list of
|
||||
* cached cells.
|
||||
*/
|
||||
MTLCacheCellInfo *
|
||||
MTLGlyphCache_GetCellInfoForCache(GlyphInfo *glyph, MTLGlyphCacheInfo *cache)
|
||||
{
|
||||
// assert (glyph != NULL && cache != NULL)
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE2, "MTLGlyphCache_GetCellInfoForCache");
|
||||
|
||||
if (glyph->cellInfo != NULL) {
|
||||
MTLCacheCellInfo *cellInfo = glyph->cellInfo;
|
||||
do {
|
||||
if (cellInfo->cacheInfo == cache) {
|
||||
J2dTraceLn3(J2D_TRACE_VERBOSE2,
|
||||
" glyph 0x%x: found cell 0x%x for cache 0x%x",
|
||||
glyph, cellInfo, cache);
|
||||
return cellInfo;
|
||||
}
|
||||
cellInfo = cellInfo->nextGCI;
|
||||
} while (cellInfo != NULL);
|
||||
}
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x",
|
||||
glyph, cache);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -576,10 +576,8 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
|
||||
jlong pDst = NEXT_LONG(b);
|
||||
|
||||
if (mtlc != NULL) {
|
||||
if (dstOps != NULL && dstOps->pTexture != NULL) {
|
||||
MTLTR_FreeGlyphCacheAA();
|
||||
MTLTR_FreeGlyphCacheLCD();
|
||||
}
|
||||
[mtlc.glyphCacheAA free];
|
||||
[mtlc.glyphCacheLCD free];
|
||||
[mtlc commitCommandBuffer:NO display:NO];
|
||||
}
|
||||
mtlc = [MTLContext setSurfacesEnv:env src:pSrc dst:pDst];
|
||||
@@ -594,10 +592,8 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
|
||||
(MTLGraphicsConfigInfo *)jlong_to_ptr(pConfigInfo);
|
||||
|
||||
if (mtlc != NULL) {
|
||||
if (dstOps != NULL && dstOps->pTexture != NULL) {
|
||||
MTLTR_FreeGlyphCacheAA();
|
||||
MTLTR_FreeGlyphCacheLCD();
|
||||
}
|
||||
[mtlc.glyphCacheAA free];
|
||||
[mtlc.glyphCacheLCD free];
|
||||
[mtlc commitCommandBuffer:NO display:NO];
|
||||
}
|
||||
|
||||
@@ -616,8 +612,8 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
|
||||
BMTLSDOps *mtlsdo = (BMTLSDOps *)jlong_to_ptr(pData);
|
||||
if (mtlsdo != NULL) {
|
||||
CONTINUE_IF_NULL(mtlc);
|
||||
MTLTR_FreeGlyphCacheAA();
|
||||
MTLTR_FreeGlyphCacheLCD();
|
||||
[mtlc.glyphCacheAA free];
|
||||
[mtlc.glyphCacheLCD free];
|
||||
MTLSD_Delete(env, mtlsdo);
|
||||
}
|
||||
break;
|
||||
@@ -641,8 +637,8 @@ Java_sun_java2d_metal_MTLRenderQueue_flushBuffer
|
||||
CHECK_PREVIOUS_OP(MTL_OP_OTHER);
|
||||
jlong pConfigInfo = NEXT_LONG(b);
|
||||
CONTINUE_IF_NULL(mtlc);
|
||||
MTLTR_FreeGlyphCacheAA();
|
||||
MTLTR_FreeGlyphCacheLCD();
|
||||
[mtlc.glyphCacheAA free];
|
||||
[mtlc.glyphCacheLCD free];
|
||||
[mtlc.encoderManager endEncoder];
|
||||
MTLGC_DestroyMTLGraphicsConfig(pConfigInfo);
|
||||
mtlc = NULL;
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
|
||||
void MTLTR_EnableGlyphVertexCache(MTLContext *mtlc, BMTLSDOps *dstOps);
|
||||
void MTLTR_DisableGlyphVertexCache(MTLContext *mtlc);
|
||||
id<MTLTexture> MTLTR_GetGlyphCacheTexture();
|
||||
id<MTLRenderCommandEncoder> MTLTR_GetGlyphCacheEncoder();
|
||||
void MTLTR_FreeGlyphCacheAA();
|
||||
void MTLTR_FreeGlyphCacheLCD();
|
||||
|
||||
void MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
jint totalGlyphs, jboolean usePositions,
|
||||
|
||||
@@ -66,19 +66,6 @@ typedef enum {
|
||||
} GlyphMode;
|
||||
static GlyphMode glyphMode = MODE_NOT_INITED;
|
||||
|
||||
/**
|
||||
* There are two separate glyph caches: for AA and for LCD.
|
||||
* Once one of them is initialized as either GRAY or LCD, it
|
||||
* stays in that mode for the duration of the application. It should
|
||||
* be safe to use this one glyph cache for all screens in a multimon
|
||||
* environment, since the glyph cache texture is shared between all contexts,
|
||||
* and (in theory) Metal drivers should be smart enough to manage that
|
||||
* texture across all screens.
|
||||
*/
|
||||
|
||||
static MTLGlyphCacheInfo *glyphCacheLCD = NULL;
|
||||
static MTLGlyphCacheInfo *glyphCacheAA = NULL;
|
||||
|
||||
/**
|
||||
* This value tracks the previous LCD rgbOrder setting, so if the rgbOrder
|
||||
* value has changed since the last time, it indicates that we need to
|
||||
@@ -98,8 +85,6 @@ static jboolean lastRGBOrder = JNI_TRUE;
|
||||
|
||||
static struct TxtVertex txtVertices[6];
|
||||
static jint vertexCacheIndex = 0;
|
||||
static id<MTLRenderCommandEncoder> aaCacheEncoder = nil;
|
||||
static id<MTLRenderCommandEncoder> lcdCacheEncoder = nil;
|
||||
|
||||
#define LCD_ADD_VERTEX(TX, TY, DX, DY, DZ) \
|
||||
do { \
|
||||
@@ -127,88 +112,28 @@ static id<MTLRenderCommandEncoder> lcdCacheEncoder = nil;
|
||||
* as intensity values.
|
||||
*/
|
||||
static jboolean
|
||||
MTLTR_InitGlyphCache(MTLContext *mtlc, BMTLSDOps *dstOps, jboolean lcdCache)
|
||||
MTLTR_ValidateGlyphCache(MTLContext *mtlc, BMTLSDOps *dstOps, jboolean lcdCache)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_InitGlyphCache");
|
||||
// TODO : Need to verify RGB order in case of LCD
|
||||
MTLPixelFormat pixelFormat =
|
||||
lcdCache ? MTLPixelFormatBGRA8Unorm : MTLPixelFormatA8Unorm;
|
||||
|
||||
MTLGlyphCacheInfo *gcinfo;
|
||||
// init glyph cache data structure
|
||||
gcinfo = MTLGlyphCache_Init(mtlc, MTLTR_CACHE_WIDTH,
|
||||
MTLTR_CACHE_HEIGHT,
|
||||
MTLTR_CACHE_CELL_WIDTH,
|
||||
MTLTR_CACHE_CELL_HEIGHT,
|
||||
MTLVertexCache_FlushGlyphVertexCache);
|
||||
|
||||
if (gcinfo == NULL) {
|
||||
MTLGlyphCache* glyphCache = (lcdCache)?mtlc.glyphCacheLCD:mtlc.glyphCacheAA;
|
||||
if (glyphCache.cacheInfo == NULL && ![glyphCache glyphCacheInitWidth:MTLTR_CACHE_WIDTH
|
||||
height:MTLTR_CACHE_HEIGHT
|
||||
cellWidth:MTLTR_CACHE_CELL_WIDTH
|
||||
cellHeight:MTLTR_CACHE_CELL_HEIGHT
|
||||
pixelFormat:(lcdCache)?MTLPixelFormatBGRA8Unorm:MTLPixelFormatA8Unorm
|
||||
func:MTLVertexCache_FlushGlyphVertexCache])
|
||||
{
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLTR_InitGlyphCache: could not init MTL glyph cache");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
MTLTextureDescriptor *textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat
|
||||
width:MTLTR_CACHE_WIDTH
|
||||
height:MTLTR_CACHE_HEIGHT
|
||||
mipmapped:NO];
|
||||
|
||||
gcinfo->texture = [mtlc.device newTextureWithDescriptor:textureDescriptor];
|
||||
|
||||
if (lcdCache) {
|
||||
glyphCacheLCD = gcinfo;
|
||||
} else {
|
||||
glyphCacheAA = gcinfo;
|
||||
}
|
||||
|
||||
glyphCache.cacheInfo->encoder = (lcdCache)?
|
||||
[mtlc.encoderManager getLCDEncoder:dstOps->pTexture isSrcOpaque:YES isDstOpaque:YES]:
|
||||
[mtlc.encoderManager getTextEncoder:dstOps isSrcOpaque:NO gammaCorrection:YES];
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
MTLTR_ValidateGlyphCache(MTLContext *mtlc, BMTLSDOps *dstOps, jboolean lcdCache)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_ValidateGlyphCache");
|
||||
if (lcdCache) {
|
||||
if (glyphCacheLCD == NULL && !MTLTR_InitGlyphCache(mtlc, dstOps, JNI_TRUE)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
lcdCacheEncoder = [mtlc.encoderManager getLCDEncoder:dstOps->pTexture
|
||||
isSrcOpaque:YES
|
||||
isDstOpaque:YES];
|
||||
} else {
|
||||
if (glyphCacheAA == NULL && !MTLTR_InitGlyphCache(mtlc, dstOps, JNI_FALSE)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
aaCacheEncoder = [mtlc.encoderManager getTextEncoder:dstOps
|
||||
isSrcOpaque:NO
|
||||
gammaCorrection:YES];
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
id<MTLRenderCommandEncoder>
|
||||
MTLTR_GetGlyphCacheEncoder()
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_GetGlyphCacheEncoder");
|
||||
if (glyphCacheAA != NULL) {
|
||||
return aaCacheEncoder;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
id<MTLTexture>
|
||||
MTLTR_GetGlyphCacheTexture()
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_GetGlyphCacheTexture");
|
||||
if (glyphCacheAA != NULL) {
|
||||
return glyphCacheAA->texture;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given glyph to the glyph cache (texture and data structure)
|
||||
* associated with the given MTLContext.
|
||||
@@ -218,32 +143,30 @@ MTLTR_AddToGlyphCache(GlyphInfo *glyph, MTLContext *mtlc,
|
||||
BMTLSDOps *dstOps, jboolean lcdCache)
|
||||
{
|
||||
MTLCacheCellInfo *ccinfo;
|
||||
MTLGlyphCacheInfo *gcinfo;
|
||||
MTLGlyphCache* gc;
|
||||
jint w = glyph->width;
|
||||
jint h = glyph->height;
|
||||
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_AddToGlyphCache");
|
||||
if (!lcdCache) {
|
||||
gcinfo = glyphCacheAA;
|
||||
gc = mtlc.glyphCacheAA;
|
||||
} else {
|
||||
gcinfo = glyphCacheLCD;
|
||||
gc = mtlc.glyphCacheLCD;
|
||||
}
|
||||
|
||||
if ((gcinfo == NULL) || (glyph->image == NULL)) {
|
||||
if ((gc.cacheInfo == NULL) || (glyph->image == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool isCacheFull = MTLGlyphCache_IsCacheFull(gcinfo, glyph);
|
||||
if (isCacheFull) {
|
||||
if ([gc isCacheFull:glyph]) {
|
||||
if (lcdCache) {
|
||||
MTLTR_FreeGlyphCacheLCD();
|
||||
[mtlc.glyphCacheLCD free];
|
||||
} else {
|
||||
MTLTR_FreeGlyphCacheAA();
|
||||
[mtlc.glyphCacheAA free];
|
||||
}
|
||||
MTLTR_ValidateGlyphCache(mtlc, dstOps, lcdCache);
|
||||
gcinfo = lcdCache ? glyphCacheLCD : glyphCacheAA;
|
||||
}
|
||||
MTLGlyphCache_AddGlyph(gcinfo, glyph);
|
||||
[gc addGlyph:glyph];
|
||||
ccinfo = (MTLCacheCellInfo *) glyph->cellInfo;
|
||||
|
||||
if (ccinfo != NULL) {
|
||||
@@ -254,7 +177,7 @@ MTLTR_AddToGlyphCache(GlyphInfo *glyph, MTLContext *mtlc,
|
||||
};
|
||||
if (!lcdCache) {
|
||||
NSUInteger bytesPerRow = 1 * w;
|
||||
[gcinfo->texture replaceRegion:region
|
||||
[gc.cacheInfo->texture replaceRegion:region
|
||||
mipmapLevel:0
|
||||
withBytes:glyph->image
|
||||
bytesPerRow:bytesPerRow];
|
||||
@@ -273,7 +196,7 @@ MTLTR_AddToGlyphCache(GlyphInfo *glyph, MTLContext *mtlc,
|
||||
}
|
||||
|
||||
NSUInteger bytesPerRow = 4 * w;
|
||||
[gcinfo->texture replaceRegion:region
|
||||
[gc.cacheInfo->texture replaceRegion:region
|
||||
mipmapLevel:0
|
||||
withBytes:imageData
|
||||
bytesPerRow:bytesPerRow];
|
||||
@@ -335,28 +258,10 @@ void
|
||||
MTLTR_DisableGlyphVertexCache(MTLContext *mtlc)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DisableGlyphVertexCache");
|
||||
MTLVertexCache_FlushGlyphVertexCache();
|
||||
MTLVertexCache_FlushGlyphVertexCache(mtlc);
|
||||
MTLVertexCache_FreeVertexCache();
|
||||
}
|
||||
|
||||
void MTLTR_FreeGlyphCacheAA() {
|
||||
if (glyphCacheAA != NULL) {
|
||||
id<MTLTexture> txt = glyphCacheAA->texture;
|
||||
MTLGlyphCache_Free(glyphCacheAA);
|
||||
[txt release];
|
||||
glyphCacheAA = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void MTLTR_FreeGlyphCacheLCD() {
|
||||
if (glyphCacheLCD != NULL) {
|
||||
id<MTLTexture> txt = glyphCacheLCD->texture;
|
||||
MTLGlyphCache_Free(glyphCacheLCD);
|
||||
[txt release];
|
||||
glyphCacheLCD = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static MTLPaint* storedPaint = nil;
|
||||
|
||||
static void EnableColorGlyphPainting(MTLContext *mtlc) {
|
||||
@@ -443,7 +348,7 @@ MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
if (rgbOrder != lastRGBOrder) {
|
||||
// need to invalidate the cache in this case; see comments
|
||||
// for lastRGBOrder above
|
||||
MTLGlyphCache_Invalidate(glyphCacheLCD);
|
||||
[mtlc.glyphCacheLCD invalidate];
|
||||
lastRGBOrder = rgbOrder;
|
||||
}
|
||||
|
||||
@@ -463,7 +368,7 @@ MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
cell = (MTLCacheCellInfo *) (ginfo->cellInfo);
|
||||
cell->timesRendered++;
|
||||
|
||||
MTLTR_SetLCDContrast(mtlc, contrast, lcdCacheEncoder);
|
||||
MTLTR_SetLCDContrast(mtlc, contrast, mtlc.glyphCacheLCD.cacheInfo->encoder);
|
||||
tx1 = cell->tx1;
|
||||
ty1 = cell->ty1;
|
||||
tx2 = cell->tx2;
|
||||
@@ -474,11 +379,11 @@ MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, BMTLSDOps *dstOps,
|
||||
|
||||
LCD_ADD_TRIANGLES(tx1, ty1, tx2, ty2, x, y, x+w, y+h);
|
||||
|
||||
[lcdCacheEncoder setVertexBytes:txtVertices length:sizeof(txtVertices) atIndex:MeshVertexBuffer];
|
||||
[lcdCacheEncoder setFragmentTexture:glyphCacheLCD->texture atIndex:0];
|
||||
[lcdCacheEncoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
[mtlc.glyphCacheLCD.cacheInfo->encoder setVertexBytes:txtVertices length:sizeof(txtVertices) atIndex:MeshVertexBuffer];
|
||||
[mtlc.glyphCacheLCD.cacheInfo->encoder setFragmentTexture:mtlc.glyphCacheLCD.cacheInfo->texture atIndex:0];
|
||||
[mtlc.glyphCacheLCD.cacheInfo->encoder setFragmentTexture:dstOps->pTexture atIndex:1];
|
||||
|
||||
[lcdCacheEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
[mtlc.glyphCacheLCD.cacheInfo->encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:6];
|
||||
|
||||
vertexCacheIndex = 0;
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
*/
|
||||
jboolean MTLVertexCache_InitVertexCache();
|
||||
void MTLVertexCache_FlushVertexCache(MTLContext *mtlc);
|
||||
void MTLVertexCache_FlushGlyphVertexCache();
|
||||
void MTLVertexCache_FlushGlyphVertexCache(MTLContext *mtlc);
|
||||
void MTLVertexCache_FreeVertexCache();
|
||||
|
||||
void MTLVertexCache_EnableMaskCache(MTLContext *mtlc, BMTLSDOps *dstOps);
|
||||
|
||||
@@ -110,15 +110,15 @@ MTLVertexCache_FlushVertexCache(MTLContext *mtlc)
|
||||
}
|
||||
|
||||
void
|
||||
MTLVertexCache_FlushGlyphVertexCache()
|
||||
MTLVertexCache_FlushGlyphVertexCache(MTLContext *mtlc)
|
||||
{
|
||||
J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_FlushGlyphVertexCache");
|
||||
|
||||
if (vertexCacheIndex > 0) {
|
||||
id<MTLRenderCommandEncoder> gcEncoder = MTLTR_GetGlyphCacheEncoder();
|
||||
if (vertexCacheIndex > 0 && mtlc.glyphCacheAA.cacheInfo != NULL) {
|
||||
id<MTLRenderCommandEncoder> gcEncoder = mtlc.glyphCacheAA.cacheInfo->encoder;
|
||||
[gcEncoder setVertexBytes: vertexCache length:vertexCacheIndex * sizeof(J2DVertex)
|
||||
atIndex:MeshVertexBuffer];
|
||||
id<MTLTexture> glyphCacheTex = MTLTR_GetGlyphCacheTexture();
|
||||
id<MTLTexture> glyphCacheTex = mtlc.glyphCacheAA.cacheInfo->texture;
|
||||
[gcEncoder setFragmentTexture:glyphCacheTex atIndex: 0];
|
||||
J2dTraceLn1(J2D_TRACE_INFO,
|
||||
"MTLVertexCache_FlushGlyphVertexCache : encode %d characters", (vertexCacheIndex / 6));
|
||||
@@ -323,7 +323,7 @@ MTLVertexCache_AddGlyphQuad(MTLContext *mtlc,
|
||||
if ((vertexCacheIndex + VERTS_FOR_A_QUAD) >= MTLVC_MAX_INDEX)
|
||||
{
|
||||
J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex);
|
||||
MTLVertexCache_FlushGlyphVertexCache();
|
||||
MTLVertexCache_FlushGlyphVertexCache(mtlc);
|
||||
}
|
||||
|
||||
MTLVC_ADD_TRIANGLES(tx1, ty1, tx2, ty2,
|
||||
|
||||
Reference in New Issue
Block a user