src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m
branchmetal-prototype-branch
changeset 57416 e153174dba06
child 57422 08d15ddd72c9
equal deleted inserted replaced
57400:978ffc56771f 57416:e153174dba06
       
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #ifndef HEADLESS
       
    27 
       
    28 #include <stdlib.h>
       
    29 #include <limits.h>
       
    30 #include <math.h>
       
    31 #include <jlong.h>
       
    32 
       
    33 #include "sun_java2d_metal_MTLTextRenderer.h"
       
    34 
       
    35 #include "SurfaceData.h"
       
    36 #include "MTLContext.h"
       
    37 #include "MTLRenderQueue.h"
       
    38 #include "MTLTextRenderer.h"
       
    39 #include "MTLVertexCache.h"
       
    40 #include "AccelGlyphCache.h"
       
    41 
       
    42 /**
       
    43  * The following constants define the inner and outer bounds of the
       
    44  * accelerated glyph cache.
       
    45  */
       
    46 #define MTLTR_CACHE_WIDTH       1024
       
    47 #define MTLTR_CACHE_HEIGHT      1024
       
    48 #define MTLTR_CACHE_CELL_WIDTH  64
       
    49 #define MTLTR_CACHE_CELL_HEIGHT 64
       
    50 
       
    51 /**
       
    52  * The current "glyph mode" state.  This variable is used to track the
       
    53  * codepath used to render a particular glyph.  This variable is reset to
       
    54  * MODE_NOT_INITED at the beginning of every call to MTLTR_DrawGlyphList().
       
    55  * As each glyph is rendered, the glyphMode variable is updated to reflect
       
    56  * the current mode, so if the current mode is the same as the mode used
       
    57  * to render the previous glyph, we can avoid doing costly setup operations
       
    58  * each time.
       
    59  */
       
    60 typedef enum {
       
    61     MODE_NOT_INITED,
       
    62     MODE_USE_CACHE_GRAY,
       
    63     MODE_USE_CACHE_LCD,
       
    64     MODE_NO_CACHE_GRAY,
       
    65     MODE_NO_CACHE_LCD,
       
    66     MODE_NO_CACHE_COLOR
       
    67 } GlyphMode;
       
    68 static GlyphMode glyphMode = MODE_NOT_INITED;
       
    69 
       
    70 /**
       
    71  * There are two separate glyph caches: for AA and for LCD.
       
    72  * Once one of them is initialized as either GRAY or LCD, it
       
    73  * stays in that mode for the duration of the application.  It should
       
    74  * be safe to use this one glyph cache for all screens in a multimon
       
    75  * environment, since the glyph cache texture is shared between all contexts,
       
    76  * and (in theory) OpenGL drivers should be smart enough to manage that
       
    77  * texture across all screens.
       
    78  */
       
    79 
       
    80 static GlyphCacheInfo *glyphCacheLCD = NULL;
       
    81 static GlyphCacheInfo *glyphCacheAA = NULL;
       
    82 
       
    83 /**
       
    84  * The handle to the LCD text fragment program object.
       
    85  */
       
    86 static GLhandleARB lcdTextProgram = 0;
       
    87 
       
    88 /**
       
    89  * This value tracks the previous LCD contrast setting, so if the contrast
       
    90  * value hasn't changed since the last time the gamma uniforms were
       
    91  * updated (not very common), then we can skip updating the unforms.
       
    92  */
       
    93 static jint lastLCDContrast = -1;
       
    94 
       
    95 /**
       
    96  * This value tracks the previous LCD rgbOrder setting, so if the rgbOrder
       
    97  * value has changed since the last time, it indicates that we need to
       
    98  * invalidate the cache, which may already store glyph images in the reverse
       
    99  * order.  Note that in most real world applications this value will not
       
   100  * change over the course of the application, but tests like Font2DTest
       
   101  * allow for changing the ordering at runtime, so we need to handle that case.
       
   102  */
       
   103 static jboolean lastRGBOrder = JNI_TRUE;
       
   104 
       
   105 /**
       
   106  * This constant defines the size of the tile to use in the
       
   107  * MTLTR_DrawLCDGlyphNoCache() method.  See below for more on why we
       
   108  * restrict this value to a particular size.
       
   109  */
       
   110 #define MTLTR_NOCACHE_TILE_SIZE 64
       
   111 
       
   112 /**
       
   113  * These constants define the size of the "cached destination" texture.
       
   114  * This texture is only used when rendering LCD-optimized text, as that
       
   115  * codepath needs direct access to the destination.  There is no way to
       
   116  * access the framebuffer directly from an OpenGL shader, so we need to first
       
   117  * copy the destination region corresponding to a particular glyph into
       
   118  * this cached texture, and then that texture will be accessed inside the
       
   119  * shader.  Copying the destination into this cached texture can be a very
       
   120  * expensive operation (accounting for about half the rendering time for
       
   121  * LCD text), so to mitigate this cost we try to bulk read a horizontal
       
   122  * region of the destination at a time.  (These values are empirically
       
   123  * derived for the common case where text runs horizontally.)
       
   124  *
       
   125  * Note: It is assumed in various calculations below that:
       
   126  *     (MTLTR_CACHED_DEST_WIDTH  >= MTLTR_CACHE_CELL_WIDTH)  &&
       
   127  *     (MTLTR_CACHED_DEST_WIDTH  >= MTLTR_NOCACHE_TILE_SIZE) &&
       
   128  *     (MTLTR_CACHED_DEST_HEIGHT >= MTLTR_CACHE_CELL_HEIGHT) &&
       
   129  *     (MTLTR_CACHED_DEST_HEIGHT >= MTLTR_NOCACHE_TILE_SIZE)
       
   130  */
       
   131 #define MTLTR_CACHED_DEST_WIDTH  1024
       
   132 #define MTLTR_CACHED_DEST_HEIGHT (MTLTR_CACHE_CELL_HEIGHT * 2)
       
   133 
       
   134 /**
       
   135  * The handle to the "cached destination" texture object.
       
   136  */
       
   137 static GLuint cachedDestTextureID = 0;
       
   138 
       
   139 /**
       
   140  * The current bounds of the "cached destination" texture, in destination
       
   141  * coordinate space.  The width/height of these bounds will not exceed the
       
   142  * MTLTR_CACHED_DEST_WIDTH/HEIGHT values defined above.  These bounds are
       
   143  * only considered valid when the isCachedDestValid flag is JNI_TRUE.
       
   144  */
       
   145 static SurfaceDataBounds cachedDestBounds;
       
   146 
       
   147 /**
       
   148  * This flag indicates whether the "cached destination" texture contains
       
   149  * valid data.  This flag is reset to JNI_FALSE at the beginning of every
       
   150  * call to MTLTR_DrawGlyphList().  Once we copy valid destination data
       
   151  * into the cached texture, this flag is set to JNI_TRUE.  This way, we can
       
   152  * limit the number of times we need to copy destination data, which is a
       
   153  * very costly operation.
       
   154  */
       
   155 static jboolean isCachedDestValid = JNI_FALSE;
       
   156 
       
   157 /**
       
   158  * The bounds of the previously rendered LCD glyph, in destination
       
   159  * coordinate space.  We use these bounds to determine whether the glyph
       
   160  * currently being rendered overlaps the previously rendered glyph (i.e.
       
   161  * its bounding box intersects that of the previously rendered glyph).  If
       
   162  * so, we need to re-read the destination area associated with that previous
       
   163  * glyph so that we can correctly blend with the actual destination data.
       
   164  */
       
   165 static SurfaceDataBounds previousGlyphBounds;
       
   166 
       
   167 /**
       
   168  * Initializes the one glyph cache (texture and data structure).
       
   169  * If lcdCache is JNI_TRUE, the texture will contain RGB data,
       
   170  * otherwise we will simply store the grayscale/monochrome glyph images
       
   171  * as intensity values (which work well with the GL_MODULATE function).
       
   172  */
       
   173 static jboolean
       
   174 MTLTR_InitGlyphCache(jboolean lcdCache)
       
   175 {
       
   176     //TODO
       
   177 
       
   178     return JNI_TRUE;
       
   179 }
       
   180 
       
   181 /**
       
   182  * Adds the given glyph to the glyph cache (texture and data structure)
       
   183  * associated with the given MTLContext.
       
   184  */
       
   185 static void
       
   186 MTLTR_AddTmTLyphCache(GlyphInfo *glyph, GLenum pixelFormat)
       
   187 {
       
   188     //TODO
       
   189 
       
   190     CacheCellInfo *ccinfo;
       
   191     GlyphCacheInfo *gcinfo;
       
   192 
       
   193     J2dTraceLn(J2D_TRACE_INFO, "MTLTR_AddTmTLyphCache");
       
   194     //J2dTracePrimitive("MTLTR_InitGlyphCache");
       
   195 }
       
   196 
       
   197 /**
       
   198  * (Re)Initializes the gamma related uniforms.
       
   199  *
       
   200  * The given contrast value is an int in the range [100, 250] which we will
       
   201  * then scale to fit in the range [1.0, 2.5].
       
   202  */
       
   203 static jboolean
       
   204 MTLTR_UpdateLCDTextContrast(jint contrast)
       
   205 {
       
   206     //TODO
       
   207     return JNI_TRUE;
       
   208 }
       
   209 
       
   210 /**
       
   211  * Updates the current gamma-adjusted source color ("src_adj") of the LCD
       
   212  * text shader program.  Note that we could calculate this value in the
       
   213  * shader (e.g. just as we do for "dst_adj"), but would be unnecessary work
       
   214  * (and a measurable performance hit, maybe around 5%) since this value is
       
   215  * constant over the entire glyph list.  So instead we just calculate the
       
   216  * gamma-adjusted value once and update the uniform parameter of the LCD
       
   217  * shader as needed.
       
   218  */
       
   219 static jboolean
       
   220 MTLTR_UpdateLCDTextColor(jint contrast)
       
   221 {
       
   222     //TODO
       
   223     return JNI_TRUE;
       
   224 }
       
   225 
       
   226 /**
       
   227  * Enables the LCD text shader and updates any related state, such as the
       
   228  * gamma lookup table textures.
       
   229  */
       
   230 static jboolean
       
   231 MTLTR_EnableLCDGlyphModeState(GLuint glyphTextureID,
       
   232                               GLuint dstTextureID,
       
   233                               jint contrast)
       
   234 {
       
   235     //TODO
       
   236     return JNI_TRUE;
       
   237 }
       
   238 
       
   239 void
       
   240 MTLTR_EnableGlyphVertexCache(MTLContext *mtlc)
       
   241 {
       
   242     //TODO
       
   243 }
       
   244 
       
   245 void
       
   246 MTLTR_DisableGlyphVertexCache(MTLContext *mtlc)
       
   247 {
       
   248     //TODO
       
   249     J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DisableGlyphVertexCache");
       
   250 
       
   251 }
       
   252 
       
   253 /**
       
   254  * Disables any pending state associated with the current "glyph mode".
       
   255  */
       
   256 void
       
   257 MTLTR_DisableGlyphModeState()
       
   258 {
       
   259     //TODO
       
   260     J2dTraceLn1(J2D_TRACE_VERBOSE,
       
   261                 "MTLTR_DisableGlyphModeState: mode=%d", glyphMode);
       
   262 }
       
   263 
       
   264 static jboolean
       
   265 MTLTR_DrawGrayscaleGlyphViaCache(MTLContext *mtlc,
       
   266                                  GlyphInfo *ginfo, jint x, jint y)
       
   267 {
       
   268     //TODO
       
   269     return JNI_TRUE;
       
   270 }
       
   271 
       
   272 /**
       
   273  * Evaluates to true if the rectangle defined by gx1/gy1/gx2/gy2 is
       
   274  * inside outerBounds.
       
   275  */
       
   276 #define INSIDE(gx1, gy1, gx2, gy2, outerBounds) \
       
   277     (((gx1) >= outerBounds.x1) && ((gy1) >= outerBounds.y1) && \
       
   278      ((gx2) <= outerBounds.x2) && ((gy2) <= outerBounds.y2))
       
   279 
       
   280 /**
       
   281  * Evaluates to true if the rectangle defined by gx1/gy1/gx2/gy2 intersects
       
   282  * the rectangle defined by bounds.
       
   283  */
       
   284 #define INTERSECTS(gx1, gy1, gx2, gy2, bounds) \
       
   285     ((bounds.x2 > (gx1)) && (bounds.y2 > (gy1)) && \
       
   286      (bounds.x1 < (gx2)) && (bounds.y1 < (gy2)))
       
   287 
       
   288 /**
       
   289  * This method checks to see if the given LCD glyph bounds fall within the
       
   290  * cached destination texture bounds.  If so, this method can return
       
   291  * immediately.  If not, this method will copy a chunk of framebuffer data
       
   292  * into the cached destination texture and then update the current cached
       
   293  * destination bounds before returning.
       
   294  */
       
   295 static void
       
   296 MTLTR_UpdateCachedDestination(MTLSDOps *dstOps, GlyphInfo *ginfo,
       
   297                               jint gx1, jint gy1, jint gx2, jint gy2,
       
   298                               jint glyphIndex, jint totalGlyphs)
       
   299 {
       
   300     //TODO
       
   301 }
       
   302 
       
   303 static jboolean
       
   304 MTLTR_DrawLCDGlyphViaCache(MTLContext *mtlc, MTLSDOps *dstOps,
       
   305                            GlyphInfo *ginfo, jint x, jint y,
       
   306                            jint glyphIndex, jint totalGlyphs,
       
   307                            jboolean rgbOrder, jint contrast,
       
   308                            jint dstTextureID, jboolean * opened)
       
   309 {
       
   310     //TODO
       
   311     return JNI_TRUE;
       
   312 }
       
   313 
       
   314 static jboolean
       
   315 MTLTR_DrawGrayscaleGlyphNoCache(MTLContext *mtlc,
       
   316                                 GlyphInfo *ginfo, jint x, jint y)
       
   317 {
       
   318     //TODO
       
   319     return JNI_TRUE;
       
   320 }
       
   321 
       
   322 static jboolean
       
   323 MTLTR_DrawLCDGlyphNoCache(MTLContext *mtlc, MTLSDOps *dstOps,
       
   324                           GlyphInfo *ginfo, jint x, jint y,
       
   325                           jint rowBytesOffset,
       
   326                           jboolean rgbOrder, jint contrast,
       
   327                           jint dstTextureID)
       
   328 {
       
   329     //TODO
       
   330     return JNI_TRUE;
       
   331 }
       
   332 
       
   333 static jboolean
       
   334 MTLTR_DrawColorGlyphNoCache(MTLContext *mtlc, GlyphInfo *ginfo, jint x, jint y)
       
   335 {
       
   336     //TODO
       
   337     return JNI_TRUE;
       
   338 }
       
   339 
       
   340 
       
   341 // see DrawGlyphList.c for more on this macro...
       
   342 #define FLOOR_ASSIGN(l, r) \
       
   343     if ((r)<0) (l) = ((int)floor(r)); else (l) = ((int)(r))
       
   344 
       
   345 void
       
   346 MTLTR_DrawGlyphList(JNIEnv *env, MTLContext *mtlc, MTLSDOps *dstOps,
       
   347                     jint totalGlyphs, jboolean usePositions,
       
   348                     jboolean subPixPos, jboolean rgbOrder, jint lcdContrast,
       
   349                     jfloat glyphListOrigX, jfloat glyphListOrigY,
       
   350                     unsigned char *images, unsigned char *positions)
       
   351 {
       
   352     //TODO
       
   353 }
       
   354 
       
   355 JNIEXPORT void JNICALL
       
   356 Java_sun_java2d_metal_MTLTextRenderer_drawGlyphList
       
   357     (JNIEnv *env, jobject self,
       
   358      jint numGlyphs, jboolean usePositions,
       
   359      jboolean subPixPos, jboolean rgbOrder, jint lcdContrast,
       
   360      jfloat glyphListOrigX, jfloat glyphListOrigY,
       
   361      jlongArray imgArray, jfloatArray posArray)
       
   362 {
       
   363     //TODO
       
   364 }
       
   365 
       
   366 #endif /* !HEADLESS */