--- /dev/null 2019-03-05 14:31:17.000000000 +0300 +++ new/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m 2019-03-05 14:31:17.000000000 +0300 @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef HEADLESS + +#include +#include +#include +#include + +#include "sun_java2d_metal_MTLTextRenderer.h" + +#include "SurfaceData.h" +#include "MTLContext.h" +#include "MTLRenderQueue.h" +#include "MTLTextRenderer.h" +#include "MTLVertexCache.h" +#include "AccelGlyphCache.h" + +/** + * The following constants define the inner and outer bounds of the + * accelerated glyph cache. + */ +#define MTLTR_CACHE_WIDTH 1024 +#define MTLTR_CACHE_HEIGHT 1024 +#define MTLTR_CACHE_CELL_WIDTH 64 +#define MTLTR_CACHE_CELL_HEIGHT 64 + +/** + * 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 MTLTR_DrawGlyphList(). + * As each glyph is rendered, the glyphMode variable is updated to reflect + * the current mode, so if the current mode is the same as the mode used + * to render the previous glyph, we can avoid doing costly setup operations + * each time. + */ +typedef enum { + MODE_NOT_INITED, + MODE_USE_CACHE_GRAY, + MODE_USE_CACHE_LCD, + MODE_NO_CACHE_GRAY, + MODE_NO_CACHE_LCD, + MODE_NO_CACHE_COLOR +} 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; + +/** + * This value tracks the previous LCD contrast setting, so if the contrast + * value hasn't changed since the last time the gamma uniforms were + * updated (not very common), then we can skip updating the unforms. + */ +static jint lastLCDContrast = -1; + +/** + * 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 + * invalidate the cache, which may already store glyph images in the reverse + * order. Note that in most real world applications this value will not + * change over the course of the application, but tests like Font2DTest + * allow for changing the ordering at runtime, so we need to handle that case. + */ +static jboolean lastRGBOrder = JNI_TRUE; + +/** + * This constant defines the size of the tile to use in the + * MTLTR_DrawLCDGlyphNoCache() method. See below for more on why we + * restrict this value to a particular size. + */ +#define MTLTR_NOCACHE_TILE_SIZE 64 + +/** + * These constants define the size of the "cached destination" texture. + * This texture is only used when rendering LCD-optimized text, as that + * codepath needs direct access to the destination. There is no way to + * access the framebuffer directly from an OpenGL shader, so we need to first + * copy the destination region corresponding to a particular glyph into + * this cached texture, and then that texture will be accessed inside the + * shader. Copying the destination into this cached texture can be a very + * expensive operation (accounting for about half the rendering time for + * LCD text), so to mitigate this cost we try to bulk read a horizontal + * region of the destination at a time. (These values are empirically + * derived for the common case where text runs horizontally.) + * + * Note: It is assumed in various calculations below that: + * (MTLTR_CACHED_DEST_WIDTH >= MTLTR_CACHE_CELL_WIDTH) && + * (MTLTR_CACHED_DEST_WIDTH >= MTLTR_NOCACHE_TILE_SIZE) && + * (MTLTR_CACHED_DEST_HEIGHT >= MTLTR_CACHE_CELL_HEIGHT) && + * (MTLTR_CACHED_DEST_HEIGHT >= MTLTR_NOCACHE_TILE_SIZE) + */ +#define MTLTR_CACHED_DEST_WIDTH 1024 +#define MTLTR_CACHED_DEST_HEIGHT (MTLTR_CACHE_CELL_HEIGHT * 2) + +/** + * The handle to the "cached destination" texture object. + */ +static GLuint cachedDestTextureID = 0; + +/** + * The current bounds of the "cached destination" texture, in destination + * coordinate space. The width/height of these bounds will not exceed the + * MTLTR_CACHED_DEST_WIDTH/HEIGHT values defined above. These bounds are + * only considered valid when the isCachedDestValid flag is JNI_TRUE. + */ +static SurfaceDataBounds cachedDestBounds; + +/** + * This flag indicates whether the "cached destination" texture contains + * valid data. This flag is reset to JNI_FALSE at the beginning of every + * call to MTLTR_DrawGlyphList(). Once we copy valid destination data + * into the cached texture, this flag is set to JNI_TRUE. This way, we can + * limit the number of times we need to copy destination data, which is a + * very costly operation. + */ +static jboolean isCachedDestValid = JNI_FALSE; + +/** + * The bounds of the previously rendered LCD glyph, in destination + * coordinate space. We use these bounds to determine whether the glyph + * currently being rendered overlaps the previously rendered glyph (i.e. + * its bounding box intersects that of the previously rendered glyph). If + * so, we need to re-read the destination area associated with that previous + * glyph so that we can correctly blend with the actual destination data. + */ +static SurfaceDataBounds previousGlyphBounds; + +/** + * Initializes the one glyph cache (texture and data structure). + * If lcdCache is JNI_TRUE, the texture will contain RGB data, + * otherwise we will simply store the grayscale/monochrome glyph images + * as intensity values (which work well with the GL_MODULATE function). + */ +static jboolean +MTLTR_InitGlyphCache(jboolean lcdCache) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_InitGlyphCache"); + + return JNI_TRUE; +} + +/** + * Adds the given glyph to the glyph cache (texture and data structure) + * associated with the given MTLContext. + */ +static void +MTLTR_AddTmTLyphCache(GlyphInfo *glyph, GLenum pixelFormat) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_AddTmTLyphCache"); + + CacheCellInfo *ccinfo; + GlyphCacheInfo *gcinfo; + + J2dTraceLn(J2D_TRACE_INFO, "MTLTR_AddTmTLyphCache"); + J2dTracePrimitive("MTLTR_InitGlyphCache"); +} + +/** + * (Re)Initializes the gamma related uniforms. + * + * The given contrast value is an int in the range [100, 250] which we will + * then scale to fit in the range [1.0, 2.5]. + */ +static jboolean +MTLTR_UpdateLCDTextContrast(jint contrast) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_UpdateLCDTextContrast"); + return JNI_TRUE; +} + +/** + * Updates the current gamma-adjusted source color ("src_adj") of the LCD + * text shader program. Note that we could calculate this value in the + * shader (e.g. just as we do for "dst_adj"), but would be unnecessary work + * (and a measurable performance hit, maybe around 5%) since this value is + * constant over the entire glyph list. So instead we just calculate the + * gamma-adjusted value once and update the uniform parameter of the LCD + * shader as needed. + */ +static jboolean +MTLTR_UpdateLCDTextColor(jint contrast) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_UpdateLCDTextColor"); + return JNI_TRUE; +} + +/** + * Enables the LCD text shader and updates any related state, such as the + * gamma lookup table textures. + */ +static jboolean +MTLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, + GLuint dstTextureID, + jint contrast) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_EnableLCDGlyphModeState"); + return JNI_TRUE; +} + +void +MTLTR_EnableGlyphVertexCache(MTLContext *mtlc) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_EnableGlyphVertexCache"); +} + +void +MTLTR_DisableGlyphVertexCache(MTLContext *mtlc) +{ + //TODO + J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DisableGlyphVertexCache"); + J2dTraceNotImplPrimitive("MTLTR_DisableGlyphVertexCache"); + +} + +/** + * Disables any pending state associated with the current "glyph mode". + */ +void +MTLTR_DisableGlyphModeState() +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DisableGlyphModeState"); + J2dTraceLn1(J2D_TRACE_VERBOSE, + "MTLTR_DisableGlyphModeState: mode=%d", glyphMode); +} + +static jboolean +MTLTR_DrawGrayscaleGlyphViaCache(MTLContext *mtlc, + GlyphInfo *ginfo, jint x, jint y) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DisableGlyphVertexCache"); + return JNI_TRUE; +} + +/** + * Evaluates to true if the rectangle defined by gx1/gy1/gx2/gy2 is + * inside outerBounds. + */ +#define INSIDE(gx1, gy1, gx2, gy2, outerBounds) \ + (((gx1) >= outerBounds.x1) && ((gy1) >= outerBounds.y1) && \ + ((gx2) <= outerBounds.x2) && ((gy2) <= outerBounds.y2)) + +/** + * Evaluates to true if the rectangle defined by gx1/gy1/gx2/gy2 intersects + * the rectangle defined by bounds. + */ +#define INTERSECTS(gx1, gy1, gx2, gy2, bounds) \ + ((bounds.x2 > (gx1)) && (bounds.y2 > (gy1)) && \ + (bounds.x1 < (gx2)) && (bounds.y1 < (gy2))) + +/** + * This method checks to see if the given LCD glyph bounds fall within the + * cached destination texture bounds. If so, this method can return + * immediately. If not, this method will copy a chunk of framebuffer data + * into the cached destination texture and then update the current cached + * destination bounds before returning. + */ +static void +MTLTR_UpdateCachedDestination(MTLSDOps *dstOps, GlyphInfo *ginfo, + jint gx1, jint gy1, jint gx2, jint gy2, + jint glyphIndex, jint totalGlyphs) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_UpdateCachedDestination"); +} + +static jboolean +MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, MTLSDOps *dstOps, + GlyphInfo *ginfo, jint x, jint y, + jint glyphIndex, jint totalGlyphs, + jboolean rgbOrder, jint contrast, + jint dstTextureID, jboolean * opened) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DrawLCDGlyphViaCache"); + return JNI_TRUE; +} + +static jboolean +MTLTR_DrawGrayscaleGlyphNoCache(MTLContext *mtlc, + GlyphInfo *ginfo, jint x, jint y) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DrawGrayscaleGlyphNoCache"); + return JNI_TRUE; +} + +static jboolean +MTLTR_DrawLCDGlyphNoCache(MTLContext *mtlc, MTLSDOps *dstOps, + GlyphInfo *ginfo, jint x, jint y, + jint rowBytesOffset, + jboolean rgbOrder, jint contrast, + jint dstTextureID) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DrawLCDGlyphNoCache"); + return JNI_TRUE; +} + +static jboolean +MTLTR_DrawColorGlyphNoCache(MTLContext *mtlc, GlyphInfo *ginfo, jint x, jint y) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DrawColorGlyphNoCache"); + return JNI_TRUE; +} + + +// see DrawGlyphList.c for more on this macro... +#define FLOOR_ASSIGN(l, r) \ + if ((r)<0) (l) = ((int)floor(r)); else (l) = ((int)(r)) + +void +MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, MTLSDOps *dstOps, + jint totalGlyphs, jboolean usePositions, + jboolean subPixPos, jboolean rgbOrder, jint lcdContrast, + jfloat glyphListOrigX, jfloat glyphListOrigY, + unsigned char *images, unsigned char *positions) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTR_DrawGlyphList"); +} + +JNIEXPORT void JNICALL +Java_sun_java2d_metal_MTLTextRenderer_drawGlyphList + (JNIEnv *env, jobject self, + jint numGlyphs, jboolean usePositions, + jboolean subPixPos, jboolean rgbOrder, jint lcdContrast, + jfloat glyphListOrigX, jfloat glyphListOrigY, + jlongArray imgArray, jfloatArray posArray) +{ + //TODO + J2dTraceNotImplPrimitive("MTLTextRenderer_drawGlyphList"); +} + +#endif /* !HEADLESS */