< prev index next >

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

Print this page




 255 
 256     AccelGlyphCache_AddGlyph(glyphCache, glyph);
 257     ccinfo = (CacheCellInfo *) glyph->cellInfo;
 258 
 259     if (ccinfo != NULL) {
 260         // store glyph image in texture cell
 261         j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
 262                             ccinfo->x, ccinfo->y,
 263                             glyph->width, glyph->height,
 264                             pixelFormat, GL_UNSIGNED_BYTE, glyph->image);
 265     }
 266 }
 267 
 268 /**
 269  * This is the GLSL fragment shader source code for rendering LCD-optimized
 270  * text.  Do not be frightened; it is much easier to understand than the
 271  * equivalent ASM-like fragment program!
 272  *
 273  * The "uniform" variables at the top are initialized once the program is
 274  * linked, and are updated at runtime as needed (e.g. when the source color
 275  * changes, we will modify the "src_adj" value in OGLTR_UpdateLCDTextColor()).
 276  *
 277  * The "main" function is executed for each "fragment" (or pixel) in the
 278  * glyph image.  We have determined that the pow() function can be quite
 279  * slow and it only operates on scalar values, not vectors as we require.
 280  * So instead we build two 3D textures containing gamma (and inverse gamma)
 281  * lookup tables that allow us to approximate a component-wise pow() function
 282  * with a single 3D texture lookup.  This approach is at least 2x faster
 283  * than the equivalent pow() calls.
 284  *
 285  * The variables involved in the equation can be expressed as follows:
 286  *
 287  *   Cs = Color component of the source (foreground color) [0.0, 1.0]
 288  *   Cd = Color component of the destination (background color) [0.0, 1.0]
 289  *   Cr = Color component to be written to the destination [0.0, 1.0]
 290  *   Ag = Glyph alpha (aka intensity or coverage) [0.0, 1.0]
 291  *   Ga = Gamma adjustment in the range [1.0, 2.5]
 292  *   (^ means raised to the power)
 293  *
 294  * And here is the theoretical equation approximated by this shader:
 295  *
 296  *            Cr = (Ag*(Cs^Ga) + (1-Ag)*(Cd^Ga)) ^ (1/Ga)
 297  */
 298 static const char *lcdTextShaderSource =
 299     "uniform vec3 src_adj;"
 300     "uniform sampler2D glyph_tex;"
 301     "uniform sampler2D dst_tex;"
 302     "uniform sampler3D invgamma_tex;"
 303     "uniform sampler3D gamma_tex;"
 304     ""
 305     "void main(void)"
 306     "{"
 307          // load the RGB value from the glyph image at the current texcoord
 308     "    vec3 glyph_clr = vec3(texture2D(glyph_tex, gl_TexCoord[0].st));"
 309     "    if (glyph_clr == vec3(0.0)) {"
 310              // zero coverage, so skip this fragment
 311     "        discard;"
 312     "    }"
 313          // load the RGB value from the corresponding destination pixel
 314     "    vec3 dst_clr = vec3(texture2D(dst_tex, gl_TexCoord[1].st));"




 315          // gamma adjust the dest color using the invgamma LUT
 316     "    vec3 dst_adj = vec3(texture3D(invgamma_tex, dst_clr.stp));"
 317          // linearly interpolate the three color values
 318     "    vec3 result = mix(dst_adj, src_adj, glyph_clr);"
 319          // gamma re-adjust the resulting color (alpha is always set to 1.0)
 320     "    gl_FragColor = vec4(vec3(texture3D(gamma_tex, result.stp)), 1.0);"


 321     "}";
 322 
 323 /**
 324  * Compiles and links the LCD text shader program.  If successful, this
 325  * function returns a handle to the newly created shader program; otherwise
 326  * returns 0.
 327  */
 328 static GLhandleARB
 329 OGLTR_CreateLCDTextProgram()
 330 {
 331     GLhandleARB lcdTextProgram;
 332     GLint loc;
 333 
 334     J2dTraceLn(J2D_TRACE_INFO, "OGLTR_CreateLCDTextProgram");
 335 
 336     lcdTextProgram = OGLContext_CreateFragmentProgram(lcdTextShaderSource);
 337     if (lcdTextProgram == 0) {
 338         J2dRlsTraceLn(J2D_TRACE_ERROR,
 339                       "OGLTR_CreateLCDTextProgram: error creating program");
 340         return 0;


 450                 invlut[z][y][x][2] = igz;
 451             }
 452         }
 453     }
 454 
 455     if (gammaLutTextureID == 0) {
 456         gammaLutTextureID = OGLTR_InitGammaLutTexture();
 457     }
 458     OGLTR_UpdateGammaLutTexture(gammaLutTextureID, (GLfloat *)lut, LUT_EDGE);
 459 
 460     if (invGammaLutTextureID == 0) {
 461         invGammaLutTextureID = OGLTR_InitGammaLutTexture();
 462     }
 463     OGLTR_UpdateGammaLutTexture(invGammaLutTextureID,
 464                                 (GLfloat *)invlut, LUT_EDGE);
 465 
 466     return JNI_TRUE;
 467 }
 468 
 469 /**
 470  * Updates the current gamma-adjusted source color ("src_adj") of the LCD
 471  * text shader program.  Note that we could calculate this value in the
 472  * shader (e.g. just as we do for "dst_adj"), but would be unnecessary work
 473  * (and a measurable performance hit, maybe around 5%) since this value is
 474  * constant over the entire glyph list.  So instead we just calculate the
 475  * gamma-adjusted value once and update the uniform parameter of the LCD
 476  * shader as needed.
 477  */
 478 static jboolean
 479 OGLTR_UpdateLCDTextColor(jint contrast)
 480 {
 481     double gamma = ((double)contrast) / 100.0;
 482     GLfloat radj, gadj, badj;
 483     GLfloat clr[4];
 484     GLint loc;
 485 
 486     J2dTraceLn1(J2D_TRACE_INFO,
 487                 "OGLTR_UpdateLCDTextColor: contrast=%d", contrast);
 488 
 489     /*
 490      * Note: Ideally we would update the "src_adj" uniform parameter only
 491      * when there is a change in the source color.  Fortunately, the cost
 492      * of querying the current OpenGL color state and updating the uniform
 493      * value is quite small, and in the common case we only need to do this
 494      * once per GlyphList, so we gain little from trying to optimize too
 495      * eagerly here.
 496      */
 497 
 498     // get the current OpenGL primary color state
 499     j2d_glGetFloatv(GL_CURRENT_COLOR, clr);
 500 
 501     // gamma adjust the primary color
 502     radj = (GLfloat)pow(clr[0], gamma);
 503     gadj = (GLfloat)pow(clr[1], gamma);
 504     badj = (GLfloat)pow(clr[2], gamma);
 505 
 506     // update the "src_adj" parameter of the shader program with this value
 507     loc = j2d_glGetUniformLocationARB(lcdTextProgram, "src_adj");
 508     j2d_glUniform3fARB(loc, radj, gadj, badj);
 509 
 510     return JNI_TRUE;
 511 }
 512 
 513 /**
 514  * Enables the LCD text shader and updates any related state, such as the
 515  * gamma lookup table textures.
 516  */
 517 static jboolean
 518 OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, jint contrast)
 519 {
 520     // bind the texture containing glyph data to texture unit 0
 521     j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
 522     j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID);
 523 
 524     // bind the texture tile containing destination data to texture unit 1
 525     j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
 526     if (cachedDestTextureID == 0) {
 527         cachedDestTextureID =
 528             OGLContext_CreateBlitTexture(GL_RGB8, GL_RGB,




 255 
 256     AccelGlyphCache_AddGlyph(glyphCache, glyph);
 257     ccinfo = (CacheCellInfo *) glyph->cellInfo;
 258 
 259     if (ccinfo != NULL) {
 260         // store glyph image in texture cell
 261         j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
 262                             ccinfo->x, ccinfo->y,
 263                             glyph->width, glyph->height,
 264                             pixelFormat, GL_UNSIGNED_BYTE, glyph->image);
 265     }
 266 }
 267 
 268 /**
 269  * This is the GLSL fragment shader source code for rendering LCD-optimized
 270  * text.  Do not be frightened; it is much easier to understand than the
 271  * equivalent ASM-like fragment program!
 272  *
 273  * The "uniform" variables at the top are initialized once the program is
 274  * linked, and are updated at runtime as needed (e.g. when the source color
 275  * changes, we will modify the "src_clr" value in OGLTR_UpdateLCDTextColor()).
 276  *
 277  * The "main" function is executed for each "fragment" (or pixel) in the
 278  * glyph image.  We have determined that the pow() function can be quite
 279  * slow and it only operates on scalar values, not vectors as we require.
 280  * So instead we build two 3D textures containing gamma (and inverse gamma)
 281  * lookup tables that allow us to approximate a component-wise pow() function
 282  * with a single 3D texture lookup.  This approach is at least 2x faster
 283  * than the equivalent pow() calls.
 284  *
 285  * The variables involved in the equation can be expressed as follows:
 286  *
 287  *   Cs = Color component of the source (foreground color) [0.0, 1.0]
 288  *   Cd = Color component of the destination (background color) [0.0, 1.0]
 289  *   Cr = Color component to be written to the destination [0.0, 1.0]
 290  *   Ag = Glyph alpha (aka intensity or coverage) [0.0, 1.0]
 291  *   Ga = Gamma adjustment in the range [1.0, 2.5]
 292  *   (^ means raised to the power)
 293  *
 294  * And here is the theoretical equation approximated by this shader:
 295  *
 296  *            Cr = (Ag*(Cs^Ga) + (1-Ag)*(Cd^Ga)) ^ (1/Ga)
 297  */
 298 static const char *lcdTextShaderSource =
 299     "uniform vec4 src_clr;"
 300     "uniform sampler2D glyph_tex;"
 301     "uniform sampler2D dst_tex;"
 302     "uniform sampler3D invgamma_tex;"
 303     "uniform sampler3D gamma_tex;"
 304     ""
 305     "void main(void)"
 306     "{"
 307          // load the RGB value from the glyph image at the current texcoord
 308     "    vec3 glyph_clr = vec3(texture2D(glyph_tex, gl_TexCoord[0].st));"
 309     "    if (glyph_clr == vec3(0.0)) {"
 310              // zero coverage, so skip this fragment
 311     "        discard;"
 312     "    }"
 313          // load the RGBA value from the corresponding destination pixel
 314     "    vec4 dst_clr = vec4(texture2D(dst_tex, gl_TexCoord[1].st));"
 315          // blend src and dst colors as SrcOverNoEa
 316     "    vec3 src_comp = vec3(src_clr.rgb + ((1.0 - src_clr.a) * dst_clr.rgb));"
 317          // gamma adjust the blended src color using the invgamma LUT
 318     "    vec3 src_adj = vec3(texture3D(invgamma_tex, src_comp));"
 319          // gamma adjust the dest color using the invgamma LUT
 320     "    vec3 dst_adj = vec3(texture3D(invgamma_tex, dst_clr.rgb));"
 321          // linearly interpolate the three color values
 322     "    vec3 result = mix(dst_adj, src_adj, glyph_clr);"
 323          // calculate the resulting alpha
 324     "    dst_clr.a = src_clr.a + (1.0 - src_clr.a) * dst_clr.a;"
 325          // gamma re-adjust the resulting color
 326     "    gl_FragColor = vec4(vec3(texture3D(gamma_tex, result.rgb)), dst_clr.a);"
 327     "}";
 328 
 329 /**
 330  * Compiles and links the LCD text shader program.  If successful, this
 331  * function returns a handle to the newly created shader program; otherwise
 332  * returns 0.
 333  */
 334 static GLhandleARB
 335 OGLTR_CreateLCDTextProgram()
 336 {
 337     GLhandleARB lcdTextProgram;
 338     GLint loc;
 339 
 340     J2dTraceLn(J2D_TRACE_INFO, "OGLTR_CreateLCDTextProgram");
 341 
 342     lcdTextProgram = OGLContext_CreateFragmentProgram(lcdTextShaderSource);
 343     if (lcdTextProgram == 0) {
 344         J2dRlsTraceLn(J2D_TRACE_ERROR,
 345                       "OGLTR_CreateLCDTextProgram: error creating program");
 346         return 0;


 456                 invlut[z][y][x][2] = igz;
 457             }
 458         }
 459     }
 460 
 461     if (gammaLutTextureID == 0) {
 462         gammaLutTextureID = OGLTR_InitGammaLutTexture();
 463     }
 464     OGLTR_UpdateGammaLutTexture(gammaLutTextureID, (GLfloat *)lut, LUT_EDGE);
 465 
 466     if (invGammaLutTextureID == 0) {
 467         invGammaLutTextureID = OGLTR_InitGammaLutTexture();
 468     }
 469     OGLTR_UpdateGammaLutTexture(invGammaLutTextureID,
 470                                 (GLfloat *)invlut, LUT_EDGE);
 471 
 472     return JNI_TRUE;
 473 }
 474 
 475 /**
 476  * Updates the current source color ("src_clr") of the LCD text shader program.






 477  */
 478 static jboolean
 479 OGLTR_UpdateLCDTextColor(jint contrast)
 480 {
 481     double gamma = 100.0 / ((double)contrast);

 482     GLfloat clr[4];
 483     GLint loc;
 484 
 485     J2dTraceLn1(J2D_TRACE_INFO,
 486                 "OGLTR_UpdateLCDTextColor: contrast=%d", contrast);
 487 









 488     // get the current OpenGL primary color state
 489     j2d_glGetFloatv(GL_CURRENT_COLOR, clr);
 490 
 491     // update the "src_clr" parameter of the shader program with this value
 492     loc = j2d_glGetUniformLocationARB(lcdTextProgram, "src_clr");
 493     j2d_glUniform4fARB(loc, clr[0], clr[1], clr[2], clr[3]);





 494 
 495     return JNI_TRUE;
 496 }
 497 
 498 /**
 499  * Enables the LCD text shader and updates any related state, such as the
 500  * gamma lookup table textures.
 501  */
 502 static jboolean
 503 OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, jint contrast)
 504 {
 505     // bind the texture containing glyph data to texture unit 0
 506     j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
 507     j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID);
 508 
 509     // bind the texture tile containing destination data to texture unit 1
 510     j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
 511     if (cachedDestTextureID == 0) {
 512         cachedDestTextureID =
 513             OGLContext_CreateBlitTexture(GL_RGB8, GL_RGB,


< prev index next >