예제 #1
0
/**
 * Initializes the OpenGL logic op state to XOR mode.  Blending is disabled
 * before enabling logic op mode.  The XOR pixel value will be applied
 * later in the OGLContext_SetColor() method.
 */
void
OGLContext_SetXorComposite(OGLContext *oglc, jint xorPixel)
{
    J2dTraceLn1(J2D_TRACE_INFO,
                "OGLContext_SetXorComposite: xorPixel=%08x", xorPixel);

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    // disable blending mode
    if (oglc->compState == sun_java2d_SunGraphics2D_COMP_ALPHA) {
        j2d_glDisable(GL_BLEND);
    }

    // enable XOR mode
    j2d_glEnable(GL_COLOR_LOGIC_OP);
    j2d_glLogicOp(GL_XOR);

    // set up the alpha test so that we discard transparent fragments (this
    // is primarily useful for rendering text in XOR mode)
    j2d_glEnable(GL_ALPHA_TEST);
    j2d_glAlphaFunc(GL_NOTEQUAL, 0.0f);

    // update state
    oglc->compState = sun_java2d_SunGraphics2D_COMP_XOR;
    oglc->xorPixel = xorPixel;
    oglc->extraAlpha = 1.0f;
}
예제 #2
0
/**
 * Enables the LCD text shader and updates any related state, such as the
 * gamma lookup table textures.
 */
static jboolean
OGLTR_EnableLCDGlyphModeState(GLuint glyphTextureID, jint contrast)
{
    // bind the texture containing glyph data to texture unit 0
    j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
    j2d_glBindTexture(GL_TEXTURE_2D, glyphTextureID);

    // bind the texture tile containing destination data to texture unit 1
    j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
    if (cachedDestTextureID == 0) {
        cachedDestTextureID =
            OGLContext_CreateBlitTexture(GL_RGB8, GL_RGB,
                                         OGLTR_CACHED_DEST_WIDTH,
                                         OGLTR_CACHED_DEST_HEIGHT);
        if (cachedDestTextureID == 0) {
            return JNI_FALSE;
        }
    }
    j2d_glBindTexture(GL_TEXTURE_2D, cachedDestTextureID);

    // note that GL_TEXTURE_2D was already enabled for texture unit 0,
    // but we need to explicitly enable it for texture unit 1
    j2d_glEnable(GL_TEXTURE_2D);

    // create the LCD text shader, if necessary
    if (lcdTextProgram == 0) {
        lcdTextProgram = OGLTR_CreateLCDTextProgram();
        if (lcdTextProgram == 0) {
            return JNI_FALSE;
        }
    }

    // enable the LCD text shader
    j2d_glUseProgramObjectARB(lcdTextProgram);

    // update the current contrast settings, if necessary
    if (lastLCDContrast != contrast) {
        if (!OGLTR_UpdateLCDTextContrast(contrast)) {
            return JNI_FALSE;
        }
        lastLCDContrast = contrast;
    }

    // update the current color settings
    if (!OGLTR_UpdateLCDTextColor(contrast)) {
        return JNI_FALSE;
    }

    // bind the gamma LUT textures
    j2d_glActiveTextureARB(GL_TEXTURE2_ARB);
    j2d_glBindTexture(GL_TEXTURE_3D, invGammaLutTextureID);
    j2d_glEnable(GL_TEXTURE_3D);
    j2d_glActiveTextureARB(GL_TEXTURE3_ARB);
    j2d_glBindTexture(GL_TEXTURE_3D, gammaLutTextureID);
    j2d_glEnable(GL_TEXTURE_3D);

    return JNI_TRUE;
}
예제 #3
0
/**
 * Sets up a complex (shape) clip using the OpenGL depth buffer.  This
 * method prepares the depth buffer so that the clip Region spans can
 * be "rendered" into it.  The depth buffer is first cleared, then the
 * depth func is setup so that when we render the clip spans,
 * nothing is rendered into the color buffer, but for each pixel that would
 * be rendered, a non-zero value is placed into that location in the depth
 * buffer.  With depth test enabled, pixels will only be rendered into the
 * color buffer if the corresponding value at that (x,y) location in the
 * depth buffer differs from the incoming depth value.
 */
void
OGLContext_BeginShapeClip(OGLContext *oglc)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_BeginShapeClip");

    RETURN_IF_NULL(oglc);
    RESET_PREVIOUS_OP();

    j2d_glDisable(GL_SCISSOR_TEST);

    // enable depth test and clear depth buffer so that depth values are at
    // their maximum; also set the depth func to GL_ALWAYS so that the
    // depth values of the clip spans are forced into the depth buffer
    j2d_glEnable(GL_DEPTH_TEST);
    j2d_glClearDepth(1.0);
    j2d_glClear(GL_DEPTH_BUFFER_BIT);
    j2d_glDepthFunc(GL_ALWAYS);

    // disable writes into the color buffer while we set up the clip
    j2d_glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

    // save current transform
    j2d_glMatrixMode(GL_MODELVIEW);
    j2d_glPushMatrix();

    // use identity transform plus slight translation in the z-axis when
    // setting the clip spans; this will push the clip spans (which would
    // normally be at z=0) to the z=1 plane to give them some depth
    j2d_glLoadIdentity();
    j2d_glTranslatef(0.0f, 0.0f, 1.0f);
}
예제 #4
0
/**
 * Sets the OpenGL scissor bounds to the provided rectangular clip bounds.
 */
