Ejemplo n.º 1
0
static jboolean
OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
                           GlyphInfo *ginfo, jint x, jint y,
                           jint glyphIndex, jint totalGlyphs,
                           jboolean rgbOrder, jint contrast)
{
    CacheCellInfo *cell;
    jint dx1, dy1, dx2, dy2;
    jfloat dtx1, dty1, dtx2, dty2;

    if (glyphMode != MODE_USE_CACHE_LCD) {
        OGLTR_DisableGlyphModeState();
        CHECK_PREVIOUS_OP(GL_TEXTURE_2D);
        j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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

        if (rgbOrder != lastRGBOrder) {
            // need to invalidate the cache in this case; see comments
            // for lastRGBOrder above
            AccelGlyphCache_Invalidate(glyphCache);
            lastRGBOrder = rgbOrder;
        }

        if (!OGLTR_EnableLCDGlyphModeState(glyphCache->cacheID, contrast)) {
            return JNI_FALSE;
        }

        // when a fragment shader is enabled, the texture function state is
        // ignored, so the following line is not needed...
        // OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE);

        glyphMode = MODE_USE_CACHE_LCD;
    }

    if (ginfo->cellInfo == NULL) {
        // rowBytes will always be a multiple of 3, so the following is safe
        j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, ginfo->rowBytes / 3);

        // make sure the glyph cache texture is bound to texture unit 0
        j2d_glActiveTextureARB(GL_TEXTURE0_ARB);

        // attempt to add glyph to accelerated glyph cache
        OGLTR_AddToGlyphCache(ginfo, rgbOrder);

        if (ginfo->cellInfo == NULL) {
            // we'll just no-op in the rare case that the cell is NULL
            return JNI_TRUE;
        }
    }

    cell = (CacheCellInfo *) (ginfo->cellInfo);
    cell->timesRendered++;

    // location of the glyph in the destination's coordinate space
    dx1 = x;
    dy1 = y;
    dx2 = dx1 + ginfo->width;
    dy2 = dy1 + ginfo->height;

    // copy destination into second cached texture, if necessary
    OGLTR_UpdateCachedDestination(dstOps, ginfo,
                                  dx1, dy1, dx2, dy2,
                                  glyphIndex, totalGlyphs);

    // texture coordinates of the destination tile
    dtx1 = ((jfloat)(dx1 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH;
    dty1 = ((jfloat)(cachedDestBounds.y2 - dy1)) / OGLTR_CACHED_DEST_HEIGHT;
    dtx2 = ((jfloat)(dx2 - cachedDestBounds.x1)) / OGLTR_CACHED_DEST_WIDTH;
    dty2 = ((jfloat)(cachedDestBounds.y2 - dy2)) / OGLTR_CACHED_DEST_HEIGHT;

    // render composed texture to the destination surface
    j2d_glBegin(GL_QUADS);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, cell->tx1, cell->ty1);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty1);
    j2d_glVertex2i(dx1, dy1);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, cell->tx2, cell->ty1);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx2, dty1);
    j2d_glVertex2i(dx2, dy1);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, cell->tx2, cell->ty2);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx2, dty2);
    j2d_glVertex2i(dx2, dy2);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, cell->tx1, cell->ty2);
    j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty2);
    j2d_glVertex2i(dx1, dy2);
    j2d_glEnd();

    return JNI_TRUE;
}
Ejemplo n.º 2
0
static jboolean
OGLTR_DrawLCDGlyphNoCache(OGLContext *oglc, OGLSDOps *dstOps,
                          GlyphInfo *ginfo, jint x, jint y,
                          jint rowBytesOffset,
                          jboolean rgbOrder, jint contrast)
{
    GLfloat tx1, ty1, tx2, ty2;
    GLfloat dtx1, dty1, dtx2, dty2;
    jint tw, th;
    jint sx, sy, sw, sh, dxadj, dyadj;
    jint x0;
    jint w = ginfo->width;
    jint h = ginfo->height;
    GLenum pixelFormat = rgbOrder ? GL_RGB : GL_BGR;

    if (glyphMode != MODE_NO_CACHE_LCD) {
        OGLTR_DisableGlyphModeState();
        CHECK_PREVIOUS_OP(GL_TEXTURE_2D);
        j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        if (oglc->blitTextureID == 0) {
            if (!OGLContext_InitBlitTileTexture(oglc)) {
                return JNI_FALSE;
            }
        }

        if (!OGLTR_EnableLCDGlyphModeState(oglc->blitTextureID, contrast)) {
            return JNI_FALSE;
        }

        // when a fragment shader is enabled, the texture function state is
        // ignored, so the following line is not needed...
        // OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE);

        glyphMode = MODE_NO_CACHE_LCD;
    }

    // rowBytes will always be a multiple of 3, so the following is safe
    j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, ginfo->rowBytes / 3);

    x0 = x;
    tx1 = 0.0f;
    ty1 = 0.0f;
    dtx1 = 0.0f;
    dty2 = 0.0f;
    tw = OGLTR_NOCACHE_TILE_SIZE;
    th = OGLTR_NOCACHE_TILE_SIZE;

    for (sy = 0; sy < h; sy += th, y += th) {
        x = x0;
        sh = ((sy + th) > h) ? (h - sy) : th;

        for (sx = 0; sx < w; sx += tw, x += tw) {
            sw = ((sx + tw) > w) ? (w - sx) : tw;

            // update the source pointer offsets
            j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
            j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);

            // copy LCD mask into glyph texture tile
            j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
            j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
                                0, 0, sw, sh,
                                pixelFormat, GL_UNSIGNED_BYTE,
                                ginfo->image + rowBytesOffset);

            // update the lower-right glyph texture coordinates
            tx2 = ((GLfloat)sw) / OGLC_BLIT_TILE_SIZE;
            ty2 = ((GLfloat)sh) / OGLC_BLIT_TILE_SIZE;

            // this accounts for lower-left origin of the destination region
            dxadj = dstOps->xOffset + x;
            dyadj = dstOps->yOffset + dstOps->height - (y + sh);

            // copy destination into cached texture tile (the lower-left
            // corner of the destination region will be positioned at the
            // lower-left corner (0,0) of the texture)
            j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
            j2d_glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
                                    0, 0,
                                    dxadj, dyadj,
                                    sw, sh);

            // update the remaining destination texture coordinates
            dtx2 = ((GLfloat)sw) / OGLTR_CACHED_DEST_WIDTH;
            dty1 = ((GLfloat)sh) / OGLTR_CACHED_DEST_HEIGHT;

            // render composed texture to the destination surface
            j2d_glBegin(GL_QUADS);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, tx1, ty1);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty1);
            j2d_glVertex2i(x, y);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, tx2, ty1);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx2, dty1);
            j2d_glVertex2i(x + sw, y);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, tx2, ty2);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx2, dty2);
            j2d_glVertex2i(x + sw, y + sh);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE0_ARB, tx1, ty2);
            j2d_glMultiTexCoord2fARB(GL_TEXTURE1_ARB, dtx1, dty2);
            j2d_glVertex2i(x, y + sh);
            j2d_glEnd();
        }
    }

    return JNI_TRUE;
}
Ejemplo n.º 3
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;
}