/** * 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; } }
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); }
/** * 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; }
void OGLTR_EnableGlyphVertexCache(OGLContext *oglc) { J2dTraceLn(J2D_TRACE_INFO, "OGLTR_EnableGlyphVertexCache"); if (glyphCache == NULL) { if (!OGLTR_InitGlyphCache(JNI_FALSE)) { return; } } j2d_glEnable(GL_TEXTURE_2D); j2d_glBindTexture(GL_TEXTURE_2D, glyphCache->cacheID); j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // for grayscale/monochrome text, the current OpenGL source color // is modulated with the glyph image as part of the texture // application stage, so we use GL_MODULATE here OGLC_UPDATE_TEXTURE_FUNCTION(oglc, GL_MODULATE); }
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; }
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; }
/* * Class: sun_java2d_opengl_WGLSurfaceData * Method: updateWindowAccelImpl * Signature: (JJII)Z */ JNIEXPORT jboolean JNICALL Java_sun_java2d_opengl_WGLSurfaceData_updateWindowAccelImpl (JNIEnv *env, jclass clazz, jlong pData, jobject peer, jint w, jint h) { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); OGLPixelFormat pf = PixelFormats[0/*PF_INT_ARGB_PRE*/]; HBITMAP hBitmap = NULL; void *pDst; jint srcx, srcy, dstx, dsty, width, height; jint pixelStride = 4; jint scanStride = pixelStride * w; J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_updateWindowAccelImpl"); if (w <= 0 || h <= 0) { return JNI_TRUE; } if (oglsdo == NULL) { return JNI_FALSE; } RESET_PREVIOUS_OP(); width = w; height = h; srcx = srcy = dstx = dsty = 0; pDst = malloc(height * scanStride); if (pDst == NULL) { return JNI_FALSE; } ZeroMemory(pDst, height * scanStride); // the code below is mostly copied from OGLBlitLoops_SurfaceToSwBlit j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, dstx); j2d_glPixelStorei(GL_PACK_ROW_LENGTH, scanStride / pixelStride); j2d_glPixelStorei(GL_PACK_ALIGNMENT, pf.alignment); // this accounts for lower-left origin of the source region srcx = oglsdo->xOffset + srcx; srcy = oglsdo->yOffset + oglsdo->height - (srcy + 1); // we must read one scanline at a time because there is no way // to read starting at the top-left corner of the source region while (height > 0) { j2d_glPixelStorei(GL_PACK_SKIP_ROWS, dsty); j2d_glReadPixels(srcx, srcy, width, 1, pf.format, pf.type, pDst); srcy--; dsty++; height--; } j2d_glPixelStorei(GL_PACK_SKIP_PIXELS, 0); j2d_glPixelStorei(GL_PACK_SKIP_ROWS, 0); j2d_glPixelStorei(GL_PACK_ROW_LENGTH, 0); j2d_glPixelStorei(GL_PACK_ALIGNMENT, 4); // the pixels read from the surface are already premultiplied // REMIND: commented until translucent window support is integrated // hBitmap = BitmapUtil_CreateBitmapFromARGBPre(w, h, scanStride, // (int*)pDst); free(pDst); if (hBitmap == NULL) { return JNI_FALSE; } // REMIND: commented until translucent window support is integrated // AwtWindow_UpdateWindow(env, peer, w, h, hBitmap); // hBitmap is released in UpdateWindow return JNI_TRUE; }