8087201: OGL: rendering of lcd text is slow

Reviewed-by: serb, prr
This commit is contained in:
Andrew Brygin 2015-07-09 16:37:35 +03:00
parent ddb2c7d163
commit 562e4371a1
6 changed files with 159 additions and 74 deletions

View File

@ -191,6 +191,10 @@ public class OGLContext extends BufferedContext {
/** Indicates the presence of the GL_ARB_texture_rectangle extension. */ /** Indicates the presence of the GL_ARB_texture_rectangle extension. */
@Native @Native
static final int CAPS_EXT_TEXRECT = (FIRST_PRIVATE_CAP << 4); static final int CAPS_EXT_TEXRECT = (FIRST_PRIVATE_CAP << 4);
/** Indicates the presence of the GL_NV_texture_barrier extension. */
@Native
static final int CAPS_EXT_TEXBARRIER = (FIRST_PRIVATE_CAP << 5);
OGLContextCaps(int caps, String adapterId) { OGLContextCaps(int caps, String adapterId) {
super(caps, adapterId); super(caps, adapterId);
@ -217,6 +221,9 @@ public class OGLContext extends BufferedContext {
if ((caps & CAPS_EXT_TEXRECT) != 0) { if ((caps & CAPS_EXT_TEXRECT) != 0) {
sb.append("CAPS_EXT_TEXRECT|"); sb.append("CAPS_EXT_TEXRECT|");
} }
if ((caps & CAPS_EXT_TEXBARRIER) != 0) {
sb.append("CAPS_EXT_TEXBARRIER|");
}
return sb.toString(); return sb.toString();
} }
} }

View File

