/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <malloc.h>
#include <math.h>
#include <jlong.h>
#include "sun_java2d_d3d_D3DTextRenderer.h"
#include "sun_java2d_pipe_BufferedTextPipe.h"
#include "SurfaceData.h"
#include "D3DContext.h"
#include "D3DSurfaceData.h"
#include "D3DRenderQueue.h"
#include "D3DTextRenderer.h"
#include "D3DGlyphCache.h"
#include "AccelGlyphCache.h"
#include "fontscalerdefs.h"
/**
* The current "glyph mode" state. This variable is used to track the
* codepath used to render a particular glyph. This variable is reset to
* MODE_NOT_INITED at the beginning of every call to D3DTR_DrawGlyphList().
* As each glyph is rendered, the glyphMode variable is updated to reflect
* the current mode, so if the current mode is the same as the mode used
* to render the previous glyph, we can avoid doing costly setup operations
* each time.
*/
typedef enum {
} GlyphMode;
/**
* The current bounds of the "cached destination" texture, in destination
* D3DTR_CACHED_DEST_WIDTH/HEIGHT values defined above. These bounds are
* only considered valid when the isCachedDestValid flag is JNI_TRUE.
*/
/**
* This flag indicates whether the "cached destination" texture contains
* valid data. This flag is reset to JNI_FALSE at the beginning of every
* call to D3DTR_DrawGlyphList(). Once we copy valid destination data
* into the cached texture, this flag is set to JNI_TRUE. This way, we
* can limit the number of times we need to copy destination data, which
* is a very costly operation.
*/
/**
* The bounds of the previously rendered LCD glyph, in destination
* coordinate space. We use these bounds to determine whether the glyph
* currently being rendered overlaps the previously rendered glyph (i.e.
* its bounding box intersects that of the previously rendered glyph).
* If so, we need to re-read the destination area associated with that
* previous glyph so that we can correctly blend with the actual
* destination data.
*/
/**
* Updates the gamma and inverse gamma values for the LCD text shader.
*/
static HRESULT
{
// update the "invgamma" parameter of the shader program
// update the "gamma" parameter of the shader program
return res;
}
/**
* Updates the current gamma-adjusted source color ("src_adj") of the LCD
* text shader program. Note that we could calculate this value in the
* shader (e.g. just as we do for "dst_adj"), but would be unnecessary work
* (and a measurable performance hit, maybe around 5%) since this value is
* constant over the entire glyph list. So instead we just calculate the
* gamma-adjusted value once and update the uniform parameter of the LCD
* shader as needed.
*/
static HRESULT
{
"D3DTR_UpdateLCDTextColor: contrast=%d", contrast);
/*
* Note: Ideally we would update the "srcAdj" uniform parameter only
* when there is a change in the source color. Fortunately, the cost
* of querying the current D3D color state and updating the uniform
* value is quite small, and in the common case we only need to do this
* once per GlyphList, so we gain little from trying to optimize too
* eagerly here.
*/
// get the current D3D primary color state
// gamma adjust the primary color
// update the "srcAdj" parameter of the shader program with this value
}
/**
* Enables the LCD text shader and updates any related state, such as the
* gamma values.
*/
static HRESULT
{
if (useCache) {
// glyph cache had been already initialized
} else {
}
// bind the texture containing glyph data to texture unit 0
// bind the texture tile containing destination data to texture unit 1
// update the current contrast settings (note: these change very rarely,
// but it seems that D3D pixel shader registers aren't maintained as
// part of the pixel shader instance, so we need to update these
// everytime around in case another shader blew away the contents
// of those registers)
// update the current color settings
}
{
// glyph cache had been successfully initialized if we got here
}
{
}
/**
* Disables any pending state associated with the current "glyph mode".
*/
static HRESULT
{
switch (glyphMode) {
case MODE_NO_CACHE_LCD:
case MODE_USE_CACHE_LCD:
d3dc->FlushVertexQueue();
break;
case MODE_NO_CACHE_GRAY:
case MODE_USE_CACHE_GRAY:
case MODE_NOT_INITED:
default:
break;
}
return res;
}
static HRESULT
{
if (glyphMode != MODE_USE_CACHE_GRAY) {
}
// attempt to add glyph to accelerated glyph cache
}
cell->timesRendered++;
}
/**
* inside outerBounds.
*/
/**
* the rectangle defined by bounds.
*/
/**
* This method checks to see if the given LCD glyph bounds fall within the
* cached destination texture bounds. If so, this method can return
* immediately. If not, this method will copy a chunk of framebuffer data
* into the cached destination texture and then update the current cached
* destination bounds before returning.
*
* The agx1, agx2 are "adjusted" glyph bounds, which are only used when checking
* against the previous glyph bounds.
*/
static HRESULT
{
// glyph is already within the cached destination bounds; no need
// to read back the entire destination region again, but we do
// need to see if the current glyph overlaps the previous glyph...
// only use the "adjusted" glyph bounds when checking against
// previous glyph's bounds
// the current glyph overlaps the destination region touched
// by the previous glyph, so now we need to read back the part
// of the destination corresponding to the previous glyph
// REMIND: make sure we flush any pending primitives that are
// dependent on the current contents of the cached dest
d3dc->FlushVertexQueue();
E_FAIL);
// now dxy12 represent the "desired" destination bounds, but the
// StretchRect() call may fail if these fall outside the actual
// surface bounds; therefore, we use cxy12 to represent the
// clamped bounds, and dxy12 are saved for later
// copy destination into subregion of cached texture tile
// cx1-cachedDestBounds.x1 == +xoffset from left of texture
// cy1-cachedDestBounds.y1 == +yoffset from top of texture
// cx2-cachedDestBounds.x1 == +xoffset from left of texture
// cy2-cachedDestBounds.y1 == +yoffset from top of texture
}
}
} else {
// destination region is not valid, so we need to read back a
// chunk of the destination into our cached texture
// position the upper-left corner of the destination region on the
// "top" line of glyph list
// REMIND: this isn't ideal; it would be better if we had some idea
// of the bounding box of the whole glyph list (this is
// do-able, but would require iterating through the whole
// list up front, which may present its own problems)
// estimate the width based on our current position in the glyph
// list and using the x advance of the current glyph (this is just
// a quick and dirty heuristic; if this is a "thin" glyph image,
// then we're likely to underestimate, and if it's "thick" then we
// may end up reading back more than we need to)
if (remainingWidth > D3DTR_CACHED_DEST_WIDTH) {
// in some cases, the x-advance may be slightly smaller
// than the actual width of the glyph; if so, adjust our
// estimate so that we can accomodate the entire glyph
}
} else {
// a negative advance is possible when rendering rotated text,
// in which case it is difficult to estimate an appropriate
// region for readback, so we will pick a region that
// encompasses just the current glyph
}
// estimate the height (this is another sloppy heuristic; we'll
// make the cached destination region tall enough to encompass most
// glyphs that are small enough to fit in the glyph cache, and then
// we add a little something extra to account for descenders
// REMIND: make sure we flush any pending primitives that are
// dependent on the current contents of the cached dest
d3dc->FlushVertexQueue();
// now dxy12 represent the "desired" destination bounds, but the
// StretchRect() call may fail if these fall outside the actual
// surface bounds; therefore, we use cxy12 to represent the
// clamped bounds, and dxy12 are saved for later
// copy destination into cached texture tile (the upper-left
// corner of the destination region will be positioned at the
// upper-left corner (0,0) of the texture)
}
// update the cached bounds and mark it valid
}
// always update the previous glyph bounds
return res;
}
static HRESULT
{
// the glyph cache is initialized before this method is called
if (glyphMode != MODE_USE_CACHE_LCD) {
}
// attempt to add glyph to accelerated glyph cache
// we'll just no-op in the rare case that the cell is NULL
}
cell->timesRendered++;
// location of the glyph in the destination's coordinate space
dx1 = x;
dy1 = y;
// copy destination into second cached texture, if necessary
// texture coordinates of the destination tile
// render composed texture to the destination surface
}
static HRESULT
{
if (glyphMode != MODE_NO_CACHE_GRAY) {
}
x0 = x;
x = x0;
}
}
return res;
}
static HRESULT
{
if (glyphMode != MODE_NO_CACHE_LCD) {
}
x0 = x;
tx1 = 0.0f;
ty1 = 0.0f;
dtx1 = 0.0f;
dty1 = 0.0f;
x = x0;
// calculate the bounds of the tile to be copied from the
// destination into the cached tile
cx1 = x;
cy1 = y;
// need to clamp to the destination bounds, otherwise the
// StretchRect() call may fail
// copy LCD mask into glyph texture tile
// update the lower-right glyph texture coordinates
// calculate the actual destination vertices
// copy destination into cached texture tile (the upper-left
// corner of the destination region will be positioned at the
// upper-left corner (0,0) of the texture)
&dstRect,
// update the remaining destination texture coordinates
// render composed texture to the destination surface
// unfortunately we need to flush after each tile
d3dc->FlushVertexQueue();
}
}
}
return res;
}
// see DrawGlyphList.c for more on this macro...
#define FLOOR_ASSIGN(l, r) \
if ((r)<0) (l) = ((int)floor(r)); else (l) = ((int)(r))
{
int glyphCounter;
if (usePositions) {
}
jint x, y;
// this shouldn't happen, but if it does we'll just break out...
"D3DTR_DrawGlyphList: glyph info is null");
break;
}
if (usePositions) {
FLOOR_ASSIGN(x, glyphx);
FLOOR_ASSIGN(y, glyphy);
} else {
FLOOR_ASSIGN(x, glyphx);
FLOOR_ASSIGN(y, glyphy);
}
continue;
}
if (grayscale) {
// grayscale or monochrome glyph data
{
} else {
}
} else {
// LCD-optimized glyph data
if (subPixPos) {
if (frac != 0) {
x += 1;
}
}
if (rowBytesOffset == 0 &&
{
ginfo, x, y,
} else {
ginfo, x, y,
}
}
break;
}
}
return res;
}
{
unsigned char *images;
images = (unsigned char *)
if (usePositions) {
unsigned char *positions = (unsigned char *)
}
} else {
}
// reset current state, and ensure rendering is flushed to dest
d3dc->FlushVertexQueue();
}
}
}