< 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 >