void
OGLPaints_ResetPaint(OGLContext *oglc)
{
    jubyte ea;

    J2dTraceLn(J2D_TRACE_INFO, "OGLPaints_ResetPaint");

    RETURN_IF_NULL(oglc);
    J2dTraceLn1(J2D_TRACE_VERBOSE, "  state=%d", oglc->paintState);
    RESET_PREVIOUS_OP();

    if (oglc->useMask) {
        // switch to texture unit 1, where paint state is currently enabled
        j2d_glActiveTextureARB(GL_TEXTURE1_ARB);
    }

    switch (oglc->paintState) {
    case sun_java2d_SunGraphics2D_PAINT_GRADIENT:
        j2d_glDisable(GL_TEXTURE_1D);
        j2d_glDisable(GL_TEXTURE_GEN_S);
        break;

    case sun_java2d_SunGraphics2D_PAINT_TEXTURE:
        // Note: The texture object used in SetTexturePaint() will
        // still be bound at this point, so it is safe to call the following.
        OGLSD_RESET_TEXTURE_WRAP(GL_TEXTURE_2D);
        j2d_glDisable(GL_TEXTURE_2D);
        j2d_glDisable(GL_TEXTURE_GEN_S);
        j2d_glDisable(GL_TEXTURE_GEN_T);
        break;

    case sun_java2d_SunGraphics2D_PAINT_LIN_GRADIENT:
    case sun_java2d_SunGraphics2D_PAINT_RAD_GRADIENT:
        j2d_glUseProgramObjectARB(0);
        j2d_glDisable(GL_TEXTURE_1D);
        break;

    case sun_java2d_SunGraphics2D_PAINT_ALPHACOLOR:
    default:
        break;
    }

    if (oglc->useMask) {
        // restore control to texture unit 0
        j2d_glActiveTextureARB(GL_TEXTURE0_ARB);
    }

    // set each component of the current color state to the extra alpha
    // value, which will effectively apply the extra alpha to each fragment
    // in paint/texturing operations
    ea = (jubyte)(oglc->extraAlpha * 0xff + 0.5f);
    j2d_glColor4ub(ea, ea, ea, ea);
    oglc->pixel = (ea << 24) | (ea << 16) | (ea << 8) | (ea << 0);
    oglc->r = ea;
    oglc->g = ea;
    oglc->b = ea;
    oglc->a = ea;
    oglc->useMask = JNI_FALSE;
    oglc->paintState = -1;
}
Example #2
0
/**
 * Creates a 2D texture of the given format and dimensions and returns the
 * texture object identifier.  This method is typically used to create a
 * temporary texture for intermediate work, such as in the
 * OGLContext_InitBlitTileTexture() method below.
 */
GLuint
OGLContext_CreateBlitTexture(GLenum internalFormat, GLenum pixelFormat,
                             GLuint width, GLuint height)
{
    GLuint texID;
    GLint sp, sr, rl, align;
    GLclampf priority = 1.0f;

    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_CreateBlitTexture");

    j2d_glGenTextures(1, &texID);
    j2d_glBindTexture(GL_TEXTURE_2D, texID);
    j2d_glPrioritizeTextures(1, &texID, &priority);
    j2d_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    j2d_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    OGLSD_RESET_TEXTURE_WRAP(GL_TEXTURE_2D);

    // save pixel store parameters (since this method could be invoked after
    // the caller has already set up its pixel store parameters)
    j2d_glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &sp);
    j2d_glGetIntegerv(GL_UNPACK_SKIP_ROWS, &sr);
    j2d_glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rl);
    j2d_glGetIntegerv(GL_UNPACK_ALIGNMENT, &align);

    // set pixel store parameters to default values
    j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    j2d_glTexImage2D(GL_TEXTURE_2D, 0, internalFormat,
                     width, height, 0,
                     pixelFormat, GL_UNSIGNED_BYTE, NULL);

    // restore pixel store parameters
    j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sp);
    j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sr);
    j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, rl);
    j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, align);

    return texID;
}
/**
 * Initializes an OpenGL texture object.
 *
 * If the isOpaque parameter is JNI_FALSE, then the texture will have a
 * full alpha channel; otherwise, the texture will be opaque (this can
 * help save VRAM when translucency is not needed).
 *
 * If the GL_ARB_texture_non_power_of_two extension is present (texNonPow2
 * is JNI_TRUE), the actual texture is allowed to have non-power-of-two
 * dimensions, and therefore width==textureWidth and height==textureHeight.
 *
 * Failing that, if the GL_ARB_texture_rectangle extension is present
 * (texRect is JNI_TRUE), the actual texture is allowed to have
 * non-power-of-two dimensions, except that instead of using the usual
 * GL_TEXTURE_2D target, we need to use the GL_TEXTURE_RECTANGLE_ARB target.
 * Note that the GL_REPEAT wrapping mode is not allowed with this target,
 * so if that mode is needed (e.g. as is the case in the TexturePaint code)
 * one should pass JNI_FALSE to avoid using this extension.  Also note that
 * when the texture target is GL_TEXTURE_RECTANGLE_ARB, texture coordinates
 * must be specified in the range [0,width] and [0,height] rather than
 * [0,1] as is the case with the usual GL_TEXTURE_2D target (so take care)!
 *
 * Otherwise, the actual texture must have power-of-two dimensions, and
 * therefore the textureWidth and textureHeight will be the next
 * power-of-two greater than (or equal to) the requested width and height.
 */
