/** * Disables any pending state associated with the current "glyph mode". */ static void OGLTR_DisableGlyphModeState() { switch (glyphMode) { case MODE_NO_CACHE_LCD: j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); /* FALLTHROUGH */ case MODE_USE_CACHE_LCD: j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4); j2d_glUseProgramObjectARB(0); j2d_glActiveTextureARB(GL_TEXTURE3_ARB); j2d_glDisable(GL_TEXTURE_3D); j2d_glActiveTextureARB(GL_TEXTURE2_ARB); j2d_glDisable(GL_TEXTURE_3D); j2d_glActiveTextureARB(GL_TEXTURE1_ARB); j2d_glDisable(GL_TEXTURE_2D); j2d_glActiveTextureARB(GL_TEXTURE0_ARB); break; case MODE_NO_CACHE_GRAY: case MODE_USE_CACHE_GRAY: case MODE_NOT_INITED: default: break; } }
/** * 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); }
/** * Initializes the OpenGL logic op state to XOR mode. Blending is disabled * before enabling logic op mode. The XOR pixel value will be applied * later in the OGLContext_SetColor() method. */ void OGLContext_SetXorComposite(OGLContext *oglc, jint xorPixel) { J2dTraceLn1(J2D_TRACE_INFO, "OGLContext_SetXorComposite: xorPixel=%08x", xorPixel); RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_CHANGE); // disable blending mode if (oglc->compState == sun_java2d_SunGraphics2D_COMP_ALPHA) { j2d_glDisable(GL_BLEND); } // enable XOR mode j2d_glEnable(GL_COLOR_LOGIC_OP); j2d_glLogicOp(GL_XOR); // set up the alpha test so that we discard transparent fragments (this // is primarily useful for rendering text in XOR mode) j2d_glEnable(GL_ALPHA_TEST); j2d_glAlphaFunc(GL_NOTEQUAL, 0.0f); // update state oglc->compState = sun_java2d_SunGraphics2D_COMP_XOR; oglc->xorPixel = xorPixel; oglc->extraAlpha = 1.0f; }
/** * Sets up a complex (shape) clip using the OpenGL depth buffer. This * method prepares the depth buffer so that the clip Region spans can * be "rendered" into it. The depth buffer is first cleared, then the * depth func is setup so that when we render the clip spans, * nothing is rendered into the color buffer, but for each pixel that would * be rendered, a non-zero value is placed into that location in the depth * buffer. With depth test enabled, pixels will only be rendered into the * color buffer if the corresponding value at that (x,y) location in the * depth buffer differs from the incoming depth value. */ void OGLContext_BeginShapeClip(OGLContext *oglc) { J2dTraceLn(J2D_TRACE_INFO, "OGLContext_BeginShapeClip"); RETURN_IF_NULL(oglc); RESET_PREVIOUS_OP(); j2d_glDisable(GL_SCISSOR_TEST); // enable depth test and clear depth buffer so that depth values are at // their maximum; also set the depth func to GL_ALWAYS so that the // depth values of the clip spans are forced into the depth buffer j2d_glEnable(GL_DEPTH_TEST); j2d_glClearDepth(1.0); j2d_glClear(GL_DEPTH_BUFFER_BIT); j2d_glDepthFunc(GL_ALWAYS); // disable writes into the color buffer while we set up the clip j2d_glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // save current transform j2d_glMatrixMode(GL_MODELVIEW); j2d_glPushMatrix(); // use identity transform plus slight translation in the z-axis when // setting the clip spans; this will push the clip spans (which would // normally be at z=0) to the z=1 plane to give them some depth j2d_glLoadIdentity(); j2d_glTranslatef(0.0f, 0.0f, 1.0f); }
/** * Sets the OpenGL scissor bounds to the provided rectangular clip bounds. */ void OGLContext_SetRectClip(OGLContext *oglc, OGLSDOps *dstOps, jint x1, jint y1, jint x2, jint y2) { jint width = x2 - x1; jint height = y2 - y1; J2dTraceLn4(J2D_TRACE_INFO, "OGLContext_SetRectClip: x=%d y=%d w=%d h=%d", x1, y1, width, height); RETURN_IF_NULL(dstOps); RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_CHANGE); if ((width < 0) || (height < 0)) { // use an empty scissor rectangle when the region is empty width = 0; height = 0; } j2d_glDisable(GL_DEPTH_TEST); j2d_glEnable(GL_SCISSOR_TEST); // the scissor rectangle is specified using the lower-left // origin of the clip region (in the framebuffer's coordinate // space), so we must account for the x/y offsets of the // destination surface j2d_glScissor(dstOps->xOffset + x1, dstOps->yOffset + dstOps->height - (y1 + height), width, height); }
/** * Initializes the alpha channel of the current surface so that it contains * fully opaque alpha values. */ static void OGLContext_InitAlphaChannel() { GLboolean scissorEnabled; J2dTraceLn(J2D_TRACE_INFO, "OGLContext_InitAlphaChannel"); // it is possible for the scissor test to be enabled at this point; // if it is, disable it temporarily since it can affect the glClear() op scissorEnabled = j2d_glIsEnabled(GL_SCISSOR_TEST); if (scissorEnabled) { j2d_glDisable(GL_SCISSOR_TEST); } // set the color mask so that we only affect the alpha channel j2d_glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); // clear the color buffer so that the alpha channel is fully opaque j2d_glClearColor(0.0f, 0.0f, 0.0f, 1.0f); j2d_glClear(GL_COLOR_BUFFER_BIT); // restore the color mask (as it was set in OGLContext_SetViewport()) j2d_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); // re-enable scissor test, only if it was enabled earlier if (scissorEnabled) { j2d_glEnable(GL_SCISSOR_TEST); } }
/** * 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; }
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; }
/** * 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; }
void OGLTR_DisableGlyphVertexCache(OGLContext *oglc) { J2dTraceLn(J2D_TRACE_INFO, "OGLTR_DisableGlyphVertexCache"); OGLVertexCache_FlushVertexCache(); OGLVertexCache_RestoreColorState(oglc); j2d_glDisable(GL_TEXTURE_2D); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4); j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 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; }