< prev index next >
src/java.desktop/share/native/common/java2d/opengl/OGLTextRenderer.c
Print this page
*** 273,288 ****
* The "uniform" variables at the top are initialized once the program is
* linked, and are updated at runtime as needed (e.g. when the source color
* changes, we will modify the "src_adj" value in OGLTR_UpdateLCDTextColor()).
*
* The "main" function is executed for each "fragment" (or pixel) in the
! * glyph image. We have determined that the pow() function can be quite
! * slow and it only operates on scalar values, not vectors as we require.
! * So instead we build two 3D textures containing gamma (and inverse gamma)
! * lookup tables that allow us to approximate a component-wise pow() function
! * with a single 3D texture lookup. This approach is at least 2x faster
! * than the equivalent pow() calls.
*
* The variables involved in the equation can be expressed as follows:
*
* Cs = Color component of the source (foreground color) [0.0, 1.0]
* Cd = Color component of the destination (background color) [0.0, 1.0]
--- 273,285 ----
* The "uniform" variables at the top are initialized once the program is
* linked, and are updated at runtime as needed (e.g. when the source color
* changes, we will modify the "src_adj" value in OGLTR_UpdateLCDTextColor()).
*
* The "main" function is executed for each "fragment" (or pixel) in the
! * glyph image. The pow() routine operates on vectors, gives precise results,
! * and provides acceptable level of performance, so we use it to perform
! * the gamma adjustment.
*
* The variables involved in the equation can be expressed as follows:
*
* Cs = Color component of the source (foreground color) [0.0, 1.0]
* Cd = Color component of the destination (background color) [0.0, 1.0]
*** 297,308 ****
*/
static const char *lcdTextShaderSource =
"uniform vec3 src_adj;"
"uniform sampler2D glyph_tex;"
"uniform sampler2D dst_tex;"
! "uniform sampler3D invgamma_tex;"
! "uniform sampler3D gamma_tex;"
""
"void main(void)"
"{"
// load the RGB value from the glyph image at the current texcoord
" vec3 glyph_clr = vec3(texture2D(glyph_tex, gl_TexCoord[0].st));"
--- 294,305 ----
*/
static const char *lcdTextShaderSource =
"uniform vec3 src_adj;"
"uniform sampler2D glyph_tex;"
"uniform sampler2D dst_tex;"
! "uniform vec3 gamma;"
! "uniform vec3 invgamma;"
""
"void main(void)"
"{"
// load the RGB value from the glyph image at the current texcoord
" vec3 glyph_clr = vec3(texture2D(glyph_tex, gl_TexCoord[0].st));"
*** 310,325 ****
// zero coverage, so skip this fragment
" discard;"
" }"
// load the RGB value from the corresponding destination pixel
" vec3 dst_clr = vec3(texture2D(dst_tex, gl_TexCoord[1].st));"
! // gamma adjust the dest color using the invgamma LUT
! " vec3 dst_adj = vec3(texture3D(invgamma_tex, dst_clr.stp));"
// linearly interpolate the three color values
" vec3 result = mix(dst_adj, src_adj, glyph_clr);"
// gamma re-adjust the resulting color (alpha is always set to 1.0)
! " gl_FragColor = vec4(vec3(texture3D(gamma_tex, result.stp)), 1.0);"
"}";
/**
* Compiles and links the LCD text shader program. If successful, this
* function returns a handle to the newly created shader program; otherwise
--- 307,322 ----
// zero coverage, so skip this fragment
" discard;"
" }"
// load the RGB value from the corresponding destination pixel
" vec3 dst_clr = vec3(texture2D(dst_tex, gl_TexCoord[1].st));"
! // gamma adjust the dest color
! " vec3 dst_adj = pow(dst_clr.rgb, invgamma);"
// linearly interpolate the three color values
" vec3 result = mix(dst_adj, src_adj, glyph_clr);"
// gamma re-adjust the resulting color (alpha is always set to 1.0)
! " gl_FragColor = vec4(pow(result.rgb, gamma), 1.0);"
"}";
/**
* Compiles and links the LCD text shader program. If successful, this
* function returns a handle to the newly created shader program; otherwise
*** 346,469 ****
// set the "uniform" values
loc = j2d_glGetUniformLocationARB(lcdTextProgram, "glyph_tex");
j2d_glUniform1iARB(loc, 0); // texture unit 0
loc = j2d_glGetUniformLocationARB(lcdTextProgram, "dst_tex");
j2d_glUniform1iARB(loc, 1); // texture unit 1
- loc = j2d_glGetUniformLocationARB(lcdTextProgram, "invgamma_tex");
- j2d_glUniform1iARB(loc, 2); // texture unit 2
- loc = j2d_glGetUniformLocationARB(lcdTextProgram, "gamma_tex");
- j2d_glUniform1iARB(loc, 3); // texture unit 3
// "unuse" the program object; it will be re-bound later as needed
j2d_glUseProgramObjectARB(0);
return lcdTextProgram;
}
/**
! * Initializes a 3D texture object for use as a three-dimensional gamma
! * lookup table. Note that the wrap mode is initialized to GL_LINEAR so
! * that the table will interpolate adjacent values when the index falls
! * somewhere in between.
! */
! static GLuint
! OGLTR_InitGammaLutTexture()
! {
! GLuint lutTextureID;
!
! j2d_glGenTextures(1, &lutTextureID);
! j2d_glBindTexture(GL_TEXTURE_3D, lutTextureID);
! j2d_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
! j2d_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
! j2d_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
! j2d_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
! j2d_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
!
! return lutTextureID;
! }
!
! /**
! * Updates the lookup table in the given texture object with the float
! * values in the given system memory buffer. Note that we could use
! * glTexSubImage3D() when updating the texture after its first
! * initialization, but since we're updating the entire table (with
! * power-of-two dimensions) and this is a relatively rare event, we'll
! * just stick with glTexImage3D().
! */
! static void
! OGLTR_UpdateGammaLutTexture(GLuint texID, GLfloat *lut, jint size)
! {
! j2d_glBindTexture(GL_TEXTURE_3D, texID);
! j2d_glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8,
! size, size, size, 0, GL_RGB, GL_FLOAT, lut);
! }
!
! /**
! * (Re)Initializes the gamma lookup table textures.
*
* 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]. We create two LUTs, one
! * that essentially calculates pow(x, gamma) and the other calculates
! * pow(x, 1/gamma). These values are replicated in all three dimensions, so
! * given a single 3D texture coordinate (typically this will be a triplet
! * in the form (r,g,b)), the 3D texture lookup will return an RGB triplet:
! *
! * (pow(r,g), pow(y,g), pow(z,g)
! *
! * where g is either gamma or 1/gamma, depending on the table.
*/
static jboolean
OGLTR_UpdateLCDTextContrast(jint contrast)
{
double gamma = ((double)contrast) / 100.0;
double ig = gamma;
double g = 1.0 / ig;
! GLfloat lut[LUT_EDGE][LUT_EDGE][LUT_EDGE][3];
! GLfloat invlut[LUT_EDGE][LUT_EDGE][LUT_EDGE][3];
! int min = 0;
! int max = LUT_EDGE - 1;
! int x, y, z;
J2dTraceLn1(J2D_TRACE_INFO,
"OGLTR_UpdateLCDTextContrast: contrast=%d", contrast);
! for (z = min; z <= max; z++) {
! double zval = ((double)z) / max;
! GLfloat gz = (GLfloat)pow(zval, g);
! GLfloat igz = (GLfloat)pow(zval, ig);
!
! for (y = min; y <= max; y++) {
! double yval = ((double)y) / max;
! GLfloat gy = (GLfloat)pow(yval, g);
! GLfloat igy = (GLfloat)pow(yval, ig);
!
! for (x = min; x <= max; x++) {
! double xval = ((double)x) / max;
! GLfloat gx = (GLfloat)pow(xval, g);
! GLfloat igx = (GLfloat)pow(xval, ig);
! lut[z][y][x][0] = gx;
! lut[z][y][x][1] = gy;
! lut[z][y][x][2] = gz;
!
! invlut[z][y][x][0] = igx;
! invlut[z][y][x][1] = igy;
! invlut[z][y][x][2] = igz;
! }
! }
! }
!
! if (gammaLutTextureID == 0) {
! gammaLutTextureID = OGLTR_InitGammaLutTexture();
! }
! OGLTR_UpdateGammaLutTexture(gammaLutTextureID, (GLfloat *)lut, LUT_EDGE);
!
! if (invGammaLutTextureID == 0) {
! invGammaLutTextureID = OGLTR_InitGammaLutTexture();
! }
! OGLTR_UpdateGammaLutTexture(invGammaLutTextureID,
! (GLfloat *)invlut, LUT_EDGE);
return JNI_TRUE;
}
/**
--- 343,381 ----
// set the "uniform" values
loc = j2d_glGetUniformLocationARB(lcdTextProgram, "glyph_tex");
j2d_glUniform1iARB(loc, 0); // texture unit 0
loc = j2d_glGetUniformLocationARB(lcdTextProgram, "dst_tex");
j2d_glUniform1iARB(loc, 1); // texture unit 1
// "unuse" the program object; it will be re-bound later as needed
j2d_glUseProgramObjectARB(0);
return lcdTextProgram;
}
/**
! * (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
OGLTR_UpdateLCDTextContrast(jint contrast)
{
double gamma = ((double)contrast) / 100.0;
double ig = gamma;
double g = 1.0 / ig;
! GLint loc;
J2dTraceLn1(J2D_TRACE_INFO,
"OGLTR_UpdateLCDTextContrast: contrast=%d", contrast);
! loc = j2d_glGetUniformLocationARB(lcdTextProgram, "gamma");
! j2d_glUniform3fARB(loc, g, g, g);
! loc = j2d_glGetUniformLocationARB(lcdTextProgram, "invgamma");
! j2d_glUniform3fARB(loc, ig, ig, ig);
return JNI_TRUE;
}
/**
*** 476,486 ****
* shader as needed.
*/
static jboolean
OGLTR_UpdateLCDTextColor(jint contrast)
{
! double gamma = ((double)contrast) / 100.0;
GLfloat radj, gadj, badj;
GLfloat clr[4];
GLint loc;
J2dTraceLn1(J2D_TRACE_INFO,
--- 388,398 ----
* shader as needed.
*/
static jboolean
OGLTR_UpdateLCDTextColor(jint contrast)
{
! double invgamma = ((double)contrast) / 100;
GLfloat radj, gadj, badj;
GLfloat clr[4];
GLint loc;
J2dTraceLn1(J2D_TRACE_INFO,
*** 497,509 ****
// get the current OpenGL primary color state
j2d_glGetFloatv(GL_CURRENT_COLOR, clr);
// gamma adjust the primary color
! radj = (GLfloat)pow(clr[0], gamma);
! gadj = (GLfloat)pow(clr[1], gamma);
! badj = (GLfloat)pow(clr[2], gamma);
// update the "src_adj" parameter of the shader program with this value
loc = j2d_glGetUniformLocationARB(lcdTextProgram, "src_adj");
j2d_glUniform3fARB(loc, radj, gadj, badj);
--- 409,421 ----
// get the current OpenGL primary color state
j2d_glGetFloatv(GL_CURRENT_COLOR, clr);
// gamma adjust the primary color
! radj = (GLfloat)pow(clr[0], invgamma);
! gadj = (GLfloat)pow(clr[1], invgamma);
! badj = (GLfloat)pow(clr[2], invgamma);
// update the "src_adj" parameter of the shader program with this value
loc = j2d_glGetUniformLocationARB(lcdTextProgram, "src_adj");
j2d_glUniform3fARB(loc, radj, gadj, badj);
< prev index next >