< prev index next >

src/java.desktop/share/native/common/java2d/opengl/OGLTextRenderer.c

Print this page

        

*** 44,55 **** * The following constants define the inner and outer bounds of the * accelerated glyph cache. */ #define OGLTR_CACHE_WIDTH 512 #define OGLTR_CACHE_HEIGHT 512 ! #define OGLTR_CACHE_CELL_WIDTH 16 ! #define OGLTR_CACHE_CELL_HEIGHT 16 /** * The current "glyph mode" state. This variable is used to track the * codepath used to render a particular glyph. This variable is reset to * MODE_NOT_INITED at the beginning of every call to OGLTR_DrawGlyphList(). --- 44,55 ---- * The following constants define the inner and outer bounds of the * accelerated glyph cache. */ #define OGLTR_CACHE_WIDTH 512 #define OGLTR_CACHE_HEIGHT 512 ! #define OGLTR_CACHE_CELL_WIDTH 32 ! #define OGLTR_CACHE_CELL_HEIGHT 32 /** * The current "glyph mode" state. This variable is used to track the * codepath used to render a particular glyph. This variable is reset to * MODE_NOT_INITED at the beginning of every call to OGLTR_DrawGlyphList().
*** 66,95 **** MODE_NO_CACHE_LCD } GlyphMode; static GlyphMode glyphMode = MODE_NOT_INITED; /** ! * This enum indicates the current state of the hardware glyph cache. ! * Initially the CacheStatus is set to CACHE_NOT_INITED, and then it is ! * set to either GRAY or LCD when the glyph cache is initialized. ! */ ! 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 * environment, since the glyph cache texture is shared between all contexts, * and (in theory) OpenGL drivers should be smart enough to manage that * texture across all screens. */ ! static GlyphCacheInfo *glyphCache = NULL; /** * The handle to the LCD text fragment program object. */ static GLhandleARB lcdTextProgram = 0; --- 66,86 ---- MODE_NO_CACHE_LCD } 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) OpenGL drivers should be smart enough to manage that * texture across all screens. */ ! ! static GlyphCacheInfo *glyphCacheLCD = NULL; ! static GlyphCacheInfo *glyphCacheAA = NULL; /** * The handle to the LCD text fragment program object. */ static GLhandleARB lcdTextProgram = 0;
*** 136,146 **** * (OGLTR_CACHED_DEST_WIDTH >= OGLTR_NOCACHE_TILE_SIZE) && * (OGLTR_CACHED_DEST_HEIGHT >= OGLTR_CACHE_CELL_HEIGHT) && * (OGLTR_CACHED_DEST_HEIGHT >= OGLTR_NOCACHE_TILE_SIZE) */ #define OGLTR_CACHED_DEST_WIDTH 512 ! #define OGLTR_CACHED_DEST_HEIGHT 32 /** * The handle to the "cached destination" texture object. */ static GLuint cachedDestTextureID = 0; --- 127,137 ---- * (OGLTR_CACHED_DEST_WIDTH >= OGLTR_NOCACHE_TILE_SIZE) && * (OGLTR_CACHED_DEST_HEIGHT >= OGLTR_CACHE_CELL_HEIGHT) && * (OGLTR_CACHED_DEST_HEIGHT >= OGLTR_NOCACHE_TILE_SIZE) */ #define OGLTR_CACHED_DEST_WIDTH 512 ! #define OGLTR_CACHED_DEST_HEIGHT (OGLTR_CACHE_CELL_HEIGHT * 2) /** * The handle to the "cached destination" texture object. */ static GLuint cachedDestTextureID = 0;
*** 210,248 **** j2d_glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, OGLTR_CACHE_WIDTH, OGLTR_CACHE_HEIGHT, 0, pixelFormat, GL_UNSIGNED_BYTE, NULL); ! cacheStatus = (lcdCache ? CACHE_LCD : CACHE_GRAY); ! glyphCache = gcinfo; return JNI_TRUE; } /** * Adds the given glyph to the glyph cache (texture and data structure) * associated with the given OGLContext. */ static void ! OGLTR_AddToGlyphCache(GlyphInfo *glyph, jboolean rgbOrder) { - GLenum pixelFormat; CacheCellInfo *ccinfo; J2dTraceLn(J2D_TRACE_INFO, "OGLTR_AddToGlyphCache"); ! if ((glyphCache == NULL) || (glyph->image == NULL)) { ! return; } ! if (cacheStatus == CACHE_LCD) { ! pixelFormat = rgbOrder ? GL_RGB : GL_BGR; ! } else { ! pixelFormat = GL_LUMINANCE; } ! AccelGlyphCache_AddGlyph(glyphCache, glyph); ccinfo = (CacheCellInfo *) glyph->cellInfo; if (ccinfo != NULL) { // store glyph image in texture cell j2d_glTexSubImage2D(GL_TEXTURE_2D, 0, --- 201,242 ---- j2d_glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, OGLTR_CACHE_WIDTH, OGLTR_CACHE_HEIGHT, 0, pixelFormat, GL_UNSIGNED_BYTE, NULL); ! if (lcdCache) { ! glyphCacheLCD = gcinfo; ! } else { ! glyphCacheAA = gcinfo; ! } return JNI_TRUE; } /** * Adds the given glyph to the glyph cache (texture and data structure) * associated with the given OGLContext. */ static void ! OGLTR_AddToGlyphCache(GlyphInfo *glyph, GLenum pixelFormat) { CacheCellInfo *ccinfo; + GlyphCacheInfo *gcinfo; J2dTraceLn(J2D_TRACE_INFO, "OGLTR_AddToGlyphCache"); ! if (pixelFormat == GL_LUMINANCE) { ! gcinfo = glyphCacheAA; ! } else { ! gcinfo = glyphCacheLCD; } ! if ((gcinfo == NULL) || (glyph->image == NULL)) { ! return; } ! AccelGlyphCache_AddGlyph(gcinfo, glyph); ccinfo = (CacheCellInfo *) glyph->cellInfo; if (ccinfo != NULL) { // store glyph image in texture cell j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
*** 411,438 **** /** * Enables the LCD text shader and updates any related state, such as the * gamma lookup table textures. */ static jboolean ! OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, jint contrast) { // bind the texture containing glyph data to texture unit 0 j2d_glActiveTextureARB(GL_TEXTURE0_ARB); j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID); // bind the texture tile containing destination data to texture unit 1 j2d_glActiveTextureARB(GL_TEXTURE1_ARB); if (cachedDestTextureID == 0) { 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); // note that GL_TEXTURE_2D was already enabled for texture unit 0, // but we need to explicitly enable it for texture unit 1 j2d_glEnable(GL_TEXTURE_2D); --- 405,439 ---- /** * Enables the LCD text shader and updates any related state, such as the * gamma lookup table textures. */ static jboolean ! OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, ! GLuint dstTextureID, ! jint contrast) { // bind the texture containing glyph data to texture unit 0 j2d_glActiveTextureARB(GL_TEXTURE0_ARB); j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID); + j2d_glEnable(GL_TEXTURE_2D); // bind the texture tile containing destination data to texture unit 1 j2d_glActiveTextureARB(GL_TEXTURE1_ARB); + if (dstTextureID != 0) { + j2d_glBindTexture(GL_TEXTURE_2D, dstTextureID); + } else { if (cachedDestTextureID == 0) { 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); + } // note that GL_TEXTURE_2D was already enabled for texture unit 0, // but we need to explicitly enable it for texture unit 1 j2d_glEnable(GL_TEXTURE_2D);
*** 470,487 **** if (!OGLVertexCache_InitVertexCache(oglc)) { return; } ! if (glyphCache == NULL) { if (!OGLTR_InitGlyphCache(JNI_FALSE)) { return; } } j2d_glEnable(GL_TEXTURE_2D); ! j2d_glBindTexture(GL_TEXTURE_2D, glyphCache->cacheID); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // for grayscale/monochrome text, the current OpenGL source color // is modulated with the glyph image as part of the texture // application stage, so we use GL_MODULATE here --- 471,488 ---- if (!OGLVertexCache_InitVertexCache(oglc)) { return; } ! if (glyphCacheAA == NULL) { if (!OGLTR_InitGlyphCache(JNI_FALSE)) { return; } } j2d_glEnable(GL_TEXTURE_2D); ! j2d_glBindTexture(GL_TEXTURE_2D, glyphCacheAA->cacheID); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // for grayscale/monochrome text, the current OpenGL source color // is modulated with the glyph image as part of the texture // application stage, so we use GL_MODULATE here
*** 520,529 **** --- 521,531 ---- j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4); j2d_glUseProgramObjectARB(0); j2d_glActiveTextureARB(GL_TEXTURE1_ARB); j2d_glDisable(GL_TEXTURE_2D); j2d_glActiveTextureARB(GL_TEXTURE0_ARB); + j2d_glDisable(GL_TEXTURE_2D); break; case MODE_NO_CACHE_GRAY: case MODE_USE_CACHE_GRAY: case MODE_NOT_INITED:
*** 545,555 **** glyphMode = MODE_USE_CACHE_GRAY; } if (ginfo->cellInfo == NULL) { // attempt to add glyph to accelerated glyph cache ! OGLTR_AddToGlyphCache(ginfo, JNI_FALSE); if (ginfo->cellInfo == NULL) { // we'll just no-op in the rare case that the cell is NULL return JNI_TRUE; } --- 547,557 ---- glyphMode = MODE_USE_CACHE_GRAY; } if (ginfo->cellInfo == NULL) { // attempt to add glyph to accelerated glyph cache ! OGLTR_AddToGlyphCache(ginfo, GL_LUMINANCE); if (ginfo->cellInfo == NULL) { // we'll just no-op in the rare case that the cell is NULL return JNI_TRUE; }
*** 705,739 **** static jboolean OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps, GlyphInfo *ginfo, jint x, jint y, jint glyphIndex, jint totalGlyphs, ! jboolean rgbOrder, jint contrast) { CacheCellInfo *cell; jint dx1, dy1, dx2, dy2; jfloat dtx1, dty1, dtx2, dty2; if (glyphMode != MODE_USE_CACHE_LCD) { OGLTR_DisableGlyphModeState(); CHECK_PREVIOUS_OP(GL_TEXTURE_2D); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ! if (glyphCache == NULL) { if (!OGLTR_InitGlyphCache(JNI_TRUE)) { return JNI_FALSE; } } if (rgbOrder != lastRGBOrder) { // need to invalidate the cache in this case; see comments // for lastRGBOrder above ! AccelGlyphCache_Invalidate(glyphCache); lastRGBOrder = rgbOrder; } ! if (!OGLTR_EnableLCDGlyphModeState(glyphCache->cacheID, contrast)) { return JNI_FALSE; } // when a fragment shader is enabled, the texture function state is // ignored, so the following line is not needed... --- 707,744 ---- static jboolean OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps, GlyphInfo *ginfo, jint x, jint y, jint glyphIndex, jint totalGlyphs, ! jboolean rgbOrder, jint contrast, ! GLuint dstTextureID) { CacheCellInfo *cell; jint dx1, dy1, dx2, dy2; jfloat dtx1, dty1, dtx2, dty2; if (glyphMode != MODE_USE_CACHE_LCD) { OGLTR_DisableGlyphModeState(); CHECK_PREVIOUS_OP(GL_TEXTURE_2D); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ! if (glyphCacheLCD == NULL) { if (!OGLTR_InitGlyphCache(JNI_TRUE)) { return JNI_FALSE; } } if (rgbOrder != lastRGBOrder) { // need to invalidate the cache in this case; see comments // for lastRGBOrder above ! AccelGlyphCache_Invalidate(glyphCacheLCD); lastRGBOrder = rgbOrder; } ! if (!OGLTR_EnableLCDGlyphModeState(glyphCacheLCD->cacheID, ! dstTextureID, contrast)) ! { return JNI_FALSE; } // when a fragment shader is enabled, the texture function state is // ignored, so the following line is not needed...
*** 748,758 **** // make sure the glyph cache texture is bound to texture unit 0 j2d_glActiveTextureARB(GL_TEXTURE0_ARB); // attempt to add glyph to accelerated glyph cache ! OGLTR_AddToGlyphCache(ginfo, rgbOrder); if (ginfo->cellInfo == NULL) { // we'll just no-op in the rare case that the cell is NULL return JNI_TRUE; } --- 753,763 ---- // make sure the glyph cache texture is bound to texture unit 0 j2d_glActiveTextureARB(GL_TEXTURE0_ARB); // attempt to add glyph to accelerated glyph cache ! OGLTR_AddToGlyphCache(ginfo, rgbOrder ? GL_RGB : GL_BGR); if (ginfo->cellInfo == NULL) { // we'll just no-op in the rare case that the cell is NULL return JNI_TRUE; }
*** 765,784 **** --- 770,807 ---- dx1 = x; dy1 = y; dx2 = dx1 + ginfo->width; dy2 = dy1 + ginfo->height; + if (dstTextureID == 0) { // copy destination into second cached texture, if necessary OGLTR_UpdateCachedDestination(dstOps, ginfo, dx1, dy1, dx2, dy2, glyphIndex, totalGlyphs); // texture coordinates of the destination tile dtx1 = ((jfloat)(dx1 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH; dty1 = ((jfloat)(cachedDestBounds.y2 - dy1)) / OGLTR_CACHED_DEST_HEIGHT; dtx2 = ((jfloat)(dx2 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH; 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 j2d_glBegin(GL_QUADS); j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, cell->tx1, cell->ty1); j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty1);
*** 835,845 **** static jboolean OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps, GlyphInfo *ginfo, jint x, jint y, jint rowBytesOffset, ! jboolean rgbOrder, jint contrast) { GLfloat tx1, ty1, tx2, ty2; GLfloat dtx1, dty1, dtx2, dty2; jint tw, th; jint sx, sy, sw, sh, dxadj, dyadj; --- 858,869 ---- static jboolean OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps, GlyphInfo *ginfo, jint x, jint y, jint rowBytesOffset, ! jboolean rgbOrder, jint contrast, ! GLuint dstTextureID) { GLfloat tx1, ty1, tx2, ty2; GLfloat dtx1, dty1, dtx2, dty2; jint tw, th; jint sx, sy, sw, sh, dxadj, dyadj;
*** 857,867 **** if (!OGLContext_InitBlitTileTexture(oglc)) { return JNI_FALSE; } } ! if (!OGLTR_EnableLCDGlyphModeState(oglc->blitTextureID, contrast)) { return JNI_FALSE; } // when a fragment shader is enabled, the texture function state is // ignored, so the following line is not needed... --- 881,893 ---- if (!OGLContext_InitBlitTileTexture(oglc)) { return JNI_FALSE; } } ! if (!OGLTR_EnableLCDGlyphModeState(oglc->blitTextureID, ! dstTextureID, contrast)) ! { return JNI_FALSE; } // when a fragment shader is enabled, the texture function state is // ignored, so the following line is not needed...
*** 905,926 **** // this accounts for lower-left origin of the destination region dxadj = dstOps->xOffset + x; dyadj = dstOps->yOffset + dstOps->height - (y + sh); // copy destination into cached texture tile (the lower-left // corner of the destination region will be positioned at the // lower-left corner (0,0) of the texture) j2d_glActiveTextureARB(GL_TEXTURE1_ARB); j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, dxadj, dyadj, sw, sh); - // update the remaining destination texture coordinates dtx2 = ((GLfloat)sw) / OGLTR_CACHED_DEST_WIDTH; dty1 = ((GLfloat)sh) / OGLTR_CACHED_DEST_HEIGHT; // render composed texture to the destination surface j2d_glBegin(GL_QUADS); j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, tx1, ty1); j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty1); --- 931,963 ---- // this accounts for lower-left origin of the destination region dxadj = dstOps->xOffset + x; dyadj = dstOps->yOffset + dstOps->height - (y + sh); + if (dstTextureID == 0) { // copy destination into cached texture tile (the lower-left // corner of the destination region will be positioned at the // lower-left corner (0,0) of the texture) j2d_glActiveTextureARB(GL_TEXTURE1_ARB); j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 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) / ((GLfloat)dstOps->textureWidth); + dtx2 = ((GLfloat)dxadj + sw) / ((GLfloat)dstOps->textureWidth); + + dty1 = ((GLfloat)dyadj + sh) / ((GLfloat)dstOps->textureHeight); + dty2 = ((GLfloat)dyadj) / ((GLfloat)dstOps->textureHeight); + + j2d_glTextureBarrierNV(); + } // render composed texture to the destination surface j2d_glBegin(GL_QUADS); j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, tx1, ty1); j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty1);
*** 951,960 **** --- 988,998 ---- jboolean subPixPos, jboolean rgbOrder, jint lcdContrast, jfloat glyphListOrigX, jfloat glyphListOrigY, unsigned char *images, unsigned char *positions) { int glyphCounter; + GLuint dstTextureID = 0; J2dTraceLn(J2D_TRACE_INFO, "OGLTR_DrawGlyphList"); RETURN_IF_NULL(oglc); RETURN_IF_NULL(dstOps);
*** 964,973 **** --- 1002,1017 ---- } glyphMode = MODE_NOT_INITED; isCachedDestValid = JNI_FALSE; + if (OGLC_IS_CAP_PRESENT(oglc, CAPS_EXT_TEXBARRIER) && + dstOps->textureTarget == GL_TEXTURE_2D) + { + dstTextureID = dstOps->textureID; + } + for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { jint x, y; jfloat glyphx, glyphy; jboolean grayscale, ok; GlyphInfo *ginfo = (GlyphInfo *)jlong_to_ptr(NEXT_LONG(images));
*** 1001,1012 **** continue; } if (grayscale) { // grayscale or monochrome glyph data ! if (cacheStatus != CACHE_LCD && ! ginfo->width <= OGLTR_CACHE_CELL_WIDTH && ginfo->height <= OGLTR_CACHE_CELL_HEIGHT) { ok = OGLTR_DrawGrayscaleGlyphViaCache(oglc, ginfo, x, y); } else { ok = OGLTR_DrawGrayscaleGlyphNoCache(oglc, ginfo, x, y); --- 1045,1055 ---- continue; } if (grayscale) { // grayscale or monochrome glyph data ! if (ginfo->width <= OGLTR_CACHE_CELL_WIDTH && ginfo->height <= OGLTR_CACHE_CELL_HEIGHT) { ok = OGLTR_DrawGrayscaleGlyphViaCache(oglc, ginfo, x, y); } else { ok = OGLTR_DrawGrayscaleGlyphNoCache(oglc, ginfo, x, y);
*** 1022,1044 **** x += 1; } } if (rowBytesOffset == 0 && - cacheStatus != CACHE_GRAY && ginfo->width <= OGLTR_CACHE_CELL_WIDTH && ginfo->height <= OGLTR_CACHE_CELL_HEIGHT) { ok = OGLTR_DrawLCDGlyphViaCache(oglc, dstOps, ginfo, x, y, glyphCounter, totalGlyphs, ! rgbOrder, lcdContrast); } else { ok = OGLTR_DrawLCDGlyphNoCache(oglc, dstOps, ginfo, x, y, rowBytesOffset, ! rgbOrder, lcdContrast); } } if (!ok) { break; --- 1065,1088 ---- x += 1; } } if (rowBytesOffset == 0 && ginfo->width <= OGLTR_CACHE_CELL_WIDTH && ginfo->height <= OGLTR_CACHE_CELL_HEIGHT) { ok = OGLTR_DrawLCDGlyphViaCache(oglc, dstOps, ginfo, x, y, glyphCounter, totalGlyphs, ! rgbOrder, lcdContrast, ! dstTextureID); } else { ok = OGLTR_DrawLCDGlyphNoCache(oglc, dstOps, ginfo, x, y, rowBytesOffset, ! rgbOrder, lcdContrast, ! dstTextureID); } } if (!ok) { break;
< prev index next >