void
OGLContext_SetRectClip(OGLContext *oglc, OGLSDOps *dstOps,
                       jint x1, jint y1, jint x2, jint y2)
{
    jint width = x2 - x1;
    jint height = y2 - y1;

    J2dTraceLn4(J2D_TRACE_INFO,
                "OGLContext_SetRectClip: x=%d y=%d w=%d h=%d",
                x1, y1, width, height);

    RETURN_IF_NULL(dstOps);
    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    if ((width < 0) || (height < 0)) {
        // use an empty scissor rectangle when the region is empty
        width = 0;
        height = 0;
    }

    j2d_glDisable(GL_DEPTH_TEST);
    j2d_glEnable(GL_SCISSOR_TEST);

    // the scissor rectangle is specified using the lower-left
    // origin of the clip region (in the framebuffer's coordinate
    // space), so we must account for the x/y offsets of the
    // destination surface
    j2d_glScissor(dstOps->xOffset + x1,
                  dstOps->yOffset + dstOps->height - (y1 + height),
                  width, height);
}
예제 #5
0
/**
 * Initializes the alpha channel of the current surface so that it contains
 * fully opaque alpha values.
 */
static void
OGLContext_InitAlphaChannel()
{
    GLboolean scissorEnabled;

    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_InitAlphaChannel");

    // it is possible for the scissor test to be enabled at this point;
    // if it is, disable it temporarily since it can affect the glClear() op
    scissorEnabled = j2d_glIsEnabled(GL_SCISSOR_TEST);
    if (scissorEnabled) {
        j2d_glDisable(GL_SCISSOR_TEST);
    }

    // set the color mask so that we only affect the alpha channel
    j2d_glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

    // clear the color buffer so that the alpha channel is fully opaque
    j2d_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    j2d_glClear(GL_COLOR_BUFFER_BIT);

    // restore the color mask (as it was set in OGLContext_SetViewport())
    j2d_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

    // re-enable scissor test, only if it was enabled earlier
    if (scissorEnabled) {
        j2d_glEnable(GL_SCISSOR_TEST);
    }
}
예제 #6
0
void
OGLTR_EnableGlyphVertexCache(OGLContext *oglc)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLTR_EnableGlyphVertexCache");

    if (glyphCache == NULL) {
        if (!OGLTR_InitGlyphCache(JNI_FALSE)) {
            return;
        }
    }

    j2d_glEnable(GL_TEXTURE_2D);
    j2d_glBindTexture(GL_TEXTURE_2D, glyphCache->cacheID);
    j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    // for grayscale/monochrome text, the current OpenGL source color
    // is modulated with the glyph image as part of the texture
    // application stage, so we use GL_MODULATE here
    OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE);
}
예제 #7
0
/**
 * Initializes the OpenGL blending state.  XOR mode is disabled and the
 * appropriate blend functions are setup based on the AlphaComposite rule
 * constant.
 */
