Beispiel #1
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;
}
Beispiel #2
0
/**
 * Returns JNI_TRUE only if all of the following conditions are met:
 *   - the GL_ARB_fragment_shader extension is available
 *   - the LCD text shader codepath has been enabled via the system property
 *   - the hardware supports the minimum number of texture units
 */
static jboolean
OGLContext_IsLCDShaderSupportAvailable(JNIEnv *env,
                                       jboolean fragShaderAvailable)
{
    jboolean isLCDShaderEnabled = JNI_FALSE;
    GLint maxTexUnits;

    J2dTraceLn(J2D_TRACE_INFO, "OGLContext_IsLCDShaderSupportAvailable");

    // first see if the fragment shader extension is available
    if (!fragShaderAvailable) {
        return JNI_FALSE;
    }

    // next see if the lcdshader system property has been enabled
    isLCDShaderEnabled =
        JNU_GetStaticFieldByName(env, NULL,
                                 "sun/java2d/opengl/OGLSurfaceData",
                                 "isLCDShaderEnabled", "Z").z;
    if (!isLCDShaderEnabled) {
        J2dRlsTraceLn(J2D_TRACE_INFO,
                      "OGLContext_IsLCDShaderSupportAvailable: disabled via flag");
        return JNI_FALSE;
    }

    // finally, check to see if the hardware supports the required number
    // of texture units
    j2d_glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &maxTexUnits);
    if (maxTexUnits < 2) {
        J2dRlsTraceLn1(J2D_TRACE_INFO,
                       "OGLContext_IsLCDShaderSupportAvailable: not enough tex units (%d)",
                       maxTexUnits);
    }

    J2dRlsTraceLn(J2D_TRACE_INFO,
                  "OGLContext_IsLCDShaderSupportAvailable: LCD text shader supported");

    return JNI_TRUE;
}
/**
 * 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;
}