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 #include <malloc.h>
28 #include "sun_java2d_pipe_BufferedOpCodes.h"
29 
30 #include "jlong.h"
31 #include "D3DBlitLoops.h"
32 #include "D3DBufImgOps.h"
33 #include "D3DPipelineManager.h"
34 #include "D3DContext.h"
35 #include "D3DMaskBlit.h"
36 #include "D3DMaskFill.h"
37 #include "D3DPaints.h"
38 #include "D3DRenderQueue.h"
39 #include "D3DRenderer.h"
40 #include "D3DSurfaceData.h"
41 #include "D3DTextRenderer.h"
42 #include "Trace.h"
43 #include "awt_Toolkit.h"
44 
45 BOOL DWMIsCompositionEnabled();
46 
47 /**
48  * References to the "current" context and destination surface.
49  */
50 static D3DContext *d3dc = NULL;
51 static D3DSDOps *dstOps = NULL;
52 static BOOL bLostDevices = FALSE;
53 
54 typedef struct {
55     byte *buffer;
56     int limit;
57     jobject runnable;
58 } FlushBufferStruct;
59 
60 HRESULT
D3DRQ_SwapBuffers(D3DPipelineManager * pMgr,D3DSDOps * d3dsdo,int x1,int y1,int x2,int y2)61 D3DRQ_SwapBuffers(D3DPipelineManager *pMgr, D3DSDOps *d3dsdo,
62                   int x1, int y1, int x2, int y2)
63 {
64     HRESULT res;
65     D3DContext *pCtx;
66     IDirect3DSwapChain9 *pSwapChain;
67     RECT srcRect, dstRect, *pSrcRect, *pDstRect;
68 
69     J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_SwapBuffers");
70     J2dTraceLn4(J2D_TRACE_VERBOSE, "  x1=%d y1=%d x2=%d y2=%d",
71                 x1, y1, x2, y2);
72 
73     RETURN_STATUS_IF_NULL(d3dsdo, E_FAIL);
74     RETURN_STATUS_IF_NULL(d3dsdo->pResource, E_FAIL);
75     RETURN_STATUS_IF_NULL(pSwapChain=d3dsdo->pResource->GetSwapChain(), E_FAIL);
76 
77     pCtx = D3DRQ_GetCurrentContext();
78     if (pCtx != NULL) {
79         // flush the current vertex queue here, just in case
80         res = d3dc->FlushVertexQueue();
81         D3DRQ_MarkLostIfNeeded(res, dstOps);
82         pCtx = NULL;
83     }
84     // end scene for this destination
85     res = pMgr->GetD3DContext(d3dsdo->adapter, &pCtx);
86     RETURN_STATUS_IF_FAILED(res);
87 
88     pCtx->EndScene();
89 
90     // This is a workaround for what apparently is a DWM bug.
91     // If the dimensions of the back-buffer don't match the dimensions of
92     // the window, Present() will flash the whole window with black.
93     // The workaround is to detect this situation and not do a present.
94     // It is ok to do so since a repaint event is coming due to the resize that
95     // just happened.
96     //
97     // REMIND: this will need to be updated if we switch to creating
98     // back-buffers of the size of the client area instead of the whole window
99     // (use GetClientRect() instead of GetWindowRect()).
100     if (DWMIsCompositionEnabled()) {
101         RECT r;
102         D3DPRESENT_PARAMETERS params;
103 
104         pSwapChain->GetPresentParameters(&params);
105         GetWindowRect(params.hDeviceWindow, &r);
106         int ww = r.right - r.left;
107         int wh = r.bottom - r.top;
108         if (ww != params.BackBufferWidth || wh != params.BackBufferHeight) {
109             J2dTraceLn4(J2D_TRACE_WARNING,
110                 "D3DRQ_SwapBuffers: surface/window dimensions mismatch: "\
111                 "win: w=%d h=%d, bb: w=%d h=%d",
112                 ww, wh, params.BackBufferWidth, params.BackBufferHeight);
113 
114             return S_OK;
115         }
116     }
117 
118     if (d3dsdo->swapEffect == D3DSWAPEFFECT_COPY) {
119         J2dTraceLn(J2D_TRACE_VERBOSE, "  D3DSWAPEFFECT_COPY");
120         if (x1 < 0) x1 = 0;
121         if (y1 < 0) y1 = 0;
122         if (x2 > d3dsdo->width)  x2 = d3dsdo->width;
123         if (y2 > d3dsdo->height) y2 = d3dsdo->height;
124         if (x2 <= x1 || y2 <= y1) {
125             // nothing to present
126             return S_OK;
127         }
128         srcRect.left = x1;
129         srcRect.top = y1;
130         srcRect.right = x2;
131         srcRect.bottom = y2;
132 
133         dstRect = srcRect;
134 
135         pSrcRect = &srcRect;
136         pDstRect = &dstRect;
137         // only offset in windowed mode
138         if (pCtx!= NULL && pCtx->GetPresentationParams()->Windowed) {
139             OffsetRect(pDstRect, d3dsdo->xoff, d3dsdo->yoff);
140         } else {
141             // some boards (Nvidia) have problems with copy strategy and
142             // non-null src/dest rectangles in fs mode; unfortunately this
143             // means that we'll paint over fs window decorations
144             pSrcRect = NULL;
145             pDstRect = NULL;
146         }
147     } else {
148         if (d3dsdo->swapEffect == D3DSWAPEFFECT_FLIP) {
149             J2dTraceLn(J2D_TRACE_VERBOSE, "  D3DSWAPEFFECT_FLIP");
150         } else {
151             J2dTraceLn(J2D_TRACE_VERBOSE, "  D3DSWAPEFFECT_DISCARD");
152         }
153         // src and dest rectangles must be NULL for FLIP/DISCARD
154         pSrcRect = NULL;
155         pDstRect = NULL;
156     }
157 
158     res = pSwapChain->Present(pSrcRect, pDstRect, 0, NULL, 0);
159     res = D3DRQ_MarkLostIfNeeded(res, d3dsdo);
160 
161     return res;
162 }
163 
164 HRESULT
D3DRQ_MarkLostIfNeeded(HRESULT res,D3DSDOps * d3dops)165 D3DRQ_MarkLostIfNeeded(HRESULT res, D3DSDOps *d3dops)
166 {
167     if (res == D3DERR_DEVICELOST || res == D3DERR_DEVICENOTRESET) {
168         D3DContext *pCtx;
169 
170         J2dTraceLn(J2D_TRACE_WARNING, "D3DRQ_MarkLostIfNeeded: device lost");
171         bLostDevices = TRUE;
172 
173         // only mark surfaces belonging to the lost device
174         if (d3dops != NULL &&
175             SUCCEEDED(res = D3DPipelineManager::GetInstance()->
176                 GetD3DContext(d3dops->adapter, &pCtx)))
177         {
178             IDirect3DDevice9 *pd3dDevice = pCtx->Get3DDevice();
179             if (pd3dDevice) {
180                 HRESULT res1 = pd3dDevice->TestCooperativeLevel();
181                 if (res1 != D3DERR_DEVICELOST && res1 != D3DERR_DEVICENOTRESET){
182                     // this surface's device is not lost, do not mark it
183                     return res;
184                 }
185             }
186         }
187         D3DSD_MarkLost(d3dops);
188     }
189     return res;
190 }
191 
D3DRQ_FlushBuffer(void * pParam)192 void D3DRQ_FlushBuffer(void *pParam)
193 {
194     FlushBufferStruct *pFlush = (FlushBufferStruct*)pParam;
195     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
196     unsigned char *b, *end;
197     int limit;
198     HRESULT res = S_OK;
199     BOOL bSync = FALSE;
200 
201     b = pFlush->buffer;
202     limit = pFlush->limit;
203     J2dTraceLn1(J2D_TRACE_INFO, "D3DRQ_flushBuffer: limit=%d", limit);
204 
205     end = b + limit;
206 
207     D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance();
208     if (pMgr == NULL) {
209         J2dRlsTraceLn(J2D_TRACE_WARNING, "D3DRQ_flushBuffer: null manager");
210         return;
211     }
212 
213     if (bLostDevices) {
214         if (SUCCEEDED(res = pMgr->HandleLostDevices())) {
215             bLostDevices = FALSE;
216         }
217     }
218 
219     while (b < end) {
220         jint opcode = NEXT_INT(b);
221 
222         J2dTraceLn1(J2D_TRACE_VERBOSE, "D3DRQ_flushBuffer: opcode=%d", opcode);
223 
224         switch (opcode) {
225 
226         // draw ops
227         case sun_java2d_pipe_BufferedOpCodes_DRAW_LINE:
228             {
229                 jint x1 = NEXT_INT(b);
230                 jint y1 = NEXT_INT(b);
231                 jint x2 = NEXT_INT(b);
232                 jint y2 = NEXT_INT(b);
233 
234                 CONTINUE_IF_NULL(d3dc);
235                 res = D3DRenderer_DrawLine(d3dc, x1, y1, x2, y2);
236             }
237             break;
238         case sun_java2d_pipe_BufferedOpCodes_DRAW_RECT:
239             {
240                 jint x = NEXT_INT(b);
241                 jint y = NEXT_INT(b);
242                 jint w = NEXT_INT(b);
243                 jint h = NEXT_INT(b);
244                 CONTINUE_IF_NULL(d3dc);
245                 res = D3DRenderer_DrawRect(d3dc, x, y, w, h);
246             }
247             break;
248         case sun_java2d_pipe_BufferedOpCodes_DRAW_POLY:
249             {
250                 jint nPoints      = NEXT_INT(b);
251                 jboolean isClosed = NEXT_BOOLEAN(b);
252                 jint transX       = NEXT_INT(b);
253                 jint transY       = NEXT_INT(b);
254                 jint *xPoints = (jint *)b;
255                 jint *yPoints = ((jint *)b) + nPoints;
256                 CONTINUE_IF_NULL(d3dc);
257                 res = D3DRenderer_DrawPoly(d3dc, nPoints, isClosed,
258                                            transX, transY,
259                                      xPoints, yPoints);
260                 SKIP_BYTES(b, nPoints * BYTES_PER_POLY_POINT);
261             }
262             break;
263         case sun_java2d_pipe_BufferedOpCodes_DRAW_PIXEL:
264             {
265                 jint x = NEXT_INT(b);
266                 jint y = NEXT_INT(b);
267 
268                 CONTINUE_IF_NULL(d3dc);
269                 res = D3DRenderer_DrawLine(d3dc, x, y, x, y);
270             }
271             break;
272         case sun_java2d_pipe_BufferedOpCodes_DRAW_SCANLINES:
273             {
274                 jint count = NEXT_INT(b);
275                 res = D3DRenderer_DrawScanlines(d3dc, count, (jint *)b);
276                 SKIP_BYTES(b, count * BYTES_PER_SCANLINE);
277             }
278             break;
279         case sun_java2d_pipe_BufferedOpCodes_DRAW_PARALLELOGRAM:
280             {
281                 jfloat x11 = NEXT_FLOAT(b);
282                 jfloat y11 = NEXT_FLOAT(b);
283                 jfloat dx21 = NEXT_FLOAT(b);
284                 jfloat dy21 = NEXT_FLOAT(b);
285                 jfloat dx12 = NEXT_FLOAT(b);
286                 jfloat dy12 = NEXT_FLOAT(b);
287                 jfloat lwr21 = NEXT_FLOAT(b);
288                 jfloat lwr12 = NEXT_FLOAT(b);
289 
290                 CONTINUE_IF_NULL(d3dc);
291                 res = D3DRenderer_DrawParallelogram(d3dc,
292                                                     x11, y11,
293                                                     dx21, dy21,
294                                                     dx12, dy12,
295                                                     lwr21, lwr12);
296             }
297             break;
298         case sun_java2d_pipe_BufferedOpCodes_DRAW_AAPARALLELOGRAM:
299             {
300                 jfloat x11 = NEXT_FLOAT(b);
301                 jfloat y11 = NEXT_FLOAT(b);
302                 jfloat dx21 = NEXT_FLOAT(b);
303                 jfloat dy21 = NEXT_FLOAT(b);
304                 jfloat dx12 = NEXT_FLOAT(b);
305                 jfloat dy12 = NEXT_FLOAT(b);
306                 jfloat lwr21 = NEXT_FLOAT(b);
307                 jfloat lwr12 = NEXT_FLOAT(b);
308 
309                 CONTINUE_IF_NULL(d3dc);
310                 res = D3DRenderer_DrawAAParallelogram(d3dc,
311                                                       x11, y11,
312                                                       dx21, dy21,
313                                                       dx12, dy12,
314                                                       lwr21, lwr12);
315             }
316             break;
317 
318         // fill ops
319         case sun_java2d_pipe_BufferedOpCodes_FILL_RECT:
320             {
321                 jint x = NEXT_INT(b);
322                 jint y = NEXT_INT(b);
323                 jint w = NEXT_INT(b);
324                 jint h = NEXT_INT(b);
325 
326                 CONTINUE_IF_NULL(d3dc);
327                 res = D3DRenderer_FillRect(d3dc, x, y, w, h);
328             }
329             break;
330         case sun_java2d_pipe_BufferedOpCodes_FILL_PARALLELOGRAM:
331             {
332                 jfloat x11 = NEXT_FLOAT(b);
333                 jfloat y11 = NEXT_FLOAT(b);
334                 jfloat dx21 = NEXT_FLOAT(b);
335                 jfloat dy21 = NEXT_FLOAT(b);
336                 jfloat dx12 = NEXT_FLOAT(b);
337                 jfloat dy12 = NEXT_FLOAT(b);
338 
339                 CONTINUE_IF_NULL(d3dc);
340                 res = D3DRenderer_FillParallelogram(d3dc,
341                                                     x11, y11,
342                                                     dx21, dy21,
343                                                     dx12, dy12);
344             }
345             break;
346         case sun_java2d_pipe_BufferedOpCodes_FILL_AAPARALLELOGRAM:
347             {
348                 jfloat x11 = NEXT_FLOAT(b);
349                 jfloat y11 = NEXT_FLOAT(b);
350                 jfloat dx21 = NEXT_FLOAT(b);
351                 jfloat dy21 = NEXT_FLOAT(b);
352                 jfloat dx12 = NEXT_FLOAT(b);
353                 jfloat dy12 = NEXT_FLOAT(b);
354 
355                 CONTINUE_IF_NULL(d3dc);
356                 res = D3DRenderer_FillAAParallelogram(d3dc,
357                                                       x11, y11,
358                                                       dx21, dy21,
359                                                       dx12, dy12);
360             }
361             break;
362         case sun_java2d_pipe_BufferedOpCodes_FILL_SPANS:
363             {
364                 jint count = NEXT_INT(b);
365                 res = D3DRenderer_FillSpans(d3dc, count, (jint *)b);
366                 SKIP_BYTES(b, count * BYTES_PER_SPAN);
367             }
368             break;
369 
370         // text-related ops
371         case sun_java2d_pipe_BufferedOpCodes_DRAW_GLYPH_LIST:
372             {
373                 jint numGlyphs        = NEXT_INT(b);
374                 jint packedParams     = NEXT_INT(b);
375                 jfloat glyphListOrigX = NEXT_FLOAT(b);
376                 jfloat glyphListOrigY = NEXT_FLOAT(b);
377                 jboolean usePositions = EXTRACT_BOOLEAN(packedParams,
378                                                         OFFSET_POSITIONS);
379                 jboolean subPixPos    = EXTRACT_BOOLEAN(packedParams,
380                                                         OFFSET_SUBPIXPOS);
381                 jboolean rgbOrder     = EXTRACT_BOOLEAN(packedParams,
382                                                         OFFSET_RGBORDER);
383                 jint lcdContrast      = EXTRACT_BYTE(packedParams,
384                                                      OFFSET_CONTRAST);
385                 unsigned char *images = b;
386                 unsigned char *positions;
387                 jint bytesPerGlyph;
388                 if (usePositions) {
389                     positions = (b + numGlyphs * BYTES_PER_GLYPH_IMAGE);
390                     bytesPerGlyph = BYTES_PER_POSITIONED_GLYPH;
391                 } else {
392                     positions = NULL;
393                     bytesPerGlyph = BYTES_PER_GLYPH_IMAGE;
394                 }
395                 res = D3DTR_DrawGlyphList(d3dc, dstOps,
396                                           numGlyphs, usePositions,
397                                           subPixPos, rgbOrder, lcdContrast,
398                                           glyphListOrigX, glyphListOrigY,
399                                           images, positions);
400                 SKIP_BYTES(b, numGlyphs * bytesPerGlyph);
401             }
402             break;
403 
404         // copy-related ops
405         case sun_java2d_pipe_BufferedOpCodes_COPY_AREA:
406             {
407                 jint x  = NEXT_INT(b);
408                 jint y  = NEXT_INT(b);
409                 jint w  = NEXT_INT(b);
410                 jint h  = NEXT_INT(b);
411                 jint dx = NEXT_INT(b);
412                 jint dy = NEXT_INT(b);
413                 res = D3DBlitLoops_CopyArea(env, d3dc, dstOps,
414                                             x, y, w, h, dx, dy);
415             }
416             break;
417         case sun_java2d_pipe_BufferedOpCodes_BLIT:
418             {
419                 jint packedParams = NEXT_INT(b);
420                 jint sx1          = NEXT_INT(b);
421                 jint sy1          = NEXT_INT(b);
422                 jint sx2          = NEXT_INT(b);
423                 jint sy2          = NEXT_INT(b);
424                 jdouble dx1       = NEXT_DOUBLE(b);
425                 jdouble dy1       = NEXT_DOUBLE(b);
426                 jdouble dx2       = NEXT_DOUBLE(b);
427                 jdouble dy2       = NEXT_DOUBLE(b);
428                 jlong pSrc        = NEXT_LONG(b);
429                 jlong pDst        = NEXT_LONG(b);
430                 jint hint         = EXTRACT_BYTE(packedParams, OFFSET_HINT);
431                 jboolean texture  = EXTRACT_BOOLEAN(packedParams,
432                                                     OFFSET_TEXTURE);
433                 jboolean rtt      = EXTRACT_BOOLEAN(packedParams,
434                                                     OFFSET_RTT);
435                 jboolean xform    = EXTRACT_BOOLEAN(packedParams,
436                                                     OFFSET_XFORM);
437                 jboolean isoblit  = EXTRACT_BOOLEAN(packedParams,
438                                                     OFFSET_ISOBLIT);
439                 if (isoblit) {
440                     res = D3DBlitLoops_IsoBlit(env, d3dc, pSrc, pDst,
441                                                xform, hint, texture, rtt,
442                                                sx1, sy1, sx2, sy2,
443                                                dx1, dy1, dx2, dy2);
444                     D3DRQ_MarkLostIfNeeded(res, (D3DSDOps*)pSrc);
445                 } else {
446                     jint srctype = EXTRACT_BYTE(packedParams, OFFSET_SRCTYPE);
447                     res = D3DBlitLoops_Blit(env, d3dc, pSrc, pDst,
448                                             xform, hint, srctype, texture,
449                                             sx1, sy1, sx2, sy2,
450                                             dx1, dy1, dx2, dy2);
451                 }
452             }
453             break;
454         case sun_java2d_pipe_BufferedOpCodes_SURFACE_TO_SW_BLIT:
455             {
456                 jint sx      = NEXT_INT(b);
457                 jint sy      = NEXT_INT(b);
458                 jint dx      = NEXT_INT(b);
459                 jint dy      = NEXT_INT(b);
460                 jint w       = NEXT_INT(b);
461                 jint h       = NEXT_INT(b);
462                 jint dsttype = NEXT_INT(b);
463                 jlong pSrc   = NEXT_LONG(b);
464                 jlong pDst   = NEXT_LONG(b);
465                 res = D3DBlitLoops_SurfaceToSwBlit(env, d3dc,
466                                                    pSrc, pDst, dsttype,
467                                                    sx, sy, dx, dy, w, h);
468                 D3DRQ_MarkLostIfNeeded(res, (D3DSDOps*)pSrc);
469             }
470             break;
471         case sun_java2d_pipe_BufferedOpCodes_MASK_FILL:
472             {
473                 jint x        = NEXT_INT(b);
474                 jint y        = NEXT_INT(b);
475                 jint w        = NEXT_INT(b);
476                 jint h        = NEXT_INT(b);
477                 jint maskoff  = NEXT_INT(b);
478                 jint maskscan = NEXT_INT(b);
479                 jint masklen  = NEXT_INT(b);
480                 unsigned char *pMask = (masklen > 0) ? b : NULL;
481                 res = D3DMaskFill_MaskFill(d3dc, x, y, w, h,
482                                            maskoff, maskscan, masklen, pMask);
483                 SKIP_BYTES(b, masklen);
484             }
485             break;
486         case sun_java2d_pipe_BufferedOpCodes_MASK_BLIT:
487             {
488                 jint dstx     = NEXT_INT(b);
489                 jint dsty     = NEXT_INT(b);
490                 jint width    = NEXT_INT(b);
491                 jint height   = NEXT_INT(b);
492                 jint masklen  = width * height * sizeof(jint);
493                 res = D3DMaskBlit_MaskBlit(env, d3dc,
494                                            dstx, dsty, width, height, b);
495                 SKIP_BYTES(b, masklen);
496             }
497             break;
498 
499         // state-related ops
500         case sun_java2d_pipe_BufferedOpCodes_SET_RECT_CLIP:
501             {
502                 jint x1 = NEXT_INT(b);
503                 jint y1 = NEXT_INT(b);
504                 jint x2 = NEXT_INT(b);
505                 jint y2 = NEXT_INT(b);
506                 CONTINUE_IF_NULL(d3dc);
507                 res = d3dc->SetRectClip(x1, y1, x2, y2);
508             }
509             break;
510         case sun_java2d_pipe_BufferedOpCodes_BEGIN_SHAPE_CLIP:
511             {
512                 CONTINUE_IF_NULL(d3dc);
513                 res = d3dc->BeginShapeClip();
514             }
515             break;
516         case sun_java2d_pipe_BufferedOpCodes_SET_SHAPE_CLIP_SPANS:
517             {
518                 jint count = NEXT_INT(b);
519                 res = D3DRenderer_FillSpans(d3dc, count, (jint *)b);
520                 SKIP_BYTES(b, count * BYTES_PER_SPAN);
521             }
522             break;
523         case sun_java2d_pipe_BufferedOpCodes_END_SHAPE_CLIP:
524             {
525                 CONTINUE_IF_NULL(d3dc);
526                 res = d3dc->EndShapeClip();
527             }
528             break;
529         case sun_java2d_pipe_BufferedOpCodes_RESET_CLIP:
530             {
531                 CONTINUE_IF_NULL(d3dc);
532                 res = d3dc->ResetClip();
533             }
534             break;
535         case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
536             {
537                 jint rule         = NEXT_INT(b);
538                 jfloat extraAlpha = NEXT_FLOAT(b);
539                 jint flags        = NEXT_INT(b);
540                 CONTINUE_IF_NULL(d3dc);
541                 res = d3dc->SetAlphaComposite(rule, extraAlpha, flags);
542             }
543             break;
544         case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
545             {
546                 jint xorPixel = NEXT_INT(b);
547 //                res = d3dc->SetXorComposite(d3dc, xorPixel);
548             }
549             break;
550         case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
551             {
552                 CONTINUE_IF_NULL(d3dc);
553                 res = d3dc->ResetComposite();
554             }
555             break;
556         case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
557             {
558                 jdouble m00 = NEXT_DOUBLE(b);
559                 jdouble m10 = NEXT_DOUBLE(b);
560                 jdouble m01 = NEXT_DOUBLE(b);
561                 jdouble m11 = NEXT_DOUBLE(b);
562                 jdouble m02 = NEXT_DOUBLE(b);
563                 jdouble m12 = NEXT_DOUBLE(b);
564                 res = d3dc->SetTransform(m00, m10, m01, m11, m02, m12);
565             }
566             break;
567         case sun_java2d_pipe_BufferedOpCodes_RESET_TRANSFORM:
568             {
569                 CONTINUE_IF_NULL(d3dc);
570                 res = d3dc->ResetTransform();
571             }
572             break;
573 
574         // context-related ops
575         case sun_java2d_pipe_BufferedOpCodes_SET_SURFACES:
576             {
577                 jlong pSrc = NEXT_LONG(b);
578                 jlong pDst = NEXT_LONG(b);
579                 D3DContext *oldd3dc = NULL;
580                 if (d3dc != NULL) {
581                     oldd3dc = d3dc;
582                     d3dc = NULL;
583                     oldd3dc->UpdateState(STATE_CHANGE);
584                 }
585                 dstOps = (D3DSDOps *)jlong_to_ptr(pDst);
586                 res = pMgr->GetD3DContext(dstOps->adapter, &d3dc);
587                 if (FAILED(res)) {
588                     J2dRlsTraceLn(J2D_TRACE_ERROR,
589                         "D3DRQ_FlushBuffer: failed to get context");
590                     D3DRQ_ResetCurrentContextAndDestination();
591                     break;
592                 }
593                 // REMIND: we may also want to do EndScene on each
594                 // render target change so that the GPU can go work on
595                 // whatever is already in the queue
596                 if (oldd3dc != d3dc && oldd3dc != NULL) {
597                     res = oldd3dc->EndScene();
598                 }
599                 CONTINUE_IF_NULL(dstOps->pResource);
600                 res = d3dc->SetRenderTarget(dstOps->pResource->GetSurface());
601             }
602             break;
603         case sun_java2d_pipe_BufferedOpCodes_SET_SCRATCH_SURFACE:
604             {
605                 jint screen = NEXT_INT(b);
606                 jint adapter = pMgr->GetAdapterOrdinalForScreen(screen);
607                 D3DContext *oldd3dc = NULL;
608 
609                 if (d3dc != NULL) {
610                     oldd3dc = d3dc;
611                     d3dc = NULL;
612                 }
613                 res = pMgr->GetD3DContext(adapter, &d3dc);
614                 if (FAILED(res)) {
615                     J2dRlsTraceLn(J2D_TRACE_ERROR,
616                         "D3DRQ_FlushBuffer: failed to get context");
617                     D3DRQ_ResetCurrentContextAndDestination();
618                 } else if (oldd3dc != d3dc && oldd3dc != NULL) {
619                     res = oldd3dc->EndScene();
620                 }
621             }
622             break;
623         case sun_java2d_pipe_BufferedOpCodes_FLUSH_SURFACE:
624             {
625                 jlong pData = NEXT_LONG(b);
626                 D3DSDOps *d3dsdo = (D3DSDOps *)jlong_to_ptr(pData);
627                 D3DSD_Flush(d3dsdo);
628                 if (dstOps == d3dsdo) {
629                     dstOps = NULL;
630                 }
631             }
632             break;
633         case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
634             {
635                 jlong pData = NEXT_LONG(b);
636                 D3DSDOps *d3dsdo = (D3DSDOps *)jlong_to_ptr(pData);
637                 D3DSD_Flush(d3dsdo);
638                 if (dstOps == d3dsdo) {
639                     dstOps = NULL;
640                 }
641             }
642             break;
643         case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
644             {
645                 jlong pConfigInfo = NEXT_LONG(b);
646                 CONTINUE_IF_NULL(d3dc);
647                 // REMIND: does this need to be implemented for D3D?
648             }
649             break;
650         case sun_java2d_pipe_BufferedOpCodes_INVALIDATE_CONTEXT:
651             {
652                 // flush just in case there are any pending operations in
653                 // the hardware pipe
654                 if (d3dc != NULL) {
655                     res = d3dc->EndScene();
656                 }
657 
658                 // invalidate the references to the current context and
659                 // destination surface that are maintained at the native level
660                 D3DRQ_ResetCurrentContextAndDestination();
661             }
662             break;
663 
664         case sun_java2d_pipe_BufferedOpCodes_SYNC:
665             {
666                 bSync = TRUE;
667             }
668             break;
669 
670         case sun_java2d_pipe_BufferedOpCodes_RESTORE_DEVICES:
671             {
672                 J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_FlushBuffer:  RESTORE_DEVICES");
673                 if (SUCCEEDED(res = pMgr->HandleLostDevices())) {
674                     bLostDevices = FALSE;
675                 } else {
676                     bLostDevices = TRUE;
677                 }
678             }
679             break;
680 
681         case sun_java2d_pipe_BufferedOpCodes_SAVE_STATE:
682             {
683                 CONTINUE_IF_NULL(d3dc);
684 
685                 res = d3dc->SaveState();
686             }
687             break;
688 
689         case sun_java2d_pipe_BufferedOpCodes_RESTORE_STATE:
690             {
691                 CONTINUE_IF_NULL(d3dc);
692 
693                 res = d3dc->RestoreState();
694             }
695             break;
696 
697         // multibuffering ops
698         case sun_java2d_pipe_BufferedOpCodes_SWAP_BUFFERS:
699             {
700                 jlong sdo = NEXT_LONG(b);
701                 jint x1 = NEXT_INT(b);
702                 jint y1 = NEXT_INT(b);
703                 jint x2 = NEXT_INT(b);
704                 jint y2 = NEXT_INT(b);
705 
706                 res = D3DRQ_SwapBuffers(pMgr, (D3DSDOps *)jlong_to_ptr(sdo),
707                                         x1, y1, x2, y2);
708             }
709             break;
710 
711         // special no-op (mainly used for achieving 8-byte alignment)
712         case sun_java2d_pipe_BufferedOpCodes_NOOP:
713             break;
714 
715         // paint-related ops
716         case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT:
717             {
718                 res = D3DPaints_ResetPaint(d3dc);
719             }
720             break;
721         case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
722             {
723                 jint pixel = NEXT_INT(b);
724                 res = D3DPaints_SetColor(d3dc, pixel);
725             }
726             break;
727         case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
728             {
729                 jboolean useMask= NEXT_BOOLEAN(b);
730                 jboolean cyclic = NEXT_BOOLEAN(b);
731                 jdouble p0      = NEXT_DOUBLE(b);
732                 jdouble p1      = NEXT_DOUBLE(b);
733                 jdouble p3      = NEXT_DOUBLE(b);
734                 jint pixel1     = NEXT_INT(b);
735                 jint pixel2     = NEXT_INT(b);
736                 res = D3DPaints_SetGradientPaint(d3dc, useMask, cyclic,
737                                                  p0, p1, p3,
738                                                  pixel1, pixel2);
739             }
740             break;
741         case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:
742             {
743                 jboolean useMask = NEXT_BOOLEAN(b);
744                 jboolean linear  = NEXT_BOOLEAN(b);
745                 jint cycleMethod = NEXT_INT(b);
746                 jint numStops    = NEXT_INT(b);
747                 jfloat p0        = NEXT_FLOAT(b);
748                 jfloat p1        = NEXT_FLOAT(b);
749                 jfloat p3        = NEXT_FLOAT(b);
750                 void *fractions, *pixels;
751                 fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
752                 pixels    = b; SKIP_BYTES(b, numStops * sizeof(jint));
753                 res = D3DPaints_SetLinearGradientPaint(d3dc, dstOps,
754                                                         useMask, linear,
755                                                         cycleMethod, numStops,
756                                                         p0, p1, p3,
757                                                         fractions, pixels);
758             }
759             break;
760         case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT:
761             {
762                 jboolean useMask = NEXT_BOOLEAN(b);
763                 jboolean linear  = NEXT_BOOLEAN(b);
764                 jint numStops    = NEXT_INT(b);
765                 jint cycleMethod = NEXT_INT(b);
766                 jfloat m00       = NEXT_FLOAT(b);
767                 jfloat m01       = NEXT_FLOAT(b);
768                 jfloat m02       = NEXT_FLOAT(b);
769                 jfloat m10       = NEXT_FLOAT(b);
770                 jfloat m11       = NEXT_FLOAT(b);
771                 jfloat m12       = NEXT_FLOAT(b);
772                 jfloat focusX    = NEXT_FLOAT(b);
773                 void *fractions, *pixels;
774                 fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat));
775                 pixels    = b; SKIP_BYTES(b, numStops * sizeof(jint));
776                 res = D3DPaints_SetRadialGradientPaint(d3dc, dstOps,
777                                                        useMask, linear,
778                                                        cycleMethod, numStops,
779                                                        m00, m01, m02,
780                                                        m10, m11, m12,
781                                                        focusX,
782                                                        fractions, pixels);
783             }
784             break;
785         case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT:
786             {
787                 jboolean useMask= NEXT_BOOLEAN(b);
788                 jboolean filter = NEXT_BOOLEAN(b);
789                 jlong pSrc      = NEXT_LONG(b);
790                 jdouble xp0     = NEXT_DOUBLE(b);
791                 jdouble xp1     = NEXT_DOUBLE(b);
792                 jdouble xp3     = NEXT_DOUBLE(b);
793                 jdouble yp0     = NEXT_DOUBLE(b);
794                 jdouble yp1     = NEXT_DOUBLE(b);
795                 jdouble yp3     = NEXT_DOUBLE(b);
796                 res = D3DPaints_SetTexturePaint(d3dc, useMask, pSrc, filter,
797                                                 xp0, xp1, xp3,
798                                                 yp0, yp1, yp3);
799             }
800             break;
801 
802         // BufferedImageOp-related ops
803         case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP:
804             {
805                 jlong pSrc        = NEXT_LONG(b);
806                 jboolean edgeZero = NEXT_BOOLEAN(b);
807                 jint kernelWidth  = NEXT_INT(b);
808                 jint kernelHeight = NEXT_INT(b);
809                 res = D3DBufImgOps_EnableConvolveOp(d3dc, pSrc, edgeZero,
810                                                     kernelWidth, kernelHeight, b);
811                 SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat));
812             }
813             break;
814         case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP:
815             {
816                 res = D3DBufImgOps_DisableConvolveOp(d3dc);
817             }
818             break;
819         case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP:
820             {
821                 jlong pSrc          = NEXT_LONG(b); // unused
822                 jboolean nonPremult = NEXT_BOOLEAN(b);
823                 jint numFactors     = 4;
824                 unsigned char *scaleFactors = b;
825                 unsigned char *offsets = (b + numFactors * sizeof(jfloat));
826                 res = D3DBufImgOps_EnableRescaleOp(d3dc, nonPremult,
827                                                    scaleFactors, offsets);
828                 SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2);
829             }
830             break;
831         case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP:
832             {
833                 D3DBufImgOps_DisableRescaleOp(d3dc);
834             }
835             break;
836         case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP:
837             {
838                 jlong pSrc          = NEXT_LONG(b); // unused
839                 jboolean nonPremult = NEXT_BOOLEAN(b);
840                 jboolean shortData  = NEXT_BOOLEAN(b);
841                 jint numBands       = NEXT_INT(b);
842                 jint bandLength     = NEXT_INT(b);
843                 jint offset         = NEXT_INT(b);
844                 jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte);
845                 void *tableValues = b;
846                 res = D3DBufImgOps_EnableLookupOp(d3dc, nonPremult, shortData,
847                                                   numBands, bandLength, offset,
848                                                   tableValues);
849                 SKIP_BYTES(b, numBands * bandLength * bytesPerElem);
850             }
851             break;
852         case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP:
853             {
854                 res = D3DBufImgOps_DisableLookupOp(d3dc);
855             }
856             break;
857 
858         default:
859             J2dRlsTraceLn1(J2D_TRACE_ERROR,
860                 "D3DRQ_flushBuffer: invalid opcode=%d", opcode);
861             return;
862         }
863         // we may mark the surface lost repeatedly but that won't do much harm
864         res = D3DRQ_MarkLostIfNeeded(res, dstOps);
865     }
866 
867     if (d3dc != NULL) {
868         res = d3dc->EndScene();
869         // REMIND: EndScene is not really enough to flush the
870         // whole d3d pipeline
871 
872         // REMIND: there may be an issue with BeginScene/EndScene
873         // for each flushQueue, because of the blits, which flush
874         // the queue
875         if (bSync) {
876             res = d3dc->Sync();
877         }
878     }
879 
880     // REMIND: we need to also handle hard errors here as well, and disable
881     // particular context if needed
882     D3DRQ_MarkLostIfNeeded(res, dstOps);
883 
884     if (!JNU_IsNull(env, pFlush->runnable)) {
885         J2dTraceLn(J2D_TRACE_VERBOSE, "  executing runnable");
886         JNU_CallMethodByName(env, NULL, pFlush->runnable, "run", "()V");
887     }
888 }
889 
890 /**
891  * Returns a pointer to the "current" context, as set by the last SET_SURFACES
892  * or SET_SCRATCH_SURFACE operation.
893  */
894 D3DContext *
D3DRQ_GetCurrentContext()895 D3DRQ_GetCurrentContext()
896 {
897     return d3dc;
898 }
899 
900 /**
901  * Returns a pointer to the "current" destination surface, as set by the last
902  * SET_SURFACES operation.
903  */
904 D3DSDOps *
D3DRQ_GetCurrentDestination()905 D3DRQ_GetCurrentDestination()
906 {
907     return dstOps;
908 }
909 
910 /**
911  * Resets current context and destination surface.
912  */
913 void
D3DRQ_ResetCurrentContextAndDestination()914 D3DRQ_ResetCurrentContextAndDestination()
915 {
916     J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_ResetCurrentContextAndDestination");
917 
918     d3dc = NULL;
919     dstOps = NULL;
920 }
921 
922 extern "C"
923 {
924 
925 /*
926  * Class:     sun_java2d_d3d_D3DRenderQueue
927  * Method:    flushBuffer
928  * Signature: (JILjava/lang/Runnable;)V
929  */
930 JNIEXPORT void JNICALL
Java_sun_java2d_d3d_D3DRenderQueue_flushBuffer(JNIEnv * env,jobject d3drq,jlong buf,jint limit,jobject runnable)931 Java_sun_java2d_d3d_D3DRenderQueue_flushBuffer
932   (JNIEnv *env, jobject d3drq, jlong buf, jint limit, jobject runnable)
933 {
934     FlushBufferStruct bufstr;
935     // just in case we forget to init any new fields
936     ZeroMemory(&bufstr, sizeof(FlushBufferStruct));
937 
938     bufstr.buffer = (unsigned char *)jlong_to_ptr(buf);
939     if (bufstr.buffer == NULL) {
940         J2dRlsTraceLn(J2D_TRACE_ERROR,
941             "D3DRenderQueue_flushBuffer: cannot get direct buffer address");
942         return;
943     }
944     bufstr.limit = limit;
945 
946     bufstr.runnable = JNU_IsNull(env, runnable) ?
947         NULL : env->NewGlobalRef(runnable);
948     AwtToolkit::GetInstance().InvokeFunction(D3DRQ_FlushBuffer, &bufstr);
949     if (!JNU_IsNull(env, bufstr.runnable)) {
950         env->DeleteGlobalRef(bufstr.runnable);
951     }
952 }
953 
954 }
955