static jboolean
OGLSD_InitTextureObject(OGLSDOps *oglsdo,
                        jboolean isOpaque,
                        jboolean texNonPow2, jboolean texRect,
                        jint width, jint height)
{
    GLenum texTarget, texProxyTarget;
    GLint format = isOpaque ? GL_RGB : GL_RGBA;
    GLuint texID;
    GLsizei texWidth, texHeight, realWidth, realHeight;
    GLint texMax;

    J2dTraceLn4(J2D_TRACE_INFO,
                "OGLSD_InitTextureObject: w=%d h=%d opq=%d nonpow2=%d",
                width, height, isOpaque, texNonPow2);

    if (oglsdo == NULL) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
                      "OGLSD_InitTextureObject: ops are null");
        return JNI_FALSE;
    }

    if (texNonPow2) {
        // use non-pow2 dimensions with GL_TEXTURE_2D target
        j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texMax);
        texWidth = (width <= texMax) ? width : 0;
        texHeight = (height <= texMax) ? height : 0;
        texTarget = GL_TEXTURE_2D;
        texProxyTarget = GL_PROXY_TEXTURE_2D;
    } else if (texRect) {
        // use non-pow2 dimensions with GL_TEXTURE_RECTANGLE_ARB target
        j2d_glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &texMax);
        texWidth = (width <= texMax) ? width : 0;
        texHeight = (height <= texMax) ? height : 0;
        texTarget = GL_TEXTURE_RECTANGLE_ARB;
        texProxyTarget = GL_PROXY_TEXTURE_RECTANGLE_ARB;
    } else {
        // find the appropriate power-of-two dimensions
        j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texMax);
        texWidth = OGLSD_NextPowerOfTwo(width, texMax);
        texHeight = OGLSD_NextPowerOfTwo(height, texMax);
        texTarget = GL_TEXTURE_2D;
        texProxyTarget = GL_PROXY_TEXTURE_2D;
    }

    J2dTraceLn3(J2D_TRACE_VERBOSE,
                "  desired texture dimensions: w=%d h=%d max=%d",
                texWidth, texHeight, texMax);

    // if either dimension is 0, we cannot allocate a texture with the
    // requested dimensions
    if ((texWidth == 0) || (texHeight == 0)) {
        J2dRlsTraceLn(J2D_TRACE_ERROR,
            "OGLSD_InitTextureObject: texture dimensions too large");
        return JNI_FALSE;
    }

    // now use a proxy to determine whether we can create a texture with
    // the calculated power-of-two dimensions and the given internal format
    j2d_glTexImage2D(texProxyTarget, 0, format,
                     texWidth, texHeight, 0,
                     format, GL_UNSIGNED_BYTE, NULL);
    j2d_glGetTexLevelParameteriv(texProxyTarget, 0,
                                 GL_TEXTURE_WIDTH, &realWidth);
    j2d_glGetTexLevelParameteriv(texProxyTarget, 0,
                                 GL_TEXTURE_HEIGHT, &realHeight);

    // if the requested dimensions and proxy dimensions don't match,
    // we shouldn't attempt to create the texture
    if ((realWidth != texWidth) || (realHeight != texHeight)) {
        J2dRlsTraceLn2(J2D_TRACE_ERROR,
            "OGLSD_InitTextureObject: actual (w=%d h=%d) != requested",
                       realWidth, realHeight);
        return JNI_FALSE;
    }

    // initialize the texture with some dummy data (this allows us to create
    // a texture object once with 2^n dimensions, and then use
    // glTexSubImage2D() to provide further updates)
    j2d_glGenTextures(1, &texID);
    j2d_glBindTexture(texTarget, texID);
    j2d_glTexImage2D(texTarget, 0, format,
                     texWidth, texHeight, 0,
                     format, GL_UNSIGNED_BYTE, NULL);

    oglsdo->isOpaque = isOpaque;
    oglsdo->xOffset = 0;
    oglsdo->yOffset = 0;
    oglsdo->width = width;
    oglsdo->height = height;
    oglsdo->textureID = texID;
    oglsdo->textureWidth = texWidth;
    oglsdo->textureHeight = texHeight;
    oglsdo->textureTarget = texTarget;
    OGLSD_INIT_TEXTURE_FILTER(oglsdo, GL_NEAREST);
    OGLSD_RESET_TEXTURE_WRAP(texTarget);

    J2dTraceLn3(J2D_TRACE_VERBOSE, "  created texture: w=%d h=%d id=%d",
                width, height, texID);

    return JNI_TRUE;
}