void
OGLContext_SetAlphaComposite(OGLContext *oglc,
                             jint rule, jfloat extraAlpha, jint flags)
{
    J2dTraceLn1(J2D_TRACE_INFO,
                "OGLContext_SetAlphaComposite: flags=%d", flags);

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    // disable XOR mode
    if (oglc->compState == sun_java2d_SunGraphics2D_COMP_XOR) {
        j2d_glDisable(GL_COLOR_LOGIC_OP);
        j2d_glDisable(GL_ALPHA_TEST);
    }

    // we can safely disable blending when:
    //   - comp is SrcNoEa or SrcOverNoEa, and
    //   - the source is opaque
    // (turning off blending can have a large positive impact on
    // performance)
    if ((rule == RULE_Src || rule == RULE_SrcOver) &&
            (extraAlpha == 1.0f) &&
            (flags & OGLC_SRC_IS_OPAQUE))
    {
        J2dTraceLn1(J2D_TRACE_VERBOSE,
                    "  disabling alpha comp: rule=%d ea=1.0 src=opq", rule);
        j2d_glDisable(GL_BLEND);
    } else {
        J2dTraceLn2(J2D_TRACE_VERBOSE,
                    "  enabling alpha comp: rule=%d ea=%f", rule, extraAlpha);
        j2d_glEnable(GL_BLEND);
        j2d_glBlendFunc(StdBlendRules[rule].src, StdBlendRules[rule].dst);
    }

    // update state
    oglc->compState = sun_java2d_SunGraphics2D_COMP_ALPHA;
    oglc->extraAlpha = extraAlpha;
}
예제 #8
0
/**
 * Used to track whether we are within a series of simple primitive operations
 * or texturing operations.  The op parameter determines the nature of the
 * operation that is to follow.  Valid values for this op parameter are:
 *
 *     GL_QUADS
 *     GL_LINES
 *     GL_LINE_LOOP
 *     GL_LINE_STRIP
 *     (basically any of the valid parameters for glBegin())
 *
 *     GL_TEXTURE_2D
 *     GL_TEXTURE_RECTANGLE_ARB
 *
 *     OGL_STATE_RESET
 *     OGL_STATE_CHANGE
 *     OGL_STATE_MASK_OP
 *     OGL_STATE_GLYPH_OP
 *
 * Note that the above constants are guaranteed to be unique values.  The
 * last few are defined to be negative values to differentiate them from
 * the core GL* constants, which are defined to be non-negative.
 *
 * For simple primitives, this method allows us to batch similar primitives
 * within the same glBegin()/glEnd() pair.  For example, if we have 100
 * consecutive FILL_RECT operations, we only have to call glBegin(GL_QUADS)
 * for the first op, and then subsequent operations will consist only of
 * glVertex*() calls, which helps improve performance.  The glEnd() call
 * only needs to be issued before an operation that cannot happen within a
 * glBegin()/glEnd() pair (e.g. updating the clip), or one that requires a
 * different primitive mode (e.g. GL_LINES).
 *
 * For operations that involve texturing, this method helps us to avoid
 * calling glEnable(GL_TEXTURE_2D) and glDisable(GL_TEXTURE_2D) around each
 * operation.  For example, if we have an alternating series of ISO_BLIT
 * and MASK_BLIT operations (both of which involve texturing), we need
 * only to call glEnable(GL_TEXTURE_2D) before the first ISO_BLIT operation.
 * The glDisable(GL_TEXTURE_2D) call only needs to be issued before an
 * operation that cannot (or should not) happen while texturing is enabled
 * (e.g. a context change, or a simple primitive operation like GL_QUADS).
 */
void
OGLRenderQueue_CheckPreviousOp(jint op)
{
    if (previousOp == op) {
        // The op is the same as last time, so we can return immediately.
        return;
    }

    J2dTraceLn1(J2D_TRACE_VERBOSE,
                "OGLRenderQueue_CheckPreviousOp: new op=%d", op);

    switch (previousOp) {
    case GL_TEXTURE_2D:
    case GL_TEXTURE_RECTANGLE_ARB:
        if (op == OGL_STATE_CHANGE) {
            // Optimization: Certain state changes (those marked as
            // OGL_STATE_CHANGE) are allowed while texturing is enabled.
            // In this case, we can allow previousOp to remain as it is and
            // then return early.
            return;
        } else {
            // Otherwise, op must be a primitive operation, or a reset, so
            // we will disable texturing.
            j2d_glDisable(previousOp);
            // This next step of binding to zero should not be strictly
            // necessary, but on some older Nvidia boards (e.g. GeForce 2)
            // problems will arise if GL_TEXTURE_2D and
            // GL_TEXTURE_RECTANGLE_ARB are bound at the same time, so we
            // will do this just to be safe.
            j2d_glBindTexture(previousOp, 0);
        }
        break;
    case OGL_STATE_MASK_OP:
        OGLVertexCache_DisableMaskCache(oglc);
        break;
    case OGL_STATE_GLYPH_OP:
        OGLTR_DisableGlyphVertexCache(oglc);
        break;
    case OGL_STATE_PGRAM_OP:
        OGLRenderer_DisableAAParallelogramProgram();
        break;
    case OGL_STATE_RESET:
    case OGL_STATE_CHANGE:
        // No-op
        break;
    default:
        // In this case, op must be one of:
        //     - the start of a different primitive type (glBegin())
        //     - a texturing operation
        //     - a state change (not allowed within glBegin()/glEnd() pairs)
        //     - a reset
        // so we must first complete the previous primitive operation.
        j2d_glEnd();
        break;
    }

    switch (op) {
    case GL_TEXTURE_2D:
    case GL_TEXTURE_RECTANGLE_ARB:
        // We are starting a texturing operation, so enable texturing.
        j2d_glEnable(op);
        break;
    case OGL_STATE_MASK_OP:
        OGLVertexCache_EnableMaskCache(oglc);
        break;
    case OGL_STATE_GLYPH_OP:
        OGLTR_EnableGlyphVertexCache(oglc);
        break;
    case OGL_STATE_PGRAM_OP:
        OGLRenderer_EnableAAParallelogramProgram();
        break;
    case OGL_STATE_RESET:
    case OGL_STATE_CHANGE:
        // No-op
        break;
    default:
        // We are starting a primitive operation, so call glBegin() with
        // the given primitive type.
        j2d_glBegin(op);
        break;
    }

    previousOp = op;
}