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