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 "D3DPipeline.h"
27 
28 #include "sun_java2d_d3d_D3DRenderer.h"
29 
30 #include "D3DContext.h"
31 #include "D3DRenderer.h"
32 #include "D3DRenderQueue.h"
33 
34 HRESULT D3DPIPELINE_API
D3DRenderer_DrawLine(D3DContext * d3dc,jint x1,jint y1,jint x2,jint y2)35 D3DRenderer_DrawLine(D3DContext *d3dc,
36                      jint x1, jint y1, jint x2, jint y2)
37 {
38     J2dTraceLn4(J2D_TRACE_INFO,
39                 "D3DRenderer_doDrawLineD3D x1=%-4d y1=%-4d x2=%-4d y2=%-4d",
40                 x1, y1, x2, y2);
41     d3dc->BeginScene(STATE_RENDEROP);
42     return d3dc->pVCacher->DrawLine(x1, y1, x2, y2);
43 }
44 
45 HRESULT D3DPIPELINE_API
D3DRenderer_DrawRect(D3DContext * d3dc,jint x,jint y,jint w,jint h)46 D3DRenderer_DrawRect(D3DContext *d3dc,
47                      jint x, jint y, jint w, jint h)
48 {
49     J2dTraceLn4(J2D_TRACE_INFO,
50                 "D3DRenderer_DrawRect x=%-4d y=%-4d w=%-4d h=%-4d",
51                 x, y, w, h);
52 
53     d3dc->BeginScene(STATE_RENDEROP);
54     return d3dc->pVCacher->DrawRect(x, y, x + w, y + h);
55 }
56 
57 HRESULT D3DPIPELINE_API
D3DRenderer_FillRect(D3DContext * d3dc,jint x,jint y,jint w,jint h)58 D3DRenderer_FillRect(D3DContext *d3dc,
59                      jint x, jint y, jint w, jint h)
60 {
61     J2dTraceLn4(J2D_TRACE_INFO,
62                "D3DRenderer_FillRect x=%-4d y=%-4d w=%-4d h=%-4d",
63                 x, y, w, h);
64 
65     d3dc->BeginScene(STATE_RENDEROP);
66     return d3dc->pVCacher->FillRect(x, y, x + w, y + h);
67 }
68 
69 HRESULT D3DPIPELINE_API
D3DRenderer_DrawPoly(D3DContext * d3dc,jint nPoints,jboolean isClosed,jint transX,jint transY,jint * xPoints,jint * yPoints)70 D3DRenderer_DrawPoly(D3DContext *d3dc,
71                      jint nPoints, jboolean isClosed,
72                      jint transX, jint transY,
73                      jint *xPoints, jint *yPoints)
74 {
75     J2dTraceLn(J2D_TRACE_INFO, "D3DRenderer_DrawPoly");
76 
77     if (d3dc == NULL || xPoints == NULL || yPoints == NULL) {
78         J2dRlsTraceLn(J2D_TRACE_ERROR,
79             "D3DRenderer_DrawPoly: d3dc, xPoints or yPoints is NULL");
80         return E_FAIL;
81     }
82 
83     d3dc->BeginScene(STATE_RENDEROP);
84     return d3dc->pVCacher->DrawPoly(nPoints, isClosed, transX, transY,
85                                     xPoints, yPoints);
86 }
87 
88 HRESULT D3DPIPELINE_API
D3DRenderer_DrawScanlines(D3DContext * d3dc,jint scanlineCount,jint * scanlines)89 D3DRenderer_DrawScanlines(D3DContext *d3dc,
90                           jint scanlineCount, jint *scanlines)
91 {
92     J2dTraceLn(J2D_TRACE_INFO, "D3DRenderer_DrawScanlines");
93 
94     if (d3dc == NULL) {
95        return E_FAIL;
96     }
97     if (scanlines == NULL || scanlineCount <= 0) {
98         return D3D_OK;
99     }
100 
101     d3dc->BeginScene(STATE_RENDEROP);
102     return d3dc->pVCacher->DrawScanlines(scanlineCount, scanlines);
103 }
104 
105 HRESULT D3DPIPELINE_API
D3DRenderer_FillSpans(D3DContext * d3dc,jint spanCount,jint * spans)106 D3DRenderer_FillSpans(D3DContext *d3dc, jint spanCount, jint *spans)
107 {
108     J2dTraceLn(J2D_TRACE_INFO, "D3DRenderer_FillSpans");
109     if (d3dc == NULL) {
110         return E_FAIL;
111     }
112 
113     d3dc->BeginScene(STATE_RENDEROP);
114     return d3dc->pVCacher->FillSpans(spanCount, spans);
115 }
116 
117 HRESULT D3DPIPELINE_API
D3DRenderer_FillParallelogram(D3DContext * d3dc,jfloat fx11,jfloat fy11,jfloat dx21,jfloat dy21,jfloat dx12,jfloat dy12)118 D3DRenderer_FillParallelogram(D3DContext *d3dc,
119                               jfloat fx11, jfloat fy11,
120                               jfloat dx21, jfloat dy21,
121                               jfloat dx12, jfloat dy12)
122 {
123     J2dTraceLn6(J2D_TRACE_INFO,
124                 "D3DRenderer_FillParallelogram "
125                 "x=%6.2f y=%6.2f "
126                 "dx1=%6.2f dy1=%6.2f "
127                 "dx2=%6.2f dy2=%6.2f ",
128                 fx11, fy11,
129                 dx21, dy21,
130                 dx12, dy12);
131 
132     d3dc->BeginScene(STATE_RENDEROP);
133     return d3dc->pVCacher->FillParallelogram(fx11, fy11,
134                                              dx21, dy21,
135                                              dx12, dy12);
136 }
137 
138 HRESULT D3DPIPELINE_API
D3DRenderer_DrawParallelogram(D3DContext * d3dc,jfloat fx11,jfloat fy11,jfloat dx21,jfloat dy21,jfloat dx12,jfloat dy12,jfloat lwr21,jfloat lwr12)139 D3DRenderer_DrawParallelogram(D3DContext *d3dc,
140                               jfloat fx11, jfloat fy11,
141                               jfloat dx21, jfloat dy21,
142                               jfloat dx12, jfloat dy12,
143                               jfloat lwr21, jfloat lwr12)
144 {
145     HRESULT res;
146 
147     J2dTraceLn8(J2D_TRACE_INFO,
148                 "D3DRenderer_DrawParallelogram "
149                 "x=%6.2f y=%6.2f "
150                 "dx1=%6.2f dy1=%6.2f lwr1=%6.2f "
151                 "dx2=%6.2f dy2=%6.2f lwr2=%6.2f ",
152                 fx11, fy11,
153                 dx21, dy21, lwr21,
154                 dx12, dy12, lwr12);
155 
156     // dx,dy for line width in the "21" and "12" directions.
157     jfloat ldx21 = dx21 * lwr21;
158     jfloat ldy21 = dy21 * lwr21;
159     jfloat ldx12 = dx12 * lwr12;
160     jfloat ldy12 = dy12 * lwr12;
161 
162     // calculate origin of the outer parallelogram
163     jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f;
164     jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f;
165 
166     res = d3dc->BeginScene(STATE_RENDEROP);
167     RETURN_STATUS_IF_FAILED(res);
168 
169     // Only need to generate 4 quads if the interior still
170     // has a hole in it (i.e. if the line width ratio was
171     // less than 1.0)
172     if (lwr21 < 1.0f && lwr12 < 1.0f) {
173         // Note: "TOP", "BOTTOM", "LEFT" and "RIGHT" here are
174         // relative to whether the dxNN variables are positive
175         // and negative.  The math works fine regardless of
176         // their signs, but for conceptual simplicity the
177         // comments will refer to the sides as if the dxNN
178         // were all positive.  "TOP" and "BOTTOM" segments
179         // are defined by the dxy21 deltas.  "LEFT" and "RIGHT"
180         // segments are defined by the dxy12 deltas.
181 
182         // Each segment includes its starting corner and comes
183         // to just short of the following corner.  Thus, each
184         // corner is included just once and the only lengths
185         // needed are the original parallelogram delta lengths
186         // and the "line width deltas".  The sides will cover
187         // the following relative territories:
188         //
189         //     T T T T T R
190         //      L         R
191         //       L         R
192         //        L         R
193         //         L         R
194         //          L B B B B B
195 
196         // TOP segment, to left side of RIGHT edge
197         // "width" of original pgram, "height" of hor. line size
198         fx11 = ox11;
199         fy11 = oy11;
200         res = d3dc->pVCacher->FillParallelogram(fx11, fy11,
201                                                 dx21, dy21,
202                                                 ldx12, ldy12);
203 
204         // RIGHT segment, to top of BOTTOM edge
205         // "width" of vert. line size , "height" of original pgram
206         fx11 = ox11 + dx21;
207         fy11 = oy11 + dy21;
208         res = d3dc->pVCacher->FillParallelogram(fx11, fy11,
209                                                 ldx21, ldy21,
210                                                 dx12, dy12);
211 
212         // BOTTOM segment, from right side of LEFT edge
213         // "width" of original pgram, "height" of hor. line size
214         fx11 = ox11 + dx12 + ldx21;
215         fy11 = oy11 + dy12 + ldy21;
216         res = d3dc->pVCacher->FillParallelogram(fx11, fy11,
217                                                 dx21, dy21,
218                                                 ldx12, ldy12);
219 
220         // LEFT segment, from bottom of TOP edge
221         // "width" of vert. line size , "height" of inner pgram
222         fx11 = ox11 + ldx12;
223         fy11 = oy11 + ldy12;
224         res = d3dc->pVCacher->FillParallelogram(fx11, fy11,
225                                                 ldx21, ldy21,
226                                                 dx12, dy12);
227     } else {
228         // The line width ratios were large enough to consume
229         // the entire hole in the middle of the parallelogram
230         // so we can just issue one large quad for the outer
231         // parallelogram.
232         dx21 += ldx21;
233         dy21 += ldy21;
234         dx12 += ldx12;
235         dy12 += ldy12;
236 
237         res = d3dc->pVCacher->FillParallelogram(ox11, oy11,
238                                                 dx21, dy21,
239                                                 dx12, dy12);
240     }
241 
242     return res;
243 }
244 
245 HRESULT D3DPIPELINE_API
D3DRenderer_FillAAParallelogram(D3DContext * d3dc,jfloat fx11,jfloat fy11,jfloat dx21,jfloat dy21,jfloat dx12,jfloat dy12)246 D3DRenderer_FillAAParallelogram(D3DContext *d3dc,
247                                 jfloat fx11, jfloat fy11,
248                                 jfloat dx21, jfloat dy21,
249                                 jfloat dx12, jfloat dy12)
250 {
251     IDirect3DDevice9 *pd3dDevice;
252     HRESULT res;
253 
254     J2dTraceLn6(J2D_TRACE_INFO,
255                 "D3DRenderer_FillAAParallelogram "
256                 "x=%6.2f y=%6.2f "
257                 "dx1=%6.2f dy1=%6.2f "
258                 "dx2=%6.2f dy2=%6.2f ",
259                 fx11, fy11,
260                 dx21, dy21,
261                 dx12, dy12);
262 
263     res = d3dc->BeginScene(STATE_AAPGRAMOP);
264     RETURN_STATUS_IF_FAILED(res);
265 
266     pd3dDevice = d3dc->Get3DDevice();
267     if (pd3dDevice == NULL) {
268         return E_FAIL;
269     }
270 
271     res = d3dc->pVCacher->FillParallelogramAA(fx11, fy11,
272                                               dx21, dy21,
273                                               dx12, dy12);
274     return res;
275 }
276 
277 HRESULT D3DPIPELINE_API
D3DRenderer_DrawAAParallelogram(D3DContext * d3dc,jfloat fx11,jfloat fy11,jfloat dx21,jfloat dy21,jfloat dx12,jfloat dy12,jfloat lwr21,jfloat lwr12)278 D3DRenderer_DrawAAParallelogram(D3DContext *d3dc,
279                                 jfloat fx11, jfloat fy11,
280                                 jfloat dx21, jfloat dy21,
281                                 jfloat dx12, jfloat dy12,
282                                 jfloat lwr21, jfloat lwr12)
283 {
284     IDirect3DDevice9 *pd3dDevice;
285     // dx,dy for line width in the "21" and "12" directions.
286     jfloat ldx21, ldy21, ldx12, ldy12;
287     // parameters for "outer" parallelogram
288     jfloat ofx11, ofy11, odx21, ody21, odx12, ody12;
289     // parameters for "inner" parallelogram
290     jfloat ifx11, ify11, idx21, idy21, idx12, idy12;
291     HRESULT res;
292 
293     J2dTraceLn8(J2D_TRACE_INFO,
294                 "D3DRenderer_DrawAAParallelogram "
295                 "x=%6.2f y=%6.2f "
296                 "dx1=%6.2f dy1=%6.2f lwr1=%6.2f "
297                 "dx2=%6.2f dy2=%6.2f lwr2=%6.2f ",
298                 fx11, fy11,
299                 dx21, dy21, lwr21,
300                 dx12, dy12, lwr12);
301 
302     res = d3dc->BeginScene(STATE_AAPGRAMOP);
303     RETURN_STATUS_IF_FAILED(res);
304 
305     pd3dDevice = d3dc->Get3DDevice();
306     if (pd3dDevice == NULL) {
307         return E_FAIL;
308     }
309 
310     // calculate true dx,dy for line widths from the "line width ratios"
311     ldx21 = dx21 * lwr21;
312     ldy21 = dy21 * lwr21;
313     ldx12 = dx12 * lwr12;
314     ldy12 = dy12 * lwr12;
315 
316     // calculate coordinates of the outer parallelogram
317     ofx11 = fx11 - (ldx21 + ldx12) / 2.0f;
318     ofy11 = fy11 - (ldy21 + ldy12) / 2.0f;
319     odx21 = dx21 + ldx21;
320     ody21 = dy21 + ldy21;
321     odx12 = dx12 + ldx12;
322     ody12 = dy12 + ldy12;
323 
324     // Only process the inner parallelogram if the line width ratio
325     // did not consume the entire interior of the parallelogram
326     // (i.e. if the width ratio was less than 1.0)
327     if (lwr21 < 1.0f && lwr12 < 1.0f) {
328         // calculate coordinates of the inner parallelogram
329         ifx11 = fx11 + (ldx21 + ldx12) / 2.0f;
330         ify11 = fy11 + (ldy21 + ldy12) / 2.0f;
331         idx21 = dx21 - ldx21;
332         idy21 = dy21 - ldy21;
333         idx12 = dx12 - ldx12;
334         idy12 = dy12 - ldy12;
335 
336         res = d3dc->pVCacher->DrawParallelogramAA(ofx11, ofy11,
337                                                   odx21, ody21,
338                                                   odx12, ody12,
339                                                   ifx11, ify11,
340                                                   idx21, idy21,
341                                                   idx12, idy12);
342     } else {
343         // Just invoke a regular fill on the outer parallelogram
344         res = d3dc->pVCacher->FillParallelogramAA(ofx11, ofy11,
345                                                   odx21, ody21,
346                                                   odx12, ody12);
347     }
348 
349     return res;
350 }
351 
352 #ifndef D3D_PPL_DLL
353 
354 extern "C"
355 {
356 
357 JNIEXPORT void JNICALL
Java_sun_java2d_d3d_D3DRenderer_drawPoly(JNIEnv * env,jobject d3dr,jintArray xpointsArray,jintArray ypointsArray,jint nPoints,jboolean isClosed,jint transX,jint transY)358 Java_sun_java2d_d3d_D3DRenderer_drawPoly
359     (JNIEnv *env, jobject d3dr,
360      jintArray xpointsArray, jintArray ypointsArray,
361      jint nPoints, jboolean isClosed,
362      jint transX, jint transY)
363 {
364     jint *xPoints, *yPoints;
365 
366     J2dTraceLn(J2D_TRACE_INFO, "D3DRenderer_drawPoly");
367 
368     xPoints = (jint *)env->GetPrimitiveArrayCritical(xpointsArray, NULL);
369     if (xPoints != NULL) {
370         yPoints = (jint *)env->GetPrimitiveArrayCritical(ypointsArray, NULL);
371         if (yPoints != NULL) {
372             D3DContext *d3dc = D3DRQ_GetCurrentContext();
373 
374             D3DRenderer_DrawPoly(d3dc,
375                                  nPoints, isClosed,
376                                  transX, transY,
377                                  xPoints, yPoints);
378 
379             if (d3dc != NULL) {
380                 HRESULT res = d3dc->EndScene();
381                 D3DRQ_MarkLostIfNeeded(res,
382                     D3DRQ_GetCurrentDestination());
383             }
384             env->ReleasePrimitiveArrayCritical(ypointsArray, yPoints, JNI_ABORT);
385         }
386         env->ReleasePrimitiveArrayCritical(xpointsArray, xPoints, JNI_ABORT);
387     }
388 }
389 
390 }
391 
392 #endif // D3D_PPL_DLL
393