jdk/src/windows/native/sun/java2d/d3d/D3DTextRenderer_md.cpp
changeset 930 2f703334f63f
parent 929 d958f883b42a
parent 923 e9301d8f49ef
child 932 2aabadbd9e85
equal deleted inserted replaced
929:d958f883b42a 930:2f703334f63f
     1 /*
       
     2  * Copyright 2005-2006 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #include <malloc.h>
       
    27 #include "sun_java2d_d3d_D3DTextRenderer.h"
       
    28 #include "SurfaceData.h"
       
    29 #include "Region.h"
       
    30 #include "glyphblitting.h"
       
    31 #include "fontscalerdefs.h"
       
    32 #include "AccelGlyphCache.h"
       
    33 #include "j2d_md.h"
       
    34 #include "jlong.h"
       
    35 
       
    36 #include "ddrawUtils.h"
       
    37 #include "D3DContext.h"
       
    38 #include "D3DUtils.h"
       
    39 #include "Win32SurfaceData.h"
       
    40 
       
    41 extern "C" {
       
    42 
       
    43 #define MAX_STATIC_QUADS_NUM 40
       
    44 static int indicesInited = 0;
       
    45 static short vertexIndices[MAX_STATIC_QUADS_NUM*6];
       
    46 static J2DLV_QUAD vertexQuads[MAX_STATIC_QUADS_NUM];
       
    47 
       
    48 /**
       
    49  * Initializes the array of index vertices used for rendering
       
    50  * glyphs using cached texture.
       
    51  */
       
    52 static void
       
    53 InitIndexArray()
       
    54 {
       
    55     int ii, vi;
       
    56     memset(vertexQuads, 0, sizeof(vertexQuads));
       
    57     for (ii = 0, vi = 0; ii < MAX_STATIC_QUADS_NUM*6; ii += 6, vi += 4) {
       
    58         vertexIndices[ii + 0] = vi + 0;
       
    59         vertexIndices[ii + 1] = vi + 1;
       
    60         vertexIndices[ii + 2] = vi + 2;
       
    61         vertexIndices[ii + 3] = vi + 0;
       
    62         vertexIndices[ii + 4] = vi + 2;
       
    63         vertexIndices[ii + 5] = vi + 3;
       
    64     }
       
    65 }
       
    66 
       
    67 /**
       
    68  * Renders each glyph directly from the glyph texture cache.
       
    69  */
       
    70 static HRESULT
       
    71 D3DDrawGlyphList_UseCache(JNIEnv *env, Win32SDOps *wsdo,
       
    72                           D3DContext *d3dc,
       
    73                           ImageRef *glyphs, jint totalGlyphs)
       
    74 {
       
    75     int glyphCounter;
       
    76     HRESULT res = DDERR_GENERIC;
       
    77     DXSurface *glyphCacheTexture;
       
    78     J2dTraceLn(J2D_TRACE_INFO, "D3DDrawGlyphList_UseCache");
       
    79     int color = d3dc->colorPixel;
       
    80     int quadCounter = 0;
       
    81 
       
    82     DDrawSurface *ddTargetSurface = d3dc->GetTargetSurface();
       
    83     if (ddTargetSurface == NULL) {
       
    84         return DDERR_GENERIC;
       
    85     }
       
    86     ddTargetSurface->GetExclusiveAccess();
       
    87     d3dc->GetExclusiveAccess();
       
    88 
       
    89     glyphCacheTexture = d3dc->GetGlyphCacheTexture();
       
    90     IDirect3DDevice7 *d3dDevice = d3dc->Get3DDevice();
       
    91     if (d3dDevice == NULL ||
       
    92         FAILED(res = d3dc->BeginScene(STATE_MASKOP)))
       
    93     {
       
    94         d3dc->ReleaseExclusiveAccess();
       
    95         ddTargetSurface->ReleaseExclusiveAccess();
       
    96         return res;
       
    97     }
       
    98 
       
    99     if (FAILED(res = d3dc->SetTexture(glyphCacheTexture))) {
       
   100         d3dc->EndScene(res);
       
   101         d3dc->ReleaseExclusiveAccess();
       
   102         ddTargetSurface->ReleaseExclusiveAccess();
       
   103         return res;
       
   104     }
       
   105 
       
   106     if (!indicesInited) {
       
   107         InitIndexArray();
       
   108         indicesInited = 1;
       
   109     }
       
   110 
       
   111     for (glyphCounter = 0; (glyphCounter < totalGlyphs) && SUCCEEDED(res);
       
   112          glyphCounter++)
       
   113     {
       
   114         // render glyph cached in texture object
       
   115         const jubyte *pixels = (const jubyte *)glyphs[glyphCounter].pixels;
       
   116         GlyphInfo *ginfo = (GlyphInfo *)glyphs[glyphCounter].glyphInfo;
       
   117         CacheCellInfo *cell;
       
   118         float x1, y1, x2, y2;
       
   119         float tx1, ty1, tx2, ty2;
       
   120         J2DLV_QUAD *quad;
       
   121 
       
   122         // it the glyph is an empty space, skip it
       
   123         if (!pixels) {
       
   124             continue;
       
   125         }
       
   126 
       
   127         if (ginfo->cellInfo == NULL ||
       
   128             // REMIND: this is a temp fix to allow a glyph be cached
       
   129             // in caches for different devices.
       
   130             // REMIND: check if this is even a problem: we're using
       
   131             // managed textures, they may be automatically accelerated
       
   132             // on a different device.
       
   133             // If the glyph is cached on a different device, cache
       
   134             // it on this context's device.
       
   135             // This may result in thrashing if the same glyphs
       
   136             // get rendered on different devices.
       
   137             // Note: this is not thread-safe: we may change the coordinates
       
   138             // while another thread is using this cell.
       
   139             // A proper fix would allow a glyph to be cached in multiple
       
   140             // caches at the same time.
       
   141             d3dc->GetGlyphCache() != ginfo->cellInfo->cacheInfo)
       
   142         {
       
   143             // attempt to add glyph to accelerated glyph cache
       
   144             if (FAILED(d3dc->GlyphCacheAdd(env, ginfo)) ||
       
   145                 ginfo->cellInfo == NULL)
       
   146             {
       
   147                 continue;
       
   148             }
       
   149         }
       
   150 
       
   151         cell = ginfo->cellInfo;
       
   152         cell->timesRendered++;
       
   153 
       
   154         x1 = (float)glyphs[glyphCounter].x;
       
   155         y1 = (float)glyphs[glyphCounter].y;
       
   156         x2 = x1 + (float)glyphs[glyphCounter].width;
       
   157         y2 = y1 + (float)glyphs[glyphCounter].height;
       
   158         tx1 = cell->tx1;
       
   159         ty1 = cell->ty1;
       
   160         tx2 = cell->tx2;
       
   161         ty2 = cell->ty2;
       
   162         quad = &vertexQuads[quadCounter++];
       
   163 
       
   164         D3DU_INIT_VERTEX_QUAD(*quad, x1, y1, x2, y2, color     ,
       
   165                               tx1, ty1, tx2, ty2);
       
   166 
       
   167         if (quadCounter == MAX_STATIC_QUADS_NUM &&
       
   168             SUCCEEDED(res = ddTargetSurface->IsLost()))
       
   169         {
       
   170             res = d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
       
   171                                                   D3DFVF_J2DLVERTEX,
       
   172                                                   vertexQuads,
       
   173                                                   4*quadCounter,
       
   174                                                   (LPWORD)vertexIndices,
       
   175                                                   6*quadCounter, 0);
       
   176             quadCounter = 0;
       
   177         }
       
   178     }
       
   179 
       
   180     if (quadCounter > 0 && SUCCEEDED(res)) {
       
   181         res = d3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
       
   182                                               D3DFVF_J2DLVERTEX,
       
   183                                               vertexQuads,
       
   184                                               4*quadCounter,
       
   185                                               (LPWORD)vertexIndices,
       
   186                                               6*quadCounter, 0);
       
   187     }
       
   188 
       
   189     d3dc->EndScene(res);
       
   190 
       
   191     d3dc->ReleaseExclusiveAccess();
       
   192     ddTargetSurface->ReleaseExclusiveAccess();
       
   193 
       
   194     return res;
       
   195 }
       
   196 
       
   197 static HRESULT
       
   198 D3DDrawGlyphList_NoCache(JNIEnv *env, Win32SDOps *wsdo,
       
   199                          D3DContext *d3dc,
       
   200                          ImageRef *glyphs, jint totalGlyphs)
       
   201 {
       
   202     int glyphCounter;
       
   203     float tx1, ty1, tx2, ty2;
       
   204     jint tw, th;
       
   205     DXSurface *maskTexture;
       
   206     static J2DLVERTEX quadVerts[4] = {
       
   207         { 0.0f, 0.0f, 0.0f, 0x0, 0.0f, 0.0f },
       
   208         { 0.0f, 0.0f, 0.0f, 0x0, 0.0f, 0.0f },
       
   209         { 0.0f, 0.0f, 0.0f, 0x0, 0.0f, 0.0f },
       
   210         { 0.0f, 0.0f, 0.0f, 0x0, 0.0f, 0.0f }
       
   211     };
       
   212 
       
   213     J2dTraceLn(J2D_TRACE_INFO, "D3DDrawGlyphList_NoCache");
       
   214 
       
   215     DDrawSurface *ddTargetSurface = d3dc->GetTargetSurface();
       
   216     if (ddTargetSurface == NULL) {
       
   217         return DDERR_GENERIC;
       
   218     }
       
   219     ddTargetSurface->GetExclusiveAccess();
       
   220     d3dc->GetExclusiveAccess();
       
   221 
       
   222     HRESULT res = DDERR_GENERIC;
       
   223 
       
   224     IDirect3DDevice7 *d3dDevice = d3dc->Get3DDevice();
       
   225     if (d3dDevice == NULL) {
       
   226         d3dc->ReleaseExclusiveAccess();
       
   227         ddTargetSurface->ReleaseExclusiveAccess();
       
   228         return res;
       
   229     }
       
   230 
       
   231     maskTexture = d3dc->GetMaskTexture();
       
   232     if (maskTexture == NULL ||
       
   233         FAILED(res = d3dc->BeginScene(STATE_MASKOP)))
       
   234     {
       
   235         d3dc->ReleaseExclusiveAccess();
       
   236         ddTargetSurface->ReleaseExclusiveAccess();
       
   237         return DDERR_GENERIC;
       
   238     }
       
   239 
       
   240     if (FAILED(res = d3dc->SetTexture(maskTexture))) {
       
   241         d3dc->EndScene(res);
       
   242         d3dc->ReleaseExclusiveAccess();
       
   243         ddTargetSurface->ReleaseExclusiveAccess();
       
   244         return res;
       
   245     }
       
   246 
       
   247     tx1 = 0.0f;
       
   248     ty1 = 0.0f;
       
   249     tw = D3DSD_MASK_TILE_SIZE;
       
   250     th = D3DSD_MASK_TILE_SIZE;
       
   251 
       
   252     D3DU_INIT_VERTEX_QUAD_COLOR(quadVerts, d3dc->colorPixel);
       
   253     for (glyphCounter = 0; (glyphCounter < totalGlyphs) && SUCCEEDED(res);
       
   254          glyphCounter++)
       
   255     {
       
   256         // render system memory glyph image
       
   257         jint sx, sy, sw, sh;
       
   258         jint x, y, w, h, x0;
       
   259         const jubyte *pixels = (const jubyte *)glyphs[glyphCounter].pixels;
       
   260 
       
   261         if (!pixels) {
       
   262             continue;
       
   263         }
       
   264 
       
   265         x = glyphs[glyphCounter].x;
       
   266         y = glyphs[glyphCounter].y;
       
   267         w = glyphs[glyphCounter].width;
       
   268         h = glyphs[glyphCounter].height;
       
   269         x0 = x;
       
   270 
       
   271         for (sy = 0; sy < h; sy += th, y += th) {
       
   272             x = x0;
       
   273             sh = ((sy + th) > h) ? (h - sy) : th;
       
   274 
       
   275             for (sx = 0; sx < w; sx += tw, x += tw) {
       
   276                 sw = ((sx + tw) > w) ? (w - sx) : tw;
       
   277 
       
   278                 if (FAILED(d3dc->UploadImageToTexture(maskTexture,
       
   279                                                       (jubyte*)pixels,
       
   280                                                       0, 0, sx, sy,
       
   281                                                       sw, sh, w)))
       
   282                 {
       
   283                     continue;
       
   284                 }
       
   285 
       
   286                 // update the lower right texture coordinates
       
   287                 tx2 = ((float)sw) / tw;
       
   288                 ty2 = ((float)sh) / th;
       
   289 
       
   290                 D3DU_INIT_VERTEX_QUAD_XYUV(quadVerts,
       
   291                                            (float)x, (float)y,
       
   292                                            (float)(x+sw), (float)(y+sh),
       
   293                                            tx1, ty1, tx2, ty2);
       
   294                 if (SUCCEEDED(res = ddTargetSurface->IsLost())) {
       
   295                     res = d3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
       
   296                                                    D3DFVF_J2DLVERTEX,
       
   297                                                    quadVerts, 4, 0);
       
   298                 }
       
   299             }
       
   300         }
       
   301     }
       
   302 
       
   303     d3dc->EndScene(res);
       
   304 
       
   305     d3dc->ReleaseExclusiveAccess();
       
   306     ddTargetSurface->ReleaseExclusiveAccess();
       
   307 
       
   308     return res;
       
   309 }
       
   310 
       
   311 
       
   312 JNIEXPORT void JNICALL
       
   313 D3DDrawGlyphList(JNIEnv *env, jobject d3dtr,
       
   314                  jlong pData, jlong pCtx,
       
   315                  ImageRef *glyphs, jint totalGlyphs,
       
   316                  jboolean useCache)
       
   317 {
       
   318     Win32SDOps *wsdo = (Win32SDOps *)jlong_to_ptr(pData);
       
   319     D3DContext *d3dc = (D3DContext *)jlong_to_ptr(pCtx);
       
   320 
       
   321     HRESULT res;
       
   322     // Note: uncomment to control glyph caching via env. variable.
       
   323     // useCache = useCache && !getenv("J2D_D3D_NOGLYPHCACHING");
       
   324 
       
   325     if (d3dc == NULL) {
       
   326         return;
       
   327     }
       
   328 
       
   329     if (useCache && SUCCEEDED(res = d3dc->InitGlyphCache())) {
       
   330         D3D_EXEC_PRIM_LOOP(env, res, wsdo,
       
   331                       D3DDrawGlyphList_UseCache(env, wsdo, d3dc, glyphs,
       
   332                                                 totalGlyphs));
       
   333         return;
       
   334     }
       
   335 
       
   336     D3D_EXEC_PRIM_LOOP(env, res, wsdo,
       
   337                   D3DDrawGlyphList_NoCache(env, wsdo, d3dc, glyphs,
       
   338                                            totalGlyphs));
       
   339 }
       
   340 
       
   341 }