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
  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
 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 
 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 *
 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 *
 905 D3DRQ_GetCurrentDestination()
 906 {
 907     return dstOps;
 908 }
 909 
 910 /**
 911  * Resets current context and destination surface.
 912  */
 913 void
 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
 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 }