430N/A/*
2362N/A * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
430N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
430N/A *
430N/A * This code is free software; you can redistribute it and/or modify it
430N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
430N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
430N/A *
430N/A * This code is distributed in the hope that it will be useful, but WITHOUT
430N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
430N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
430N/A * version 2 for more details (a copy is included in the LICENSE file that
430N/A * accompanied this code).
430N/A *
430N/A * You should have received a copy of the GNU General Public License version
430N/A * 2 along with this work; if not, write to the Free Software Foundation,
430N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
430N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
430N/A */
430N/A
430N/A#include "D3DGlyphCache.h"
430N/A#include "D3DTextRenderer.h"
430N/A#include "D3DRenderQueue.h"
430N/A
430N/Avoid D3DGlyphCache_FlushGlyphVertexCache();
430N/A
430N/A// static
430N/AHRESULT
430N/AD3DGlyphCache::CreateInstance(D3DContext *pCtx, GlyphCacheType gcType,
430N/A D3DGlyphCache **ppGlyphCache)
430N/A{
430N/A HRESULT res;
430N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::CreateInstance");
430N/A
430N/A *ppGlyphCache = new D3DGlyphCache(gcType);
430N/A if (FAILED(res = (*ppGlyphCache)->Init(pCtx))) {
430N/A delete *ppGlyphCache;
430N/A *ppGlyphCache = NULL;
430N/A }
430N/A return res;
430N/A}
430N/A
430N/AD3DGlyphCache::D3DGlyphCache(GlyphCacheType type)
430N/A{
430N/A J2dTraceLn1(J2D_TRACE_INFO, "D3DGlyphCache::D3DGlyphCache gcType=%d", type);
430N/A
430N/A pCtx = NULL;
430N/A gcType = type;
430N/A pGlyphCacheRes = NULL;
430N/A pGlyphCache = NULL;
430N/A tileFormat = (gcType == CACHE_GRAY) ? TILEFMT_1BYTE_ALPHA : TILEFMT_UNKNOWN;
430N/A lastRGBOrder = JNI_FALSE;
430N/A}
430N/A
430N/AD3DGlyphCache::~D3DGlyphCache()
430N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::~D3DGlyphCache");
430N/A
430N/A ReleaseDefPoolResources();
430N/A
430N/A pCtx = NULL;
430N/A if (pGlyphCache != NULL) {
430N/A AccelGlyphCache_Free(pGlyphCache);
430N/A pGlyphCache = NULL;
430N/A }
430N/A}
430N/A
430N/Avoid
430N/AD3DGlyphCache::ReleaseDefPoolResources()
430N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::ReleaseDefPoolResources");
430N/A
430N/A AccelGlyphCache_Invalidate(pGlyphCache);
430N/A // REMIND: the glyph cache texture is not in the default pool, so
430N/A // this can be optimized not to release the texture
430N/A pCtx->GetResourceManager()->ReleaseResource(pGlyphCacheRes);
430N/A pGlyphCacheRes = NULL;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DGlyphCache::Init(D3DContext *pCtx)
430N/A{
430N/A D3DFORMAT format;
430N/A
430N/A RETURN_STATUS_IF_NULL(pCtx, E_FAIL);
430N/A
430N/A J2dTraceLn1(J2D_TRACE_INFO, "D3DGlyphCache::Init pCtx=%x", pCtx);
430N/A
430N/A this->pCtx = pCtx;
430N/A
430N/A if (pGlyphCache == NULL) {
430N/A // init glyph cache data structure
430N/A pGlyphCache = AccelGlyphCache_Init(D3DTR_CACHE_WIDTH,
430N/A D3DTR_CACHE_HEIGHT,
430N/A D3DTR_CACHE_CELL_WIDTH,
430N/A D3DTR_CACHE_CELL_HEIGHT,
430N/A D3DGlyphCache_FlushGlyphVertexCache);
430N/A if (pGlyphCache == NULL) {
430N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "D3DGlyphCache::Init: "\
430N/A "could not init D3D glyph cache");
430N/A return E_FAIL;
430N/A }
430N/A }
430N/A
430N/A if (gcType == CACHE_GRAY) {
430N/A format = pCtx->IsTextureFormatSupported(D3DFMT_A8) ?
430N/A D3DFMT_A8 : D3DFMT_A8R8G8B8;
430N/A } else { // gcType == CACHE_LCD
430N/A format = pCtx->IsTextureFormatSupported(D3DFMT_R8G8B8) ?
430N/A D3DFMT_R8G8B8 : D3DFMT_A8R8G8B8;
430N/A }
430N/A
430N/A HRESULT res = pCtx->GetResourceManager()->
430N/A CreateTexture(D3DTR_CACHE_WIDTH, D3DTR_CACHE_HEIGHT,
430N/A FALSE/*isRTT*/, FALSE/*isOpaque*/, &format, 0/*usage*/,
430N/A &pGlyphCacheRes);
430N/A if (FAILED(res)) {
430N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "D3DGlyphCache::Init: "\
430N/A "could not create glyph cache texture");
430N/A }
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DGlyphCache::AddGlyph(GlyphInfo *glyph)
430N/A{
430N/A HRESULT res = S_OK;
430N/A
430N/A RETURN_STATUS_IF_NULL(pGlyphCacheRes, E_FAIL);
430N/A
430N/A CacheCellInfo *cellInfo = AccelGlyphCache_AddGlyph(pGlyphCache, glyph);
430N/A if (cellInfo != NULL) {
430N/A jint pixelsTouchedL = 0, pixelsTouchedR = 0;
430N/A // store glyph image in texture cell
430N/A res = pCtx->UploadTileToTexture(pGlyphCacheRes,
430N/A glyph->image,
430N/A cellInfo->x, cellInfo->y,
430N/A 0, 0,
430N/A glyph->width, glyph->height,
430N/A glyph->rowBytes, tileFormat,
430N/A &pixelsTouchedL,
430N/A &pixelsTouchedR);
430N/A // LCD text rendering optimization: if the number of pixels touched on
430N/A // the first or last column of the glyph image is less than 1/3 of the
430N/A // height of the glyph we do not consider them touched.
430N/A // See D3DTextRenderer.cpp:UpdateCachedDestination for more information.
430N/A // The leftOff/rightOff are only used in LCD cache case.
430N/A if (gcType == CACHE_LCD) {
430N/A jint threshold = glyph->height/3;
430N/A
430N/A cellInfo->leftOff = pixelsTouchedL < threshold ? 1 : 0;
430N/A cellInfo->rightOff = pixelsTouchedR < threshold ? -1 : 0;
430N/A } else {
430N/A cellInfo->leftOff = 0;
430N/A cellInfo->rightOff = 0;
430N/A }
430N/A }
430N/A
430N/A return res;
430N/A}
430N/A
430N/AHRESULT
430N/AD3DGlyphCache::CheckGlyphCacheByteOrder(jboolean rgbOrder)
430N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::CheckGlyphCacheByteOrder");
430N/A
430N/A if (gcType != CACHE_LCD) {
430N/A J2dTraceLn(J2D_TRACE_ERROR, "D3DGlyphCache::CheckGlyphCacheByteOrder"\
430N/A " invoked on CACHE_GRAY cache type instance!");
430N/A return E_FAIL;
430N/A }
430N/A
430N/A if (rgbOrder != lastRGBOrder) {
430N/A // need to invalidate the cache in this case; see comments
430N/A // for lastRGBOrder
430N/A AccelGlyphCache_Invalidate(pGlyphCache);
430N/A lastRGBOrder = rgbOrder;
430N/A }
430N/A tileFormat = rgbOrder ? TILEFMT_3BYTE_RGB : TILEFMT_3BYTE_BGR;
430N/A
430N/A return S_OK;
430N/A}
430N/A
430N/A/**
430N/A * This method is invoked in the (relatively rare) case where one or
430N/A * more glyphs is about to be kicked out of the glyph cache texture.
430N/A * Here we simply flush the vertex queue of the current context in case
430N/A * any pending vertices are dependent upon the current glyph cache layout.
430N/A */
430N/Astatic void
430N/AD3DGlyphCache_FlushGlyphVertexCache()
430N/A{
430N/A D3DContext *d3dc = D3DRQ_GetCurrentContext();
430N/A if (d3dc != NULL) {
430N/A J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache_FlushGlyphVertexCache");
430N/A d3dc->FlushVertexQueue();
430N/A }
430N/A}