< prev index next >

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

Print this page




  43  * The ConvolveOp shader is fairly straightforward.  For each texel in
  44  * the source texture, the shader samples the MxN texels in the surrounding
  45  * area, multiplies each by its corresponding kernel value, and then sums
  46  * them all together to produce a single color result.  Finally, the
  47  * resulting value is multiplied by the current OpenGL color, which contains
  48  * the extra alpha value.
  49  *
  50  * Note that this shader source code includes some "holes" marked by "%s".
  51  * This allows us to build different shader programs (e.g. one for
  52  * 3x3, one for 5x5, and so on) simply by filling in these "holes" with
  53  * a call to sprintf().  See the OGLBufImgOps_CreateConvolveProgram() method
  54  * for more details.
  55  *
  56  * REMIND: Currently this shader (and the supporting code in the
  57  *         EnableConvolveOp() method) only supports 3x3 and 5x5 filters.
  58  *         Early shader-level hardware did not support non-constant sized
  59  *         arrays but modern hardware should support them (although I
  60  *         don't know of any simple way to find out, other than to compile
  61  *         the shader at runtime and see if the drivers complain).
  62  */
  63 static const char *convolveShaderSource =
  64     // maximum size supported by this shader
  65     "const int MAX_KERNEL_SIZE = %s;"
  66     // image to be convolved
  67     "uniform sampler%s baseImage;"
  68     // image edge limits:
  69     //   imgEdge.xy = imgMin.xy (anything < will be treated as edge case)
  70     //   imgEdge.zw = imgMax.xy (anything > will be treated as edge case)
  71     "uniform vec4 imgEdge;"
  72     // value for each location in the convolution kernel:
  73     //   kernelVals[i].x = offsetX[i]
  74     //   kernelVals[i].y = offsetY[i]
  75     //   kernelVals[i].z = kernel[i]
  76     "uniform vec3 kernelVals[MAX_KERNEL_SIZE];"
  77     ""
  78     "void main(void)"
  79     "{"
  80     "    int i;"
  81     "    vec4 sum;"
  82     ""
  83     "    if (any(lessThan(gl_TexCoord[0].st, imgEdge.xy)) ||"
  84     "        any(greaterThan(gl_TexCoord[0].st, imgEdge.zw)))"
  85     "    {"
  86              // (placeholder for edge condition code)
  87     "        %s"
  88     "    } else {"
  89     "        sum = vec4(0.0);"
  90     "        for (i = 0; i < MAX_KERNEL_SIZE; i++) {"
  91     "            sum +="
  92     "                kernelVals[i].z *"
  93     "                texture%s(baseImage,"
  94     "                          gl_TexCoord[0].st + kernelVals[i].xy);"
  95     "        }"
  96     "    }"
  97     ""
  98          // modulate with gl_Color in order to apply extra alpha
  99     "    gl_FragColor = sum * gl_Color;"
 100     "}";
 101 
 102 /**
 103  * Flags that can be bitwise-or'ed together to control how the shader
 104  * source code is generated.
 105  */
 106 #define CONVOLVE_RECT            (1 << 0)
 107 #define CONVOLVE_EDGE_ZERO_FILL  (1 << 1)
 108 #define CONVOLVE_5X5             (1 << 2)
 109 
 110 /**
 111  * The handles to the ConvolveOp fragment program objects.  The index to
 112  * the array should be a bitwise-or'ing of the CONVOLVE_* flags defined
 113  * above.  Note that most applications will likely need to initialize one
 114  * or two of these elements, so the array is usually sparsely populated.
 115  */
 116 static GLhandleARB convolvePrograms[8];
 117 
 118 /**
 119  * The maximum kernel size supported by the ConvolveOp shader.
 120  */


 133     char *kernelMax = IS_SET(CONVOLVE_5X5) ? "25" : "9";
 134     char *target = IS_SET(CONVOLVE_RECT) ? "2DRect" : "2D";
 135     char edge[100];
 136     char finalSource[2000];
 137 
 138     J2dTraceLn1(J2D_TRACE_INFO,
 139                 "OGLBufImgOps_CreateConvolveProgram: flags=%d",
 140                 flags);
 141 
 142     if (IS_SET(CONVOLVE_EDGE_ZERO_FILL)) {
 143         // EDGE_ZERO_FILL: fill in zero at the edges
 144         sprintf(edge, "sum = vec4(0.0);");
 145     } else {
 146         // EDGE_NO_OP: use the source pixel color at the edges
 147         sprintf(edge,
 148                 "sum = texture%s(baseImage, gl_TexCoord[0].st);",
 149                 target);
 150     }
 151 
 152     // compose the final source code string from the various pieces
 153     sprintf(finalSource, convolveShaderSource,
 154             kernelMax, target, edge, target);




































 155 
 156     convolveProgram = OGLContext_CreateFragmentProgram(finalSource);
 157     if (convolveProgram == 0) {
 158         J2dRlsTraceLn(J2D_TRACE_ERROR,
 159             "OGLBufImgOps_CreateConvolveProgram: error creating program");
 160         return 0;
 161     }
 162 
 163     // "use" the program object temporarily so that we can set the uniforms
 164     j2d_glUseProgramObjectARB(convolveProgram);
 165 
 166     // set the "uniform" texture unit binding
 167     loc = j2d_glGetUniformLocationARB(convolveProgram, "baseImage");
 168     j2d_glUniform1iARB(loc, 0); // texture unit 0
 169 
 170     // "unuse" the program object; it will be re-bound later as needed
 171     j2d_glUseProgramObjectARB(0);
 172 
 173     return convolveProgram;
 174 }


 282  * to the user's offset value (these are component-wise operations).
 283  * Finally, the resulting value is multiplied by the current OpenGL color,
 284  * which contains the extra alpha value.
 285  *
 286  * The RescaleOp spec says that the operation is performed regardless of
 287  * whether the source data is premultiplied or non-premultiplied.  This is
 288  * a problem for the OpenGL pipeline in that a non-premultiplied
 289  * BufferedImage will have already been converted into premultiplied
 290  * when uploaded to an OpenGL texture.  Therefore, we have a special mode
 291  * called RESCALE_NON_PREMULT (used only for source images that were
 292  * originally non-premultiplied) that un-premultiplies the source color
 293  * prior to the rescale operation, then re-premultiplies the resulting
 294  * color before returning from the fragment shader.
 295  *
 296  * Note that this shader source code includes some "holes" marked by "%s".
 297  * This allows us to build different shader programs (e.g. one for
 298  * GL_TEXTURE_2D targets, one for GL_TEXTURE_RECTANGLE_ARB targets, and so on)
 299  * simply by filling in these "holes" with a call to sprintf().  See the
 300  * OGLBufImgOps_CreateRescaleProgram() method for more details.
 301  */
 302 static const char *rescaleShaderSource =
 303     // image to be rescaled
 304     "uniform sampler%s baseImage;"
 305     // vector containing scale factors
 306     "uniform vec4 scaleFactors;"
 307     // vector containing offsets
 308     "uniform vec4 offsets;"
 309     ""
 310     "void main(void)"
 311     "{"
 312     "    vec4 srcColor = texture%s(baseImage, gl_TexCoord[0].st);"
 313          // (placeholder for un-premult code)
 314     "    %s"
 315          // rescale source value
 316     "    vec4 result = (srcColor * scaleFactors) + offsets;"
 317          // (placeholder for re-premult code)
 318     "    %s"
 319          // modulate with gl_Color in order to apply extra alpha
 320     "    gl_FragColor = result * gl_Color;"
 321     "}";
 322 
 323 /**
 324  * Flags that can be bitwise-or'ed together to control how the shader
 325  * source code is generated.
 326  */
 327 #define RESCALE_RECT        (1 << 0)
 328 #define RESCALE_NON_PREMULT (1 << 1)
 329 
 330 /**
 331  * The handles to the RescaleOp fragment program objects.  The index to
 332  * the array should be a bitwise-or'ing of the RESCALE_* flags defined
 333  * above.  Note that most applications will likely need to initialize one
 334  * or two of these elements, so the array is usually sparsely populated.
 335  */
 336 static GLhandleARB rescalePrograms[4];
 337 
 338 /**
 339  * Compiles and links the RescaleOp shader program.  If successful, this
 340  * function returns a handle to the newly created shader program; otherwise
 341  * returns 0.


 343 static GLhandleARB
 344 OGLBufImgOps_CreateRescaleProgram(jint flags)
 345 {
 346     GLhandleARB rescaleProgram;
 347     GLint loc;
 348     char *target = IS_SET(RESCALE_RECT) ? "2DRect" : "2D";
 349     char *preRescale = "";
 350     char *postRescale = "";
 351     char finalSource[2000];
 352 
 353     J2dTraceLn1(J2D_TRACE_INFO,
 354                 "OGLBufImgOps_CreateRescaleProgram: flags=%d",
 355                 flags);
 356 
 357     if (IS_SET(RESCALE_NON_PREMULT)) {
 358         preRescale  = "srcColor.rgb /= srcColor.a;";
 359         postRescale = "result.rgb *= result.a;";
 360     }
 361 
 362     // compose the final source code string from the various pieces
 363     sprintf(finalSource, rescaleShaderSource,
 364             target, target, preRescale, postRescale);


















 365 
 366     rescaleProgram = OGLContext_CreateFragmentProgram(finalSource);
 367     if (rescaleProgram == 0) {
 368         J2dRlsTraceLn(J2D_TRACE_ERROR,
 369             "OGLBufImgOps_CreateRescaleProgram: error creating program");
 370         return 0;
 371     }
 372 
 373     // "use" the program object temporarily so that we can set the uniforms
 374     j2d_glUseProgramObjectARB(rescaleProgram);
 375 
 376     // set the "uniform" values
 377     loc = j2d_glGetUniformLocationARB(rescaleProgram, "baseImage");
 378     j2d_glUniform1iARB(loc, 0); // texture unit 0
 379 
 380     // "unuse" the program object; it will be re-bound later as needed
 381     j2d_glUseProgramObjectARB(0);
 382 
 383     return rescaleProgram;
 384 }


 488  * this fact because the software LookupOp implementation would usually
 489  * throw an ArrayIndexOutOfBoundsException in this scenario (although it is
 490  * not something demanded by the spec).
 491  *
 492  * The LookupOp spec says that the operation is performed regardless of
 493  * whether the source data is premultiplied or non-premultiplied.  This is
 494  * a problem for the OpenGL pipeline in that a non-premultiplied
 495  * BufferedImage will have already been converted into premultiplied
 496  * when uploaded to an OpenGL texture.  Therefore, we have a special mode
 497  * called LOOKUP_NON_PREMULT (used only for source images that were
 498  * originally non-premultiplied) that un-premultiplies the source color
 499  * prior to the lookup operation, then re-premultiplies the resulting
 500  * color before returning from the fragment shader.
 501  *
 502  * Note that this shader source code includes some "holes" marked by "%s".
 503  * This allows us to build different shader programs (e.g. one for
 504  * GL_TEXTURE_2D targets, one for GL_TEXTURE_RECTANGLE_ARB targets, and so on)
 505  * simply by filling in these "holes" with a call to sprintf().  See the
 506  * OGLBufImgOps_CreateLookupProgram() method for more details.
 507  */
 508 static const char *lookupShaderSource =
 509     // source image (bound to texture unit 0)
 510     "uniform sampler%s baseImage;"
 511     // lookup table (bound to texture unit 1)
 512     "uniform sampler2D lookupTable;"
 513     // offset subtracted from source index prior to lookup step
 514     "uniform vec4 offset;"
 515     ""
 516     "void main(void)"
 517     "{"
 518     "    vec4 srcColor = texture%s(baseImage, gl_TexCoord[0].st);"
 519          // (placeholder for un-premult code)
 520     "    %s"
 521          // subtract offset from original index
 522     "    vec4 srcIndex = srcColor - offset;"
 523          // use source value as input to lookup table (note that
 524          // "v" texcoords are hardcoded to hit texel centers of
 525          // each row/band in texture)
 526     "    vec4 result;"
 527     "    result.r = texture2D(lookupTable, vec2(srcIndex.r, 0.125)).r;"
 528     "    result.g = texture2D(lookupTable, vec2(srcIndex.g, 0.375)).r;"
 529     "    result.b = texture2D(lookupTable, vec2(srcIndex.b, 0.625)).r;"
 530          // (placeholder for alpha store code)
 531     "    %s"
 532          // (placeholder for re-premult code)
 533     "    %s"
 534          // modulate with gl_Color in order to apply extra alpha
 535     "    gl_FragColor = result * gl_Color;"
 536     "}";
 537 
 538 /**
 539  * Flags that can be bitwise-or'ed together to control how the shader
 540  * source code is generated.
 541  */
 542 #define LOOKUP_RECT          (1 << 0)
 543 #define LOOKUP_USE_SRC_ALPHA (1 << 1)
 544 #define LOOKUP_NON_PREMULT   (1 << 2)
 545 
 546 /**
 547  * The handles to the LookupOp fragment program objects.  The index to
 548  * the array should be a bitwise-or'ing of the LOOKUP_* flags defined
 549  * above.  Note that most applications will likely need to initialize one
 550  * or two of these elements, so the array is usually sparsely populated.
 551  */
 552 static GLhandleARB lookupPrograms[8];
 553 
 554 /**
 555  * The handle to the lookup table texture object used by the shader.
 556  */


 575     J2dTraceLn1(J2D_TRACE_INFO,
 576                 "OGLBufImgOps_CreateLookupProgram: flags=%d",
 577                 flags);
 578 
 579     if (IS_SET(LOOKUP_USE_SRC_ALPHA)) {
 580         // when numComps is 1 or 3, the alpha is not looked up in the table;
 581         // just keep the alpha from the source fragment
 582         alpha = "result.a = srcColor.a;";
 583     } else {
 584         // when numComps is 4, the alpha is looked up in the table, just
 585         // like the other color components from the source fragment
 586         alpha =
 587             "result.a = texture2D(lookupTable, vec2(srcIndex.a, 0.875)).r;";
 588     }
 589     if (IS_SET(LOOKUP_NON_PREMULT)) {
 590         preLookup  = "srcColor.rgb /= srcColor.a;";
 591         postLookup = "result.rgb *= result.a;";
 592     }
 593 
 594     // compose the final source code string from the various pieces
 595     sprintf(finalSource, lookupShaderSource,
 596             target, target, preLookup, alpha, postLookup);



























 597 
 598     lookupProgram = OGLContext_CreateFragmentProgram(finalSource);
 599     if (lookupProgram == 0) {
 600         J2dRlsTraceLn(J2D_TRACE_ERROR,
 601             "OGLBufImgOps_CreateLookupProgram: error creating program");
 602         return 0;
 603     }
 604 
 605     // "use" the program object temporarily so that we can set the uniforms
 606     j2d_glUseProgramObjectARB(lookupProgram);
 607 
 608     // set the "uniform" values
 609     loc = j2d_glGetUniformLocationARB(lookupProgram, "baseImage");
 610     j2d_glUniform1iARB(loc, 0); // texture unit 0
 611     loc = j2d_glGetUniformLocationARB(lookupProgram, "lookupTable");
 612     j2d_glUniform1iARB(loc, 1); // texture unit 1
 613 
 614     // "unuse" the program object; it will be re-bound later as needed
 615     j2d_glUseProgramObjectARB(0);
 616 




  43  * The ConvolveOp shader is fairly straightforward.  For each texel in
  44  * the source texture, the shader samples the MxN texels in the surrounding
  45  * area, multiplies each by its corresponding kernel value, and then sums
  46  * them all together to produce a single color result.  Finally, the
  47  * resulting value is multiplied by the current OpenGL color, which contains
  48  * the extra alpha value.
  49  *
  50  * Note that this shader source code includes some "holes" marked by "%s".
  51  * This allows us to build different shader programs (e.g. one for
  52  * 3x3, one for 5x5, and so on) simply by filling in these "holes" with
  53  * a call to sprintf().  See the OGLBufImgOps_CreateConvolveProgram() method
  54  * for more details.
  55  *
  56  * REMIND: Currently this shader (and the supporting code in the
  57  *         EnableConvolveOp() method) only supports 3x3 and 5x5 filters.
  58  *         Early shader-level hardware did not support non-constant sized
  59  *         arrays but modern hardware should support them (although I
  60  *         don't know of any simple way to find out, other than to compile
  61  *         the shader at runtime and see if the drivers complain).
  62  */






































  63 
  64 /**
  65  * Flags that can be bitwise-or'ed together to control how the shader
  66  * source code is generated.
  67  */
  68 #define CONVOLVE_RECT            (1 << 0)
  69 #define CONVOLVE_EDGE_ZERO_FILL  (1 << 1)
  70 #define CONVOLVE_5X5             (1 << 2)
  71 
  72 /**
  73  * The handles to the ConvolveOp fragment program objects.  The index to
  74  * the array should be a bitwise-or'ing of the CONVOLVE_* flags defined
  75  * above.  Note that most applications will likely need to initialize one
  76  * or two of these elements, so the array is usually sparsely populated.
  77  */
  78 static GLhandleARB convolvePrograms[8];
  79 
  80 /**
  81  * The maximum kernel size supported by the ConvolveOp shader.
  82  */


  95     char *kernelMax = IS_SET(CONVOLVE_5X5) ? "25" : "9";
  96     char *target = IS_SET(CONVOLVE_RECT) ? "2DRect" : "2D";
  97     char edge[100];
  98     char finalSource[2000];
  99 
 100     J2dTraceLn1(J2D_TRACE_INFO,
 101                 "OGLBufImgOps_CreateConvolveProgram: flags=%d",
 102                 flags);
 103 
 104     if (IS_SET(CONVOLVE_EDGE_ZERO_FILL)) {
 105         // EDGE_ZERO_FILL: fill in zero at the edges
 106         sprintf(edge, "sum = vec4(0.0);");
 107     } else {
 108         // EDGE_NO_OP: use the source pixel color at the edges
 109         sprintf(edge,
 110                 "sum = texture%s(baseImage, gl_TexCoord[0].st);",
 111                 target);
 112     }
 113 
 114     // compose the final source code string from the various pieces
 115     sprintf(finalSource,
 116         // maximum size supported by this shader
 117         "const int MAX_KERNEL_SIZE = %s;"
 118         // image to be convolved
 119         "uniform sampler%s baseImage;"
 120         // image edge limits:
 121         //   imgEdge.xy = imgMin.xy (anything < will be treated as edge case)
 122         //   imgEdge.zw = imgMax.xy (anything > will be treated as edge case)
 123         "uniform vec4 imgEdge;"
 124         // value for each location in the convolution kernel:
 125         //   kernelVals[i].x = offsetX[i]
 126         //   kernelVals[i].y = offsetY[i]
 127         //   kernelVals[i].z = kernel[i]
 128         "uniform vec3 kernelVals[MAX_KERNEL_SIZE];"
 129         ""
 130         "void main(void)"
 131         "{"
 132         "    int i;"
 133         "    vec4 sum;"
 134         ""
 135         "    if (any(lessThan(gl_TexCoord[0].st, imgEdge.xy)) ||"
 136         "        any(greaterThan(gl_TexCoord[0].st, imgEdge.zw)))"
 137         "    {"
 138                  // (placeholder for edge condition code)
 139         "        %s"
 140         "    } else {"
 141         "        sum = vec4(0.0);"
 142         "        for (i = 0; i < MAX_KERNEL_SIZE; i++) {"
 143         "            sum +="
 144         "                kernelVals[i].z *"
 145         "                texture%s(baseImage,"
 146         "                          gl_TexCoord[0].st + kernelVals[i].xy);"
 147         "        }"
 148         "    }"
 149         ""
 150              // modulate with gl_Color in order to apply extra alpha
 151         "    gl_FragColor = sum * gl_Color;"
 152         "}", kernelMax, target, edge, target);
 153 
 154     convolveProgram = OGLContext_CreateFragmentProgram(finalSource);
 155     if (convolveProgram == 0) {
 156         J2dRlsTraceLn(J2D_TRACE_ERROR,
 157             "OGLBufImgOps_CreateConvolveProgram: error creating program");
 158         return 0;
 159     }
 160 
 161     // "use" the program object temporarily so that we can set the uniforms
 162     j2d_glUseProgramObjectARB(convolveProgram);
 163 
 164     // set the "uniform" texture unit binding
 165     loc = j2d_glGetUniformLocationARB(convolveProgram, "baseImage");
 166     j2d_glUniform1iARB(loc, 0); // texture unit 0
 167 
 168     // "unuse" the program object; it will be re-bound later as needed
 169     j2d_glUseProgramObjectARB(0);
 170 
 171     return convolveProgram;
 172 }


 280  * to the user's offset value (these are component-wise operations).
 281  * Finally, the resulting value is multiplied by the current OpenGL color,
 282  * which contains the extra alpha value.
 283  *
 284  * The RescaleOp spec says that the operation is performed regardless of
 285  * whether the source data is premultiplied or non-premultiplied.  This is
 286  * a problem for the OpenGL pipeline in that a non-premultiplied
 287  * BufferedImage will have already been converted into premultiplied
 288  * when uploaded to an OpenGL texture.  Therefore, we have a special mode
 289  * called RESCALE_NON_PREMULT (used only for source images that were
 290  * originally non-premultiplied) that un-premultiplies the source color
 291  * prior to the rescale operation, then re-premultiplies the resulting
 292  * color before returning from the fragment shader.
 293  *
 294  * Note that this shader source code includes some "holes" marked by "%s".
 295  * This allows us to build different shader programs (e.g. one for
 296  * GL_TEXTURE_2D targets, one for GL_TEXTURE_RECTANGLE_ARB targets, and so on)
 297  * simply by filling in these "holes" with a call to sprintf().  See the
 298  * OGLBufImgOps_CreateRescaleProgram() method for more details.
 299  */




















 300 
 301 /**
 302  * Flags that can be bitwise-or'ed together to control how the shader
 303  * source code is generated.
 304  */
 305 #define RESCALE_RECT        (1 << 0)
 306 #define RESCALE_NON_PREMULT (1 << 1)
 307 
 308 /**
 309  * The handles to the RescaleOp fragment program objects.  The index to
 310  * the array should be a bitwise-or'ing of the RESCALE_* flags defined
 311  * above.  Note that most applications will likely need to initialize one
 312  * or two of these elements, so the array is usually sparsely populated.
 313  */
 314 static GLhandleARB rescalePrograms[4];
 315 
 316 /**
 317  * Compiles and links the RescaleOp shader program.  If successful, this
 318  * function returns a handle to the newly created shader program; otherwise
 319  * returns 0.


 321 static GLhandleARB
 322 OGLBufImgOps_CreateRescaleProgram(jint flags)
 323 {
 324     GLhandleARB rescaleProgram;
 325     GLint loc;
 326     char *target = IS_SET(RESCALE_RECT) ? "2DRect" : "2D";
 327     char *preRescale = "";
 328     char *postRescale = "";
 329     char finalSource[2000];
 330 
 331     J2dTraceLn1(J2D_TRACE_INFO,
 332                 "OGLBufImgOps_CreateRescaleProgram: flags=%d",
 333                 flags);
 334 
 335     if (IS_SET(RESCALE_NON_PREMULT)) {
 336         preRescale  = "srcColor.rgb /= srcColor.a;";
 337         postRescale = "result.rgb *= result.a;";
 338     }
 339 
 340     // compose the final source code string from the various pieces
 341     sprintf(finalSource,
 342         // image to be rescaled
 343         "uniform sampler%s baseImage;"
 344         // vector containing scale factors
 345         "uniform vec4 scaleFactors;"
 346         // vector containing offsets
 347         "uniform vec4 offsets;"
 348         ""
 349         "void main(void)"
 350         "{"
 351         "    vec4 srcColor = texture%s(baseImage, gl_TexCoord[0].st);"
 352              // (placeholder for un-premult code)
 353         "    %s"
 354              // rescale source value
 355         "    vec4 result = (srcColor * scaleFactors) + offsets;"
 356              // (placeholder for re-premult code)
 357         "    %s"
 358              // modulate with gl_Color in order to apply extra alpha
 359         "    gl_FragColor = result * gl_Color;"
 360         "}", target, target, preRescale, postRescale);
 361 
 362     rescaleProgram = OGLContext_CreateFragmentProgram(finalSource);
 363     if (rescaleProgram == 0) {
 364         J2dRlsTraceLn(J2D_TRACE_ERROR,
 365             "OGLBufImgOps_CreateRescaleProgram: error creating program");
 366         return 0;
 367     }
 368 
 369     // "use" the program object temporarily so that we can set the uniforms
 370     j2d_glUseProgramObjectARB(rescaleProgram);
 371 
 372     // set the "uniform" values
 373     loc = j2d_glGetUniformLocationARB(rescaleProgram, "baseImage");
 374     j2d_glUniform1iARB(loc, 0); // texture unit 0
 375 
 376     // "unuse" the program object; it will be re-bound later as needed
 377     j2d_glUseProgramObjectARB(0);
 378 
 379     return rescaleProgram;
 380 }


 484  * this fact because the software LookupOp implementation would usually
 485  * throw an ArrayIndexOutOfBoundsException in this scenario (although it is
 486  * not something demanded by the spec).
 487  *
 488  * The LookupOp spec says that the operation is performed regardless of
 489  * whether the source data is premultiplied or non-premultiplied.  This is
 490  * a problem for the OpenGL pipeline in that a non-premultiplied
 491  * BufferedImage will have already been converted into premultiplied
 492  * when uploaded to an OpenGL texture.  Therefore, we have a special mode
 493  * called LOOKUP_NON_PREMULT (used only for source images that were
 494  * originally non-premultiplied) that un-premultiplies the source color
 495  * prior to the lookup operation, then re-premultiplies the resulting
 496  * color before returning from the fragment shader.
 497  *
 498  * Note that this shader source code includes some "holes" marked by "%s".
 499  * This allows us to build different shader programs (e.g. one for
 500  * GL_TEXTURE_2D targets, one for GL_TEXTURE_RECTANGLE_ARB targets, and so on)
 501  * simply by filling in these "holes" with a call to sprintf().  See the
 502  * OGLBufImgOps_CreateLookupProgram() method for more details.
 503  */





























 504 
 505 /**
 506  * Flags that can be bitwise-or'ed together to control how the shader
 507  * source code is generated.
 508  */
 509 #define LOOKUP_RECT          (1 << 0)
 510 #define LOOKUP_USE_SRC_ALPHA (1 << 1)
 511 #define LOOKUP_NON_PREMULT   (1 << 2)
 512 
 513 /**
 514  * The handles to the LookupOp fragment program objects.  The index to
 515  * the array should be a bitwise-or'ing of the LOOKUP_* flags defined
 516  * above.  Note that most applications will likely need to initialize one
 517  * or two of these elements, so the array is usually sparsely populated.
 518  */
 519 static GLhandleARB lookupPrograms[8];
 520 
 521 /**
 522  * The handle to the lookup table texture object used by the shader.
 523  */


 542     J2dTraceLn1(J2D_TRACE_INFO,
 543                 "OGLBufImgOps_CreateLookupProgram: flags=%d",
 544                 flags);
 545 
 546     if (IS_SET(LOOKUP_USE_SRC_ALPHA)) {
 547         // when numComps is 1 or 3, the alpha is not looked up in the table;
 548         // just keep the alpha from the source fragment
 549         alpha = "result.a = srcColor.a;";
 550     } else {
 551         // when numComps is 4, the alpha is looked up in the table, just
 552         // like the other color components from the source fragment
 553         alpha =
 554             "result.a = texture2D(lookupTable, vec2(srcIndex.a, 0.875)).r;";
 555     }
 556     if (IS_SET(LOOKUP_NON_PREMULT)) {
 557         preLookup  = "srcColor.rgb /= srcColor.a;";
 558         postLookup = "result.rgb *= result.a;";
 559     }
 560 
 561     // compose the final source code string from the various pieces
 562     sprintf(finalSource,
 563     // source image (bound to texture unit 0)
 564         "uniform sampler%s baseImage;"
 565         // lookup table (bound to texture unit 1)
 566         "uniform sampler2D lookupTable;"
 567         // offset subtracted from source index prior to lookup step
 568         "uniform vec4 offset;"
 569         ""
 570         "void main(void)"
 571         "{"
 572         "    vec4 srcColor = texture%s(baseImage, gl_TexCoord[0].st);"
 573              // (placeholder for un-premult code)
 574         "    %s"
 575              // subtract offset from original index
 576         "    vec4 srcIndex = srcColor - offset;"
 577              // use source value as input to lookup table (note that
 578              // "v" texcoords are hardcoded to hit texel centers of
 579              // each row/band in texture)
 580         "    vec4 result;"
 581         "    result.r = texture2D(lookupTable, vec2(srcIndex.r, 0.125)).r;"
 582         "    result.g = texture2D(lookupTable, vec2(srcIndex.g, 0.375)).r;"
 583         "    result.b = texture2D(lookupTable, vec2(srcIndex.b, 0.625)).r;"
 584              // (placeholder for alpha store code)
 585         "    %s"
 586              // (placeholder for re-premult code)
 587         "    %s"
 588              // modulate with gl_Color in order to apply extra alpha
 589         "    gl_FragColor = result * gl_Color;"
 590         "}", target, target, preLookup, alpha, postLookup);
 591 
 592     lookupProgram = OGLContext_CreateFragmentProgram(finalSource);
 593     if (lookupProgram == 0) {
 594         J2dRlsTraceLn(J2D_TRACE_ERROR,
 595             "OGLBufImgOps_CreateLookupProgram: error creating program");
 596         return 0;
 597     }
 598 
 599     // "use" the program object temporarily so that we can set the uniforms
 600     j2d_glUseProgramObjectARB(lookupProgram);
 601 
 602     // set the "uniform" values
 603     loc = j2d_glGetUniformLocationARB(lookupProgram, "baseImage");
 604     j2d_glUniform1iARB(loc, 0); // texture unit 0
 605     loc = j2d_glGetUniformLocationARB(lookupProgram, "lookupTable");
 606     j2d_glUniform1iARB(loc, 1); // texture unit 1
 607 
 608     // "unuse" the program object; it will be re-bound later as needed
 609     j2d_glUseProgramObjectARB(0);
 610 


< prev index next >