コード例 #1
0
ファイル: OGLContext.c プロジェクト: wei-tang/JVM
/**
 * Resets the current clip state (disables both scissor and depth tests).
 */
void
OGLContext_ResetClip(OGLContext *oglc)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_ResetClip");

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    j2d_glDisable(GL_SCISSOR_TEST);
    j2d_glDisable(GL_DEPTH_TEST);
}
コード例 #2
0
ファイル: OGLContext.c プロジェクト: wei-tang/JVM
/**
 * Resets the OpenGL transform state back to the identity matrix.
 */
void
OGLContext_ResetTransform(OGLContext *oglc)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_ResetTransform");

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    j2d_glMatrixMode(GL_MODELVIEW);
    j2d_glLoadIdentity();
}
コード例 #3
0
void
OGLRenderer_DrawRect(OGLContext *oglc, jint x, jint y, jint w, jint h)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawRect");

    if (w < 0 || h < 0) {
        return;
    }

    RETURN_IF_NULL(oglc);

    if (w < 2 || h < 2) {
        // If one dimension is less than 2 then there is no
        // gap in the middle - draw a solid filled rectangle.
        CHECK_PREVIOUS_OP(GL_QUADS);
        GLRECT_BODY_XYWH(x, y, w+1, h+1);
    } else {
        GLfloat fx1 = ((GLfloat)x) + 0.2f;
        GLfloat fy1 = ((GLfloat)y) + 0.2f;
        GLfloat fx2 = fx1 + ((GLfloat)w);
        GLfloat fy2 = fy1 + ((GLfloat)h);

        // Avoid drawing the endpoints twice.
        // Also prefer including the endpoints in the
        // horizontal sections which draw pixels faster.

        CHECK_PREVIOUS_OP(GL_LINES);
        // top
        j2d_glVertex2f(fx1,      fy1);
        j2d_glVertex2f(fx2+1.0f, fy1);
        // right
        j2d_glVertex2f(fx2,      fy1+1.0f);
        j2d_glVertex2f(fx2,      fy2);
        // bottom
        j2d_glVertex2f(fx1,      fy2);
        j2d_glVertex2f(fx2+1.0f, fy2);
        // left
        j2d_glVertex2f(fx1,      fy1+1.0f);
        j2d_glVertex2f(fx1,      fy2);
    }
}
コード例 #4
0
void
OGLRenderer_FillRect(OGLContext *oglc, jint x, jint y, jint w, jint h)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_FillRect");

    if (w <= 0 || h <= 0) {
        return;
    }

    RETURN_IF_NULL(oglc);

    CHECK_PREVIOUS_OP(GL_QUADS);
    GLRECT_BODY_XYWH(x, y, w, h);
}
コード例 #5
0
void
OGLRenderer_FillSpans(OGLContext *oglc, jint spanCount, jint *spans)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_FillSpans");

    RETURN_IF_NULL(oglc);
    RETURN_IF_NULL(spans);

    CHECK_PREVIOUS_OP(GL_QUADS);
    while (spanCount > 0) {
        jint x1 = *(spans++);
        jint y1 = *(spans++);
        jint x2 = *(spans++);
        jint y2 = *(spans++);
        GLRECT_BODY_XYXY(x1, y1, x2, y2);
        spanCount--;
    }
}
コード例 #6
0
ファイル: OGLMaskFill.c プロジェクト: AllenWeb/openjdk-1
/**
 * This implementation first copies the alpha tile into a texture and then
 * maps that texture to the destination surface.  This approach appears to
 * offer the best performance despite being a two-step process.
 *
 * When the source paint is a Color, we can simply use the GL_MODULATE
 * function to multiply the current color (already premultiplied with the
 * extra alpha value from the AlphaComposite) with the alpha value from
 * the mask texture tile.  In picture form, this process looks like:
 *
 *                        A     R    G     B
 *     primary color      Pa    Pr   Pg    Pb    (modulated with...)
 *     texture unit 0     Ca    Ca   Ca    Ca
 *     ---------------------------------------
 *     resulting color    Ra    Rr   Rg    Rb
 *
 * where:
 *     Px = current color (already premultiplied by extra alpha)
 *     Cx = coverage value from mask tile
 *     Rx = resulting color/alpha component
 *
 * When the source paint is not a Color, it means that we are rendering with
 * a complex paint (e.g. GradientPaint, TexturePaint).  In this case, we
 * rely on the GL_ARB_multitexture extension to effectively multiply the
 * paint fragments (autogenerated on texture unit 1, see the
 * OGLPaints_Set{Gradient,Texture,etc}Paint() methods for more details)
 * with the coverage values from the mask texture tile (provided on texture
 * unit 0), all of which is multiplied with the current color value (which
 * contains the extra alpha value).  In picture form:
 *
 *                        A     R    G     B
 *     primary color      Ea    Ea   Ea    Ea    (modulated with...)
 *     texture unit 0     Ca    Ca   Ca    Ca    (modulated with...)
 *     texture unit 1     Pa    Pr   Pg    Pb
 *     ---------------------------------------
 *     resulting color    Ra    Rr   Rg    Rb
 *
 * where:
 *     Ea = extra alpha
 *     Cx = coverage value from mask tile
 *     Px = gradient/texture paint color (generated for each fragment)
 *     Rx = resulting color/alpha component
 *
 * Here are some descriptions of the many variables used in this method:
 *   x,y     - upper left corner of the tile destination
 *   w,h     - width/height of the mask tile
 *   x0      - placekeeper for the original destination x location
 *   tw,th   - width/height of the actual texture tile in pixels
 *   sx1,sy1 - upper left corner of the mask tile source region
 *   sx2,sy2 - lower left corner of the mask tile source region
 *   sx,sy   - "current" upper left corner of the mask tile region of interest
 */