@ -6506,6 +6506,13 @@ GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei, const GLvoid *);
typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string); typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const GLvoid *string);
#endif #endif
#ifndef GL_NV_texture_barrier
#define GL_NV_texture_barrier 1
#ifdef GL_EXT_PROTOTYPES
GLAPI void APIENTRY glTextureBarrierNV (void);
#endif /* GL_EXT_PROTOTYPES */
typedef void (APIENTRYP PNFGLTEXTUREBARRIERNVPROC) (void);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -913,6 +913,10 @@ OGLContext_GetExtensionInfo(JNIEnv *env, jint *caps)
} }
} }
} }
if (OGLContext_IsExtensionAvailable(e, "GL_NV_texture_barrier")) {
*caps |= CAPS_EXT_TEXBARRIER;
}
// stuff vendor descriptor in the upper bits of the caps // stuff vendor descriptor in the upper bits of the caps
if (vendor != NULL) { if (vendor != NULL) {
if (strncmp(vendor, "ATI", 3) == 0) { if (strncmp(vendor, "ATI", 3) == 0) {

View File

@ -132,6 +132,8 @@ typedef struct {
sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_GRAD_SHADER sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_GRAD_SHADER
#define CAPS_EXT_TEXRECT \ #define CAPS_EXT_TEXRECT \
sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_TEXRECT sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_TEXRECT
#define CAPS_EXT_TEXBARRIER \
sun_java2d_opengl_OGLContext_OGLContextCaps_CAPS_EXT_TEXBARRIER
/** /**
* Evaluates to true if the given capability bitmask is present for the * Evaluates to true if the given capability bitmask is present for the

View File

@ -172,6 +172,11 @@ typedef void (GLAPIENTRY *glAttachObjectARBType)(GLhandleARB, GLhandleARB);
typedef void (GLAPIENTRY *glLinkProgramARBType)(GLhandleARB); typedef void (GLAPIENTRY *glLinkProgramARBType)(GLhandleARB);
typedef void (GLAPIENTRY *glDeleteObjectARBType)(GLhandleARB); typedef void (GLAPIENTRY *glDeleteObjectARBType)(GLhandleARB);
/**
* GL_NV_texture_barrier extension function typedef's
*/
typedef void (GLAPIENTRY *glTextureBarrierNVType) (void);
/** /**
* REMIND: this caused an internal error in the MS compiler!?!? * REMIND: this caused an internal error in the MS compiler!?!?
* *
@ -316,7 +321,8 @@ typedef void (GLAPIENTRY *glDeleteObjectARBType)(GLhandleARB);
OGL_##action##_EXT_FUNC(glGetProgramivARB); \ OGL_##action##_EXT_FUNC(glGetProgramivARB); \
OGL_##action##_EXT_FUNC(glGetInfoLogARB); \ OGL_##action##_EXT_FUNC(glGetInfoLogARB); \
OGL_##action##_EXT_FUNC(glGetObjectParameterivARB); \ OGL_##action##_EXT_FUNC(glGetObjectParameterivARB); \
OGL_##action##_EXT_FUNC(glDeleteObjectARB); OGL_##action##_EXT_FUNC(glDeleteObjectARB); \
OGL_##action##_EXT_FUNC(glTextureBarrierNV);
#define OGL_EXPRESS_ALL_FUNCS(action) \ #define OGL_EXPRESS_ALL_FUNCS(action) \
OGL_EXPRESS_BASE_FUNCS(action) \ OGL_EXPRESS_BASE_FUNCS(action) \

View File

@ -46,8 +46,8 @@
*/ */
#define OGLTR_CACHE_WIDTH 512 #define OGLTR_CACHE_WIDTH 512
#define OGLTR_CACHE_HEIGHT 512 #define OGLTR_CACHE_HEIGHT 512
#define OGLTR_CACHE_CELL_WIDTH 16 #define OGLTR_CACHE_CELL_WIDTH 32
#define OGLTR_CACHE_CELL_HEIGHT 16 #define OGLTR_CACHE_CELL_HEIGHT 32
/** /**
* The current "glyph mode" state. This variable is used to track the * The current "glyph mode" state. This variable is used to track the
@ -68,26 +68,17 @@ typedef enum {
static GlyphMode glyphMode = MODE_NOT_INITED; static GlyphMode glyphMode = MODE_NOT_INITED;
/** /**
* This enum indicates the current state of the hardware glyph cache. * There are two separate glyph caches: for AA and for LCD.
* Initially the CacheStatus is set to CACHE_NOT_INITED, and then it is * Once one of them is initialized as either GRAY or LCD, it
* set to either GRAY or LCD when the glyph cache is initialized. * stays in that mode for the duration of the application. It should
*/
typedef enum {
CACHE_NOT_INITED,
CACHE_GRAY,
CACHE_LCD
} CacheStatus;
static CacheStatus cacheStatus = CACHE_NOT_INITED;
/**
* This is the one glyph cache. Once it 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 * 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, * environment, since the glyph cache texture is shared between all contexts,
* and (in theory) OpenGL drivers should be smart enough to manage that * and (in theory) OpenGL drivers should be smart enough to manage that
* texture across all screens. * texture across all screens.
*/ */
static GlyphCacheInfo *glyphCache = NULL;
static GlyphCacheInfo *glyphCacheLCD = NULL;
static GlyphCacheInfo *glyphCacheAA = NULL;
/** /**
* The handle to the LCD text fragment program object. * The handle to the LCD text fragment program object.
@ -138,7 +129,7 @@ static jboolean lastRGBOrder = JNI_TRUE;
* (OGLTR_CACHED_DEST_HEIGHT >= OGLTR_NOCACHE_TILE_SIZE) * (OGLTR_CACHED_DEST_HEIGHT >= OGLTR_NOCACHE_TILE_SIZE)
*/ */
#define OGLTR_CACHED_DEST_WIDTH 512 #define OGLTR_CACHED_DEST_WIDTH 512
#define OGLTR_CACHED_DEST_HEIGHT 32 #define OGLTR_CACHED_DEST_HEIGHT (OGLTR_CACHE_CELL_HEIGHT * 2)
/** /**
* The handle to the "cached destination" texture object. * The handle to the "cached destination" texture object.
@ -212,8 +203,11 @@ OGLTR_InitGlyphCache(jboolean lcdCache)
OGLTR_CACHE_WIDTH, OGLTR_CACHE_HEIGHT, 0, OGLTR_CACHE_WIDTH, OGLTR_CACHE_HEIGHT, 0,
pixelFormat, GL_UNSIGNED_BYTE, NULL); pixelFormat, GL_UNSIGNED_BYTE, NULL);
cacheStatus = (lcdCache ? CACHE_LCD : CACHE_GRAY); if (lcdCache) {
glyphCache = gcinfo; glyphCacheLCD = gcinfo;
} else {
glyphCacheAA = gcinfo;
}
return JNI_TRUE; return JNI_TRUE;
} }
@ -223,24 +217,24 @@ OGLTR_InitGlyphCache(jboolean lcdCache)
* associated with the given OGLContext. * associated with the given OGLContext.
*/ */
static void static void
OGLTR_AddToGlyphCache(GlyphInfo *glyph, jboolean rgbOrder) OGLTR_AddToGlyphCache(GlyphInfo *glyph, GLenum pixelFormat)
{ {
GLenum pixelFormat;
CacheCellInfo *ccinfo; CacheCellInfo *ccinfo;
GlyphCacheInfo *gcinfo;
J2dTraceLn(J2D_TRACE_INFO, "OGLTR_AddToGlyphCache"); J2dTraceLn(J2D_TRACE_INFO, "OGLTR_AddToGlyphCache");
if ((glyphCache == NULL) || (glyph->image == NULL)) { if (pixelFormat == GL_LUMINANCE) {
gcinfo = glyphCacheAA;
} else {
gcinfo = glyphCacheLCD;
}
if ((gcinfo == NULL) || (glyph->image == NULL)) {
return; return;
} }
if (cacheStatus == CACHE_LCD) { AccelGlyphCache_AddGlyph(gcinfo, glyph);
pixelFormat = rgbOrder ? GL_RGB : GL_BGR;
} else {
pixelFormat = GL_LUMINANCE;
}
AccelGlyphCache_AddGlyph(glyphCache, glyph);
ccinfo = (CacheCellInfo *) glyph->cellInfo; ccinfo = (CacheCellInfo *) glyph->cellInfo;
if (ccinfo != NULL) { if (ccinfo != NULL) {
@ -413,24 +407,31 @@ OGLTR_UpdateLCDTextColor(jint contrast)
* gamma lookup table textures. * gamma lookup table textures.
*/ */
static jboolean static jboolean
OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, jint contrast) OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID,
GLuint dstTextureID,
jint contrast)
{ {
// bind the texture containing glyph data to texture unit 0 // bind the texture containing glyph data to texture unit 0
j2d_glActiveTextureARB(GL_TEXTURE0_ARB); j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID); j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID);
j2d_glEnable(GL_TEXTURE_2D);
// bind the texture tile containing destination data to texture unit 1 // bind the texture tile containing destination data to texture unit 1
j2d_glActiveTextureARB(GL_TEXTURE1_ARB); j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
if (cachedDestTextureID == 0) { if (dstTextureID != 0) {
cachedDestTextureID = j2d_glBindTexture(GL_TEXTURE_2D, dstTextureID);
OGLContext_CreateBlitTexture(GL_RGB8, GL_RGB, } else {
OGLTR_CACHED_DEST_WIDTH,
OGLTR_CACHED_DEST_HEIGHT);
if (cachedDestTextureID == 0) { if (cachedDestTextureID == 0) {
return JNI_FALSE; cachedDestTextureID =
OGLContext_CreateBlitTexture(GL_RGB8, GL_RGB,
OGLTR_CACHED_DEST_WIDTH,
OGLTR_CACHED_DEST_HEIGHT);
if (cachedDestTextureID == 0) {
return JNI_FALSE;
}
} }
j2d_glBindTexture(GL_TEXTURE_2D, cachedDestTextureID);
} }
j2d_glBindTexture(GL_TEXTURE_2D, cachedDestTextureID);
// note that GL_TEXTURE_2D was already enabled for texture unit 0, // note that GL_TEXTURE_2D was already enabled for texture unit 0,
// but we need to explicitly enable it for texture unit 1 // but we need to explicitly enable it for texture unit 1
@ -472,14 +473,14 @@ OGLTR_EnableGlyphVertexCache(OGLContext *oglc)
return; return;
} }
if (glyphCache == NULL) { if (glyphCacheAA == NULL) {
if (!OGLTR_InitGlyphCache(JNI_FALSE)) { if (!OGLTR_InitGlyphCache(JNI_FALSE)) {
return; return;
} }
} }
j2d_glEnable(GL_TEXTURE_2D); j2d_glEnable(GL_TEXTURE_2D);
j2d_glBindTexture(GL_TEXTURE_2D, glyphCache->cacheID); j2d_glBindTexture(GL_TEXTURE_2D, glyphCacheAA->cacheID);
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// for grayscale/monochrome text, the current OpenGL source color // for grayscale/monochrome text, the current OpenGL source color
@ -522,6 +523,7 @@ OGLTR_DisableGlyphModeState()
j2d_glActiveTextureARB(GL_TEXTURE1_ARB); j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
j2d_glDisable(GL_TEXTURE_2D); j2d_glDisable(GL_TEXTURE_2D);
j2d_glActiveTextureARB(GL_TEXTURE0_ARB); j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
j2d_glDisable(GL_TEXTURE_2D);
break; break;
case MODE_NO_CACHE_GRAY: case MODE_NO_CACHE_GRAY:
@ -547,7 +549,7 @@ OGLTR_DrawGrayscaleGlyphViaCache(OGLContext *oglc,
if (ginfo->cellInfo == NULL) { if (ginfo->cellInfo == NULL) {
// attempt to add glyph to accelerated glyph cache // attempt to add glyph to accelerated glyph cache
OGLTR_AddToGlyphCache(ginfo, JNI_FALSE); OGLTR_AddToGlyphCache(ginfo, GL_LUMINANCE);
if (ginfo->cellInfo == NULL) { if (ginfo->cellInfo == NULL) {
// we'll just no-op in the rare case that the cell is NULL // we'll just no-op in the rare case that the cell is NULL
@ -707,7 +709,8 @@ static jboolean
OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps, OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
GlyphInfo *ginfo, jint x, jint y, GlyphInfo *ginfo, jint x, jint y,
jint glyphIndex, jint totalGlyphs, jint glyphIndex, jint totalGlyphs,
jboolean rgbOrder, jint contrast) jboolean rgbOrder, jint contrast,
GLuint dstTextureID)
{ {
CacheCellInfo *cell; CacheCellInfo *cell;
jint dx1, dy1, dx2, dy2; jint dx1, dy1, dx2, dy2;
@ -718,7 +721,7 @@ OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
CHECK_PREVIOUS_OP(GL_TEXTURE_2D); CHECK_PREVIOUS_OP(GL_TEXTURE_2D);
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (glyphCache == NULL) { if (glyphCacheLCD == NULL) {
if (!OGLTR_InitGlyphCache(JNI_TRUE)) { if (!OGLTR_InitGlyphCache(JNI_TRUE)) {
return JNI_FALSE; return JNI_FALSE;
} }
@ -727,11 +730,13 @@ OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
if (rgbOrder != lastRGBOrder) { if (rgbOrder != lastRGBOrder) {
// need to invalidate the cache in this case; see comments // need to invalidate the cache in this case; see comments
// for lastRGBOrder above // for lastRGBOrder above
AccelGlyphCache_Invalidate(glyphCache); AccelGlyphCache_Invalidate(glyphCacheLCD);
lastRGBOrder = rgbOrder; lastRGBOrder = rgbOrder;
} }
if (!OGLTR_EnableLCDGlyphModeState(glyphCache->cacheID, contrast)) { if (!OGLTR_EnableLCDGlyphModeState(glyphCacheLCD->cacheID,
dstTextureID, contrast))
{
return JNI_FALSE; return JNI_FALSE;
} }
@ -750,7 +755,7 @@ OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
j2d_glActiveTextureARB(GL_TEXTURE0_ARB); j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
// attempt to add glyph to accelerated glyph cache // attempt to add glyph to accelerated glyph cache
OGLTR_AddToGlyphCache(ginfo, rgbOrder); OGLTR_AddToGlyphCache(ginfo, rgbOrder ? GL_RGB : GL_BGR);
if (ginfo->cellInfo == NULL) { if (ginfo->cellInfo == NULL) {
// we'll just no-op in the rare case that the cell is NULL // we'll just no-op in the rare case that the cell is NULL
@ -767,16 +772,34 @@ OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
dx2 = dx1 + ginfo->width; dx2 = dx1 + ginfo->width;
dy2 = dy1 + ginfo->height; dy2 = dy1 + ginfo->height;
// copy destination into second cached texture, if necessary if (dstTextureID == 0) {
OGLTR_UpdateCachedDestination(dstOps, ginfo, // copy destination into second cached texture, if necessary
dx1, dy1, dx2, dy2, OGLTR_UpdateCachedDestination(dstOps, ginfo,
glyphIndex, totalGlyphs); dx1, dy1, dx2, dy2,
glyphIndex, totalGlyphs);
// texture coordinates of the destination tile // texture coordinates of the destination tile
dtx1 = ((jfloat)(dx1 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH; dtx1 = ((jfloat)(dx1 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH;
dty1 = ((jfloat)(cachedDestBounds.y2 - dy1)) / OGLTR_CACHED_DEST_HEIGHT; dty1 = ((jfloat)(cachedDestBounds.y2 - dy1)) / OGLTR_CACHED_DEST_HEIGHT;
dtx2 = ((jfloat)(dx2 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH; dtx2 = ((jfloat)(dx2 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH;
dty2 = ((jfloat)(cachedDestBounds.y2 - dy2)) / OGLTR_CACHED_DEST_HEIGHT; dty2 = ((jfloat)(cachedDestBounds.y2 - dy2)) / OGLTR_CACHED_DEST_HEIGHT;
} else {
jint gw = ginfo->width;
jint gh = ginfo->height;
// this accounts for lower-left origin of the destination region
jint dxadj = dstOps->xOffset + x;
jint dyadj = dstOps->yOffset + dstOps->height - (y + gh);
// update the remaining destination texture coordinates
dtx1 =((GLfloat)dxadj) / dstOps->textureWidth;
dtx2 = ((GLfloat)dxadj + gw) / dstOps->textureWidth;
dty1 = ((GLfloat)dyadj + gh) / dstOps->textureHeight;
dty2 = ((GLfloat)dyadj) / dstOps->textureHeight;
j2d_glTextureBarrierNV();
}
// render composed texture to the destination surface // render composed texture to the destination surface
j2d_glBegin(GL_QUADS); j2d_glBegin(GL_QUADS);
@ -837,7 +860,8 @@ static jboolean
OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps, OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps,
GlyphInfo *ginfo, jint x, jint y, GlyphInfo *ginfo, jint x, jint y,
jint rowBytesOffset, jint rowBytesOffset,
jboolean rgbOrder, jint contrast) jboolean rgbOrder, jint contrast,
GLuint dstTextureID)
{ {
GLfloat tx1, ty1, tx2, ty2; GLfloat tx1, ty1, tx2, ty2;
GLfloat dtx1, dty1, dtx2, dty2; GLfloat dtx1, dty1, dtx2, dty2;
@ -859,7 +883,9 @@ OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps,
} }
} }
if (!OGLTR_EnableLCDGlyphModeState(oglc->blitTextureID, contrast)) { if (!OGLTR_EnableLCDGlyphModeState(oglc->blitTextureID,
dstTextureID, contrast))
{
return JNI_FALSE; return JNI_FALSE;
} }
@ -907,18 +933,29 @@ OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps,
dxadj = dstOps->xOffset + x; dxadj = dstOps->xOffset + x;
dyadj = dstOps->yOffset + dstOps->height - (y + sh); dyadj = dstOps->yOffset + dstOps->height - (y + sh);
// copy destination into cached texture tile (the lower-left if (dstTextureID == 0) {
// corner of the destination region will be positioned at the // copy destination into cached texture tile (the lower-left
// lower-left corner (0,0) of the texture) // corner of the destination region will be positioned at the
j2d_glActiveTextureARB(GL_TEXTURE1_ARB); // lower-left corner (0,0) of the texture)
j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0, j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
0, 0, j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
dxadj, dyadj, 0, 0,
sw, sh); dxadj, dyadj,
sw, sh);
// update the remaining destination texture coordinates
dtx2 = ((GLfloat)sw) / OGLTR_CACHED_DEST_WIDTH;
dty1 = ((GLfloat)sh) / OGLTR_CACHED_DEST_HEIGHT;
} else {
// use the destination texture directly
// update the remaining destination texture coordinates
dtx1 =((GLfloat)dxadj) / dstOps->textureWidth;
dtx2 = ((GLfloat)dxadj + sw) / dstOps->textureWidth;
// update the remaining destination texture coordinates dty1 = ((GLfloat)dyadj + sh) / dstOps->textureHeight;
dtx2 = ((GLfloat)sw) / OGLTR_CACHED_DEST_WIDTH; dty2 = ((GLfloat)dyadj) / dstOps->textureHeight;
dty1 = ((GLfloat)sh) / OGLTR_CACHED_DEST_HEIGHT;
j2d_glTextureBarrierNV();
}
// render composed texture to the destination surface // render composed texture to the destination surface
j2d_glBegin(GL_QUADS); j2d_glBegin(GL_QUADS);
@ -953,6 +990,7 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
unsigned char *images, unsigned char *positions) unsigned char *images, unsigned char *positions)
{ {
int glyphCounter; int glyphCounter;
GLuint dstTextureID = 0;
J2dTraceLn(J2D_TRACE_INFO, "OGLTR_DrawGlyphList"); J2dTraceLn(J2D_TRACE_INFO, "OGLTR_DrawGlyphList");
@ -966,6 +1004,27 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
glyphMode = MODE_NOT_INITED; glyphMode = MODE_NOT_INITED;
isCachedDestValid = JNI_FALSE; isCachedDestValid = JNI_FALSE;
// We have to obtain an information about destination content
// in order to render lcd glyphs. It could be done by copying
// a part of desitination buffer into an intermediate texture
// using glCopyTexSubImage2D(). However, on macosx this path is
// slow, and it dramatically reduces the overall speed of lcd
// text rendering.
//
// In some cases, we can use a texture from the destination
// surface data in oredr to avoid this slow reading routine.
// It requires:
// * An appropriate textureTarget for the destination SD.
// In particular, we need GL_TEXTURE_2D
// * Means to prevent read-after-write problem.
// At the moment, a GL_NV_texture_barrier extension is used
// to achieve this.
if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_TEXBARRIER) &&
dstOps->textureTarget == GL_TEXTURE_2D)
{
dstTextureID = dstOps->textureID;
}
for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) {
jint x, y; jint x, y;
jfloat glyphx, glyphy; jfloat glyphx, glyphy;
@ -1003,8 +1062,7 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
if (grayscale) { if (grayscale) {
// grayscale or monochrome glyph data // grayscale or monochrome glyph data
if (cacheStatus != CACHE_LCD && if (ginfo->width <= OGLTR_CACHE_CELL_WIDTH &&
ginfo->width <= OGLTR_CACHE_CELL_WIDTH &&
ginfo->height <= OGLTR_CACHE_CELL_HEIGHT) ginfo->height <= OGLTR_CACHE_CELL_HEIGHT)
{ {
ok = OGLTR_DrawGrayscaleGlyphViaCache(oglc, ginfo, x, y); ok = OGLTR_DrawGrayscaleGlyphViaCache(oglc, ginfo, x, y);
@ -1024,19 +1082,20 @@ OGLTR_DrawGlyphList(JNIEnv *env, OGLContext *oglc, OGLSDOps *dstOps,
} }
if (rowBytesOffset == 0 && if (rowBytesOffset == 0 &&
cacheStatus != CACHE_GRAY &&
ginfo->width <= OGLTR_CACHE_CELL_WIDTH && ginfo->width <= OGLTR_CACHE_CELL_WIDTH &&
ginfo->height <= OGLTR_CACHE_CELL_HEIGHT) ginfo->height <= OGLTR_CACHE_CELL_HEIGHT)
{ {
ok = OGLTR_DrawLCDGlyphViaCache(oglc, dstOps, ok = OGLTR_DrawLCDGlyphViaCache(oglc, dstOps,
ginfo, x, y, ginfo, x, y,
glyphCounter, totalGlyphs, glyphCounter, totalGlyphs,
rgbOrder, lcdContrast); rgbOrder, lcdContrast,
dstTextureID);
} else { } else {
ok = OGLTR_DrawLCDGlyphNoCache(oglc, dstOps, ok = OGLTR_DrawLCDGlyphNoCache(oglc, dstOps,
ginfo, x, y, ginfo, x, y,
rowBytesOffset, rowBytesOffset,
rgbOrder, lcdContrast); rgbOrder, lcdContrast,
dstTextureID);
} }
} }