1 /*
2  * Copyright (c) 2007, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 #include "sun_java2d_d3d_D3DMaskFill.h"
27 
28 #include "D3DMaskFill.h"
29 #include "D3DRenderQueue.h"
30 
31 /**
32  * This implementation first copies the alpha tile into a texture and then
33  * maps that texture to the destination surface.  This approach appears to
34  * offer the best performance despite being a two-step process.
35  *
36  * Here are some descriptions of the many variables used in this method:
37  *   x,y     - upper left corner of the tile destination
38  *   w,h     - width/height of the mask tile
39  *   x0      - placekeeper for the original destination x location
40  *   tw,th   - width/height of the actual texture tile in pixels
41  *   sx1,sy1 - upper left corner of the mask tile source region
42  *   sx2,sy2 - lower left corner of the mask tile source region
43  *   sx,sy   - "current" upper left corner of the mask tile region of interest
44  */
45 HRESULT
D3DMaskFill_MaskFill(D3DContext * d3dc,jint x,jint y,jint w,jint h,jint maskoff,jint maskscan,jint masklen,unsigned char * pMask)46 D3DMaskFill_MaskFill(D3DContext *d3dc,
47                      jint x, jint y, jint w, jint h,
48                      jint maskoff, jint maskscan, jint masklen,
49                      unsigned char *pMask)
50 {
51     HRESULT res = S_OK;
52 
53     J2dTraceLn(J2D_TRACE_INFO, "D3DMaskFill_MaskFill");
54 
55     RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
56 
57     J2dTraceLn4(J2D_TRACE_VERBOSE, "  x=%d y=%d w=%d h=%d", x, y, w, h);
58     J2dTraceLn2(J2D_TRACE_VERBOSE, "  maskoff=%d maskscan=%d",
59                 maskoff, maskscan);
60 
61     {
62         D3DMaskCache *maskCache = d3dc->GetMaskCache();
63         jint tw, th, x0;
64         jint sx1, sy1, sx2, sy2;
65         jint sx, sy, sw, sh;
66 
67         res = d3dc->BeginScene(STATE_MASKOP);
68         RETURN_STATUS_IF_FAILED(res);
69 
70         x0 = x;
71         tw = D3D_MASK_CACHE_TILE_WIDTH;
72         th = D3D_MASK_CACHE_TILE_HEIGHT;
73         sx1 = maskoff % maskscan;
74         sy1 = maskoff / maskscan;
75         sx2 = sx1 + w;
76         sy2 = sy1 + h;
77 
78         for (sy = sy1; sy < sy2; sy += th, y += th) {
79             x = x0;
80             sh = ((sy + th) > sy2) ? (sy2 - sy) : th;
81 
82             for (sx = sx1; sx < sx2; sx += tw, x += tw) {
83                 sw = ((sx + tw) > sx2) ? (sx2 - sx) : tw;
84 
85                 res = maskCache->AddMaskQuad(sx, sy, x, y, sw, sh,
86                                              maskscan, pMask);
87             }
88         }
89     }
90     return res;
91 }
92 
93 JNIEXPORT void JNICALL
Java_sun_java2d_d3d_D3DMaskFill_maskFill(JNIEnv * env,jobject self,jint x,jint y,jint w,jint h,jint maskoff,jint maskscan,jint masklen,jbyteArray maskArray)94 Java_sun_java2d_d3d_D3DMaskFill_maskFill
95     (JNIEnv *env, jobject self,
96      jint x, jint y, jint w, jint h,
97      jint maskoff, jint maskscan, jint masklen,
98      jbyteArray maskArray)
99 {
100     D3DContext *d3dc = D3DRQ_GetCurrentContext();
101     unsigned char *mask;
102 
103     J2dTraceLn(J2D_TRACE_ERROR, "D3DMaskFill_maskFill");
104 
105     if (maskArray != NULL) {
106         mask = (unsigned char *)
107             env->GetPrimitiveArrayCritical(maskArray, NULL);
108     } else {
109         mask = NULL;
110     }
111 
112     D3DMaskFill_MaskFill(d3dc,
113                          x, y, w, h,
114                          maskoff, maskscan, masklen, mask);
115 
116     // reset current state, and ensure rendering is flushed to dest
117     if (d3dc != NULL) {
118         d3dc->FlushVertexQueue();
119     }
120 
121     if (mask != NULL) {
122         env->ReleasePrimitiveArrayCritical(maskArray, mask, JNI_ABORT);
123     }
124 }
125