void
OGLMaskFill_MaskFill(OGLContext *oglc,
                     jint x, jint y, jint w, jint h,
                     jint maskoff, jint maskscan, jint masklen,
                     unsigned char *pMask)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLMaskFill_MaskFill");

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_MASK_OP);

    J2dTraceLn4(J2D_TRACE_VERBOSE, "  x=%d y=%d w=%d h=%d", x, y, w, h);
    J2dTraceLn2(J2D_TRACE_VERBOSE, "  maskoff=%d maskscan=%d",
                maskoff, maskscan);

    {
        jint tw, th, x0;
        jint sx1, sy1, sx2, sy2;
        jint sx, sy, sw, sh;

        x0 = x;
        tw = OGLVC_MASK_CACHE_TILE_WIDTH;
        th = OGLVC_MASK_CACHE_TILE_HEIGHT;
        sx1 = maskoff % maskscan;
        sy1 = maskoff / maskscan;
        sx2 = sx1 + w;
        sy2 = sy1 + h;

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

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

                OGLVertexCache_AddMaskQuad(oglc,
                                           sx, sy, x, y, sw, sh,
                                           maskscan, pMask);
            }
        }
    }
}
コード例 #7
0
/**
 * Resets all OpenGL compositing state (disables blending and logic
 * operations).
 */
void
OGLContext_ResetComposite(OGLContext *oglc)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_ResetComposite");

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    // disable blending and XOR mode
    if (oglc->compState == sun_java2d_SunGraphics2D_COMP_ALPHA) {
        j2d_glDisable(GL_BLEND);
    } else if (oglc->compState == sun_java2d_SunGraphics2D_COMP_XOR) {
        j2d_glDisable(GL_COLOR_LOGIC_OP);
        j2d_glDisable(GL_ALPHA_TEST);
    }

    // set state to default values
    oglc->compState = sun_java2d_SunGraphics2D_COMP_ISCOPY;
    oglc->extraAlpha = 1.0f;
}
コード例 #8
0
void
OGLRenderer_DrawScanlines(OGLContext *oglc,
                          jint scanlineCount, jint *scanlines)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawScanlines");

    RETURN_IF_NULL(oglc);
    RETURN_IF_NULL(scanlines);

    CHECK_PREVIOUS_OP(GL_LINES);
    while (scanlineCount > 0) {
        // Translate each vertex by a fraction so
        // that we hit pixel centers.
        GLfloat x1 = ((GLfloat)*(scanlines++)) + 0.2f;
        GLfloat x2 = ((GLfloat)*(scanlines++)) + 1.2f;
        GLfloat y  = ((GLfloat)*(scanlines++)) + 0.5f;
        j2d_glVertex2f(x1, y);
        j2d_glVertex2f(x2, y);
        scanlineCount--;
    }
}
コード例 #9
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;
}
コード例 #10
0
ファイル: OGLTextRenderer.c プロジェクト: ChenYao/jdk7u-jdk
static jboolean
OGLTR_DrawGrayscaleGlyphViaCache(OGLContext *oglc,
                                 GlyphInfo *ginfo, jint x, jint y)
{
    CacheCellInfo *cell;
    jfloat x1, y1, x2, y2;

    if (glyphMode != MODE_USE_CACHE_GRAY) {
        OGLTR_DisableGlyphModeState();
        CHECK_PREVIOUS_OP(OGL_STATE_GLYPH_OP);
        glyphMode = MODE_USE_CACHE_GRAY;
    }

    if (ginfo->cellInfo == NULL) {
        // attempt to add glyph to accelerated glyph cache
        OGLTR_AddToGlyphCache(ginfo, JNI_FALSE);

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

    x1 = (jfloat)x;
    y1 = (jfloat)y;
    x2 = x1 + ginfo->width;
    y2 = y1 + ginfo->height;

    OGLVertexCache_AddGlyphQuad(oglc,
                                cell->tx1, cell->ty1,
                                cell->tx2, cell->ty2,
                                x1, y1, x2, y2);

    return JNI_TRUE;
}
コード例 #11
0
/**
 * Initializes the OpenGL transform state by setting the modelview transform
 * using the given matrix parameters.
 *
 * REMIND: it may be worthwhile to add serial id to AffineTransform, so we
 *         could do a quick check to see if the xform has changed since
 *         last time... a simple object compare won't suffice...
 */
void
OGLContext_SetTransform(OGLContext *oglc,
                        jdouble m00, jdouble m10,
                        jdouble m01, jdouble m11,
                        jdouble m02, jdouble m12)
{
    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_SetTransform");

    RETURN_IF_NULL(oglc);
    CHECK_PREVIOUS_OP(OGL_STATE_CHANGE);

    if (oglc->xformMatrix == NULL) {
        size_t arrsize = 16 * sizeof(GLdouble);
        oglc->xformMatrix = (GLdouble *)malloc(arrsize);
        memset(oglc->xformMatrix, 0, arrsize);
        oglc->xformMatrix[10] = 1.0;
        oglc->xformMatrix[15] = 1.0;
    }

    // copy values from AffineTransform object into native matrix array
    oglc->xformMatrix[0] = m00;
    oglc->xformMatrix[1] = m10;
    oglc->xformMatrix[4] = m01;
    oglc->xformMatrix[5] = m11;
    oglc->xformMatrix[12] = m02;
    oglc->xformMatrix[13] = m12;

    J2dTraceLn3(J2D_TRACE_VERBOSE, "  [%lf %lf %lf]",
                oglc->xformMatrix[0], oglc->xformMatrix[4],
                oglc->xformMatrix[12]);
    J2dTraceLn3(J2D_TRACE_VERBOSE, "  [%lf %lf %lf]",
                oglc->xformMatrix[1], oglc->xformMatrix[5],
                oglc->xformMatrix[13]);

    j2d_glMatrixMode(GL_MODELVIEW);
    j2d_glLoadMatrixd(oglc->xformMatrix);
}
コード例 #12
0
ファイル: OGLTextRenderer.c プロジェクト: ChenYao/jdk7u-jdk
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;
}
コード例 #13
0
ファイル: OGLTextRenderer.c プロジェクト: ChenYao/jdk7u-jdk
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;
}
コード例 #14
0
JNIEXPORT void JNICALL
Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer
    (JNIEnv *env, jobject oglrq,
     jlong buf, jint limit)
{
    jboolean sync = JNI_FALSE;
    unsigned char *b, *end;

    J2dTraceLn1(J2D_TRACE_INFO,
                "OGLRenderQueue_flushBuffer: limit=%d", limit);

    b = (unsigned char *)jlong_to_ptr(buf);
    if (b == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "OGLRenderQueue_flushBuffer: cannot get direct buffer address");
        return;
    }

    INIT_PREVIOUS_OP();
    end = b + limit;

    while (b < end) {
        jint opcode = NEXT_INT(b);

        J2dTraceLn2(J2D_TRACE_VERBOSE,
                    "OGLRenderQueue_flushBuffer: opcode=%d, rem=%d",
                    opcode, (end-b));

        switch (opcode) {

        // draw ops
        case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
            {
                jint x1 = NEXT_INT(b);
                jint y1 = NEXT_INT(b);
                jint x2 = NEXT_INT(b);
                jint y2 = NEXT_INT(b);
                OGLRenderer_DrawLine(oglc, x1, y1, x2, y2);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT:
            {
                jint x = NEXT_INT(b);
                jint y = NEXT_INT(b);
                jint w = NEXT_INT(b);
                jint h = NEXT_INT(b);
                OGLRenderer_DrawRect(oglc, x, y, w, h);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY:
            {
                jint nPoints      = NEXT_INT(b);
                jboolean isClosed = NEXT_BOOLEAN(b);
                jint transX       = NEXT_INT(b);
                jint transY       = NEXT_INT(b);
                jint *xPoints = (jint *)b;
                jint *yPoints = ((jint *)b) + nPoints;
                OGLRenderer_DrawPoly(oglc, nPoints, isClosed,
                                     transX, transY,
                                     xPoints, yPoints);
                SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL:
            {
                jint x = NEXT_INT(b);
                jint y = NEXT_INT(b);
                // Note that we could use GL_POINTS here, but the common
                // use case for DRAW_PIXEL is when rendering a Path2D,
                // which will consist of a mix of DRAW_PIXEL and DRAW_LINE
                // calls.  So to improve batching we use GL_LINES here,
                // even though it requires an extra vertex per pixel.
                CONTINUE_IF_NULL(oglc);
                CHECK_PREVIOUS_OP(GL_LINES);
                j2d_glVertex2i(x, y);
                j2d_glVertex2i(x+1, y+1);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES:
            {
                jint count = NEXT_INT(b);
                OGLRenderer_DrawScanlines(oglc, count, (jint *)b);
                SKIP_BYTES(b, count * BYTES_PER_SCANLINE);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
            {
                jfloat x11 = NEXT_FLOAT(b);
                jfloat y11 = NEXT_FLOAT(b);
                jfloat dx21 = NEXT_FLOAT(b);
                jfloat dy21 = NEXT_FLOAT(b);
                jfloat dx12 = NEXT_FLOAT(b);
                jfloat dy12 = NEXT_FLOAT(b);
                jfloat lwr21 = NEXT_FLOAT(b);
                jfloat lwr12 = NEXT_FLOAT(b);
                OGLRenderer_DrawParallelogram(oglc,
                                              x11, y11,
                                              dx21, dy21,
                                              dx12, dy12,
                                              lwr21, lwr12);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM:
            {
                jfloat x11 = NEXT_FLOAT(b);
                jfloat y11 = NEXT_FLOAT(b);
                jfloat dx21 = NEXT_FLOAT(b);
                jfloat dy21 = NEXT_FLOAT(b);
                jfloat dx12 = NEXT_FLOAT(b);
                jfloat dy12 = NEXT_FLOAT(b);
                jfloat lwr21 = NEXT_FLOAT(b);
                jfloat lwr12 = NEXT_FLOAT(b);
                OGLRenderer_DrawAAParallelogram(oglc, dstOps,
                                                x11, y11,
                                                dx21, dy21,
                                                dx12, dy12,
                                                lwr21, lwr12);
            }
            break;

        // fill ops
        case sun_java2d_pipe_BufferedOpCodes_FILL_RECT:
            {
                jint x = NEXT_INT(b);
                jint y = NEXT_INT(b);
                jint w = NEXT_INT(b);
                jint h = NEXT_INT(b);
                OGLRenderer_FillRect(oglc, x, y, w, h);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS:
            {
                jint count = NEXT_INT(b);
                OGLRenderer_FillSpans(oglc, count, (jint *)b);
                SKIP_BYTES(b, count * BYTES_PER_SPAN);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
            {
                jfloat x11 = NEXT_FLOAT(b);
                jfloat y11 = NEXT_FLOAT(b);
                jfloat dx21 = NEXT_FLOAT(b);
                jfloat dy21 = NEXT_FLOAT(b);
                jfloat dx12 = NEXT_FLOAT(b);
                jfloat dy12 = NEXT_FLOAT(b);
                OGLRenderer_FillParallelogram(oglc,
                                              x11, y11,
                                              dx21, dy21,
                                              dx12, dy12);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM:
            {
                jfloat x11 = NEXT_FLOAT(b);
                jfloat y11 = NEXT_FLOAT(b);
                jfloat dx21 = NEXT_FLOAT(b);
                jfloat dy21 = NEXT_FLOAT(b);
                jfloat dx12 = NEXT_FLOAT(b);
                jfloat dy12 = NEXT_FLOAT(b);
                OGLRenderer_FillAAParallelogram(oglc, dstOps,
                                                x11, y11,
                                                dx21, dy21,
                                                dx12, dy12);
            }
            break;

        // text-related ops
        case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST:
            {
                jint numGlyphs        = NEXT_INT(b);
                jint packedParams     = NEXT_INT(b);
                jfloat glyphListOrigX = NEXT_FLOAT(b);
                jfloat glyphListOrigY = NEXT_FLOAT(b);
                jboolean usePositions = EXTRACT_BOOLEAN(packedParams,
                                                        OFFSET_POSITIONS);
                jboolean subPixPos    = EXTRACT_BOOLEAN(packedParams,
                                                        OFFSET_SUBPIXPOS);
                jboolean rgbOrder     = EXTRACT_BOOLEAN(packedParams,
                                                        OFFSET_RGBORDER);
                jint lcdContrast      = EXTRACT_BYTE(packedParams,
                                                     OFFSET_CONTRAST);
                unsigned char *images = b;
                unsigned char *positions;
                jint bytesPerGlyph;
                if (usePositions) {
                    positions = (b + numGlyphs * BYTES_PER_GLYPH_IMAGE);
                    bytesPerGlyph = BYTES_PER_POSITIONED_GLYPH;
                } else {
                    positions = NULL;
                    bytesPerGlyph = BYTES_PER_GLYPH_IMAGE;
                }
                OGLTR_DrawGlyphList(env, oglc, dstOps,
                                    numGlyphs, usePositions,
                                    subPixPos, rgbOrder, lcdContrast,
                                    glyphListOrigX, glyphListOrigY,
                                    images, positions);
                SKIP_BYTES(b, numGlyphs * bytesPerGlyph);
            }
            break;

        // copy-related ops
        case sun_java2d_pipe_BufferedOpCodes_COPY_AREA:
            {
                jint x  = NEXT_INT(b);
                jint y  = NEXT_INT(b);
                jint w  = NEXT_INT(b);
                jint h  = NEXT_INT(b);
                jint dx = NEXT_INT(b);
                jint dy = NEXT_INT(b);
                OGLBlitLoops_CopyArea(env, oglc, dstOps,
                                      x, y, w, h, dx, dy);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_BLIT:
            {
                jint packedParams = NEXT_INT(b);
                jint sx1          = NEXT_INT(b);
                jint sy1          = NEXT_INT(b);
                jint sx2          = NEXT_INT(b);
                jint sy2          = NEXT_INT(b);
                jdouble dx1       = NEXT_DOUBLE(b);
                jdouble dy1       = NEXT_DOUBLE(b);
                jdouble dx2       = NEXT_DOUBLE(b);
                jdouble dy2       = NEXT_DOUBLE(b);
                jlong pSrc        = NEXT_LONG(b);
                jlong pDst        = NEXT_LONG(b);
                jint hint         = EXTRACT_BYTE(packedParams, OFFSET_HINT);
                jboolean texture  = EXTRACT_BOOLEAN(packedParams,
                                                    OFFSET_TEXTURE);
                jboolean rtt      = EXTRACT_BOOLEAN(packedParams,
                                                    OFFSET_RTT);
                jboolean xform    = EXTRACT_BOOLEAN(packedParams,
                                                    OFFSET_XFORM);
                jboolean isoblit  = EXTRACT_BOOLEAN(packedParams,
                                                    OFFSET_ISOBLIT);
                if (isoblit) {
                    OGLBlitLoops_IsoBlit(env, oglc, pSrc, pDst,
                                         xform, hint, texture, rtt,
                                         sx1, sy1, sx2, sy2,
                                         dx1, dy1, dx2, dy2);
                } else {
                    jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE);
                    OGLBlitLoops_Blit(env, oglc, pSrc, pDst,
                                      xform, hint, srctype, texture,
                                      sx1, sy1, sx2, sy2,
                                      dx1, dy1, dx2, dy2);
                }
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SURFACE_TO_SW_BLIT:
            {
                jint sx      = NEXT_INT(b);
                jint sy      = NEXT_INT(b);
                jint dx      = NEXT_INT(b);
                jint dy      = NEXT_INT(b);
                jint w       = NEXT_INT(b);
                jint h       = NEXT_INT(b);
                jint dsttype = NEXT_INT(b);
                jlong pSrc   = NEXT_LONG(b);
                jlong pDst   = NEXT_LONG(b);
                OGLBlitLoops_SurfaceToSwBlit(env, oglc,
                                             pSrc, pDst, dsttype,
                                             sx, sy, dx, dy, w, h);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_MASK_FILL:
            {
                jint x        = NEXT_INT(b);
                jint y        = NEXT_INT(b);
                jint w        = NEXT_INT(b);
                jint h        = NEXT_INT(b);
                jint maskoff  = NEXT_INT(b);
                jint maskscan = NEXT_INT(b);
                jint masklen  = NEXT_INT(b);
                unsigned char *pMask = (masklen > 0) ? b : NULL;
                OGLMaskFill_MaskFill(oglc, x, y, w, h,
                                     maskoff, maskscan, masklen, pMask);
                SKIP_BYTES(b, masklen);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_MASK_BLIT:
            {
                jint dstx     = NEXT_INT(b);
                jint dsty     = NEXT_INT(b);
                jint width    = NEXT_INT(b);
                jint height   = NEXT_INT(b);
                jint masklen  = width * height * sizeof(jint);
                OGLMaskBlit_MaskBlit(env, oglc,
                                     dstx, dsty, width, height, b);
                SKIP_BYTES(b, masklen);
            }
            break;

        // state-related ops
        case sun_java2d_pipe_BufferedOpCodes_SET_RECT_CLIP:
            {
                jint x1 = NEXT_INT(b);
                jint y1 = NEXT_INT(b);
                jint x2 = NEXT_INT(b);
                jint y2 = NEXT_INT(b);
                OGLContext_SetRectClip(oglc, dstOps, x1, y1, x2, y2);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP:
            {
                OGLContext_BeginShapeClip(oglc);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS:
            {
                jint count = NEXT_INT(b);
                OGLRenderer_FillSpans(oglc, count, (jint *)b);
                SKIP_BYTES(b, count * BYTES_PER_SPAN);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP:
            {
                OGLContext_EndShapeClip(oglc, dstOps);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP:
            {
                OGLContext_ResetClip(oglc);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
            {
                jint rule         = NEXT_INT(b);
                jfloat extraAlpha = NEXT_FLOAT(b);
                jint flags        = NEXT_INT(b);
                OGLContext_SetAlphaComposite(oglc, rule, extraAlpha, flags);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
            {
                jint xorPixel = NEXT_INT(b);
                OGLContext_SetXorComposite(oglc, xorPixel);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
            {
                OGLContext_ResetComposite(oglc);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
            {
                jdouble m00 = NEXT_DOUBLE(b);
                jdouble m10 = NEXT_DOUBLE(b);
                jdouble m01 = NEXT_DOUBLE(b);
                jdouble m11 = NEXT_DOUBLE(b);
                jdouble m02 = NEXT_DOUBLE(b);
                jdouble m12 = NEXT_DOUBLE(b);
                OGLContext_SetTransform(oglc, m00, m10, m01, m11, m02, m12);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM:
            {
                OGLContext_ResetTransform(oglc);
            }
            break;

        // context-related ops
        case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
            {
                jlong pSrc = NEXT_LONG(b);
                jlong pDst = NEXT_LONG(b);
                if (oglc != NULL) {
                    RESET_PREVIOUS_OP();
                }
                oglc = OGLContext_SetSurfaces(env, pSrc, pDst);
                dstOps = (OGLSDOps *)jlong_to_ptr(pDst);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE:
            {
                jlong pConfigInfo = NEXT_LONG(b);
                if (oglc != NULL) {
                    RESET_PREVIOUS_OP();
                }
                oglc = OGLSD_SetScratchSurface(env, pConfigInfo);
                dstOps = NULL;
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE:
            {
                jlong pData = NEXT_LONG(b);
                OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
                if (oglsdo != NULL) {
                    CONTINUE_IF_NULL(oglc);
                    RESET_PREVIOUS_OP();
                    OGLSD_Delete(env, oglsdo);
                }
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
            {
                jlong pData = NEXT_LONG(b);
                OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData);
                if (oglsdo != NULL) {
                    CONTINUE_IF_NULL(oglc);
                    RESET_PREVIOUS_OP();
                    OGLSD_Delete(env, oglsdo);
                    if (oglsdo->privOps != NULL) {
                        free(oglsdo->privOps);
                    }
                }
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
            {
                jlong pConfigInfo = NEXT_LONG(b);
                CONTINUE_IF_NULL(oglc);
                RESET_PREVIOUS_OP();
                OGLGC_DestroyOGLGraphicsConfig(pConfigInfo);

                // the previous method will call glX/wglMakeCurrent(None),
                // so we should nullify the current oglc and dstOps to avoid
                // calling glFlush() (or similar) while no context is current
                oglc = NULL;
                dstOps = NULL;
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT:
            {
                // flush just in case there are any pending operations in
                // the hardware pipe
                if (oglc != NULL) {
                    RESET_PREVIOUS_OP();
                    j2d_glFlush();
                }

                // invalidate the references to the current context and
                // destination surface that are maintained at the native level
                oglc = NULL;
                dstOps = NULL;
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE:
            {
                j2d_glPushAttrib(GL_ALL_ATTRIB_BITS);
                j2d_glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
                j2d_glMatrixMode(GL_MODELVIEW);
                j2d_glPushMatrix();
                j2d_glMatrixMode(GL_PROJECTION);
                j2d_glPushMatrix();
                j2d_glMatrixMode(GL_TEXTURE);
                j2d_glPushMatrix();
            }
            break;

        case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE:
            {
                j2d_glPopAttrib();
                j2d_glPopClientAttrib();
                j2d_glMatrixMode(GL_MODELVIEW);
                j2d_glPopMatrix();
                j2d_glMatrixMode(GL_PROJECTION);
                j2d_glPopMatrix();
                j2d_glMatrixMode(GL_TEXTURE);
                j2d_glPopMatrix();
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SYNC:
            {
                sync = JNI_TRUE;
            }
            break;

        // multibuffering ops
        case sun_java2d_pipe_BufferedOpCodes_SWAP_BUFFERS:
            {
                jlong window = NEXT_LONG(b);
                if (oglc != NULL) {
                    RESET_PREVIOUS_OP();
                }
                OGLSD_SwapBuffers(env, window);
            }
            break;

        // special no-op (mainly used for achieving 8-byte alignment)
        case sun_java2d_pipe_BufferedOpCodes_NOOP:
            break;

        // paint-related ops
        case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT:
            {
                OGLPaints_ResetPaint(oglc);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
            {
                jint pixel = NEXT_INT(b);
                OGLPaints_SetColor(oglc, pixel);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
            {
                jboolean useMask= NEXT_BOOLEAN(b);
                jboolean cyclic = NEXT_BOOLEAN(b);
                jdouble p0      = NEXT_DOUBLE(b);
                jdouble p1      = NEXT_DOUBLE(b);
                jdouble p3      = NEXT_DOUBLE(b);
                jint pixel1     = NEXT_INT(b);
                jint pixel2     = NEXT_INT(b);
                OGLPaints_SetGradientPaint(oglc, useMask, cyclic,
                                           p0, p1, p3,
                                           pixel1, pixel2);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:
            {
                jboolean useMask = NEXT_BOOLEAN(b);
                jboolean linear  = NEXT_BOOLEAN(b);
                jint cycleMethod = NEXT_INT(b);
                jint numStops    = NEXT_INT(b);
                jfloat p0        = NEXT_FLOAT(b);
                jfloat p1        = NEXT_FLOAT(b);
                jfloat p3        = NEXT_FLOAT(b);
                void *fractions, *pixels;
                fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
                pixels    = b; SKIP_BYTES(b, numStops * sizeof(jint));
                OGLPaints_SetLinearGradientPaint(oglc, dstOps,
                                                 useMask, linear,
                                                 cycleMethod, numStops,
                                                 p0, p1, p3,
                                                 fractions, pixels);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT:
            {
                jboolean useMask = NEXT_BOOLEAN(b);
                jboolean linear  = NEXT_BOOLEAN(b);
                jint numStops    = NEXT_INT(b);
                jint cycleMethod = NEXT_INT(b);
                jfloat m00       = NEXT_FLOAT(b);
                jfloat m01       = NEXT_FLOAT(b);
                jfloat m02       = NEXT_FLOAT(b);
                jfloat m10       = NEXT_FLOAT(b);
                jfloat m11       = NEXT_FLOAT(b);
                jfloat m12       = NEXT_FLOAT(b);
                jfloat focusX    = NEXT_FLOAT(b);
                void *fractions, *pixels;
                fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
                pixels    = b; SKIP_BYTES(b, numStops * sizeof(jint));
                OGLPaints_SetRadialGradientPaint(oglc, dstOps,
                                                 useMask, linear,
                                                 cycleMethod, numStops,
                                                 m00, m01, m02,
                                                 m10, m11, m12,
                                                 focusX,
                                                 fractions, pixels);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT:
            {
                jboolean useMask= NEXT_BOOLEAN(b);
                jboolean filter = NEXT_BOOLEAN(b);
                jlong pSrc      = NEXT_LONG(b);
                jdouble xp0     = NEXT_DOUBLE(b);
                jdouble xp1     = NEXT_DOUBLE(b);
                jdouble xp3     = NEXT_DOUBLE(b);
                jdouble yp0     = NEXT_DOUBLE(b);
                jdouble yp1     = NEXT_DOUBLE(b);
                jdouble yp3     = NEXT_DOUBLE(b);
                OGLPaints_SetTexturePaint(oglc, useMask, pSrc, filter,
                                          xp0, xp1, xp3,
                                          yp0, yp1, yp3);
            }
            break;

        // BufferedImageOp-related ops
        case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP:
            {
                jlong pSrc        = NEXT_LONG(b);
                jboolean edgeZero = NEXT_BOOLEAN(b);
                jint kernelWidth  = NEXT_INT(b);
                jint kernelHeight = NEXT_INT(b);
                OGLBufImgOps_EnableConvolveOp(oglc, pSrc, edgeZero,
                                              kernelWidth, kernelHeight, b);
                SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat));
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP:
            {
                OGLBufImgOps_DisableConvolveOp(oglc);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP:
            {
                jlong pSrc          = NEXT_LONG(b);
                jboolean nonPremult = NEXT_BOOLEAN(b);
                jint numFactors     = 4;
                unsigned char *scaleFactors = b;
                unsigned char *offsets = (b + numFactors * sizeof(jfloat));
                OGLBufImgOps_EnableRescaleOp(oglc, pSrc, nonPremult,
                                             scaleFactors, offsets);
                SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP:
            {
                OGLBufImgOps_DisableRescaleOp(oglc);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP:
            {
                jlong pSrc          = NEXT_LONG(b);
                jboolean nonPremult = NEXT_BOOLEAN(b);
                jboolean shortData  = NEXT_BOOLEAN(b);
                jint numBands       = NEXT_INT(b);
                jint bandLength     = NEXT_INT(b);
                jint offset         = NEXT_INT(b);
                jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte);
                void *tableValues = b;
                OGLBufImgOps_EnableLookupOp(oglc, pSrc, nonPremult, shortData,
                                            numBands, bandLength, offset,
                                            tableValues);
                SKIP_BYTES(b, numBands * bandLength * bytesPerElem);
            }
            break;
        case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP:
            {
                OGLBufImgOps_DisableLookupOp(oglc);
            }
            break;

        default:
            J2dRlsTraceLn1(J2D_TRACE_ERROR,
                "OGLRenderQueue_flushBuffer: invalid opcode=%d", opcode);
            if (oglc != NULL) {
                RESET_PREVIOUS_OP();
            }
            return;
        }
    }

    if (oglc != NULL) {
        RESET_PREVIOUS_OP();
        if (sync) {
            j2d_glFinish();
        } else {
            j2d_glFlush();
        }
        OGLSD_Flush(env);
    }
}
コード例 #15
0
void
OGLRenderer_DrawPoly(OGLContext *oglc,
                     jint nPoints, jint isClosed,
                     jint transX, jint transY,
                     jint *xPoints, jint *yPoints)
{
    jboolean isEmpty = JNI_TRUE;
    jint mx, my;
    jint i;

    J2dTraceLn(J2D_TRACE_INFO, "OGLRenderer_DrawPoly");

    if (xPoints == NULL || yPoints == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "OGLRenderer_DrawPoly: points array is null");
        return;
    }

    RETURN_IF_NULL(oglc);

    // Note that BufferedRenderPipe.drawPoly() has already rejected polys
    // with nPoints<2, so we can be certain here that we have nPoints>=2.

    mx = xPoints[0];
    my = yPoints[0];

    CHECK_PREVIOUS_OP(GL_LINE_STRIP);
    for (i = 0; i < nPoints; i++) {
        jint x = xPoints[i];
        jint y = yPoints[i];

        isEmpty = isEmpty && (x == mx && y == my);

        // Translate each vertex by a fraction so that we hit pixel centers.
        j2d_glVertex2f((GLfloat)(x + transX) + 0.5f,
                       (GLfloat)(y + transY) + 0.5f);
    }

    if (isClosed && !isEmpty &&
        (xPoints[nPoints-1] != mx ||
         yPoints[nPoints-1] != my))
    {
        // In this case, the polyline's start and end positions are
        // different and need to be closed manually; we do this by adding
        // one more segment back to the starting position.  Note that we
        // do not need to fill in the last pixel (as we do in the following
        // block) because we are returning to the starting pixel, which
        // has already been filled in.
        j2d_glVertex2f((GLfloat)(mx + transX) + 0.5f,
                       (GLfloat)(my + transY) + 0.5f);
        RESET_PREVIOUS_OP(); // so that we don't leave the line strip open
    } else if (!isClosed || isEmpty) {
        // OpenGL omits the last pixel in a polyline, so we fix this by
        // adding a one-pixel segment at the end.  Also, if the polyline
        // never went anywhere (isEmpty is true), we need to use this
        // workaround to ensure that a single pixel is touched.
        CHECK_PREVIOUS_OP(GL_LINES); // this closes the line strip first
        mx = xPoints[nPoints-1] + transX;
        my = yPoints[nPoints-1] + transY;
        j2d_glVertex2i(mx, my);
        j2d_glVertex2i(mx+1, my+1);
        // no need for RESET_PREVIOUS_OP, as the line strip is no longer open
    } else {
        RESET_PREVIOUS_OP(); // so that we don't leave the line strip open
    }
}