1 /* 2 * Copyright (c) 2007, 2019, 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(¶ms); 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 // multibuffering ops 681 case sun_java2d_pipe_BufferedOpCodes_SWAP_BUFFERS: 682 { 683 jlong sdo = NEXT_LONG(b); 684 jint x1 = NEXT_INT(b); 685 jint y1 = NEXT_INT(b); 686 jint x2 = NEXT_INT(b); 687 jint y2 = NEXT_INT(b); 688 689 res = D3DRQ_SwapBuffers(pMgr, (D3DSDOps *)jlong_to_ptr(sdo), 690 x1, y1, x2, y2); 691 } 692 break; 693 694 // special no-op (mainly used for achieving 8-byte alignment) 695 case sun_java2d_pipe_BufferedOpCodes_NOOP: 696 break; 697 698 // paint-related ops 699 case sun_java2d_pipe_BufferedOpCodes_RESET_PAINT: 700 { 701 res = D3DPaints_ResetPaint(d3dc); 702 } 703 break; 704 case sun_java2d_pipe_BufferedOpCodes_SET_COLOR: 705 { 706 jint pixel = NEXT_INT(b); 707 res = D3DPaints_SetColor(d3dc, pixel); 708 } 709 break; 710 case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT: 711 { 712 jboolean useMask= NEXT_BOOLEAN(b); 713 jboolean cyclic = NEXT_BOOLEAN(b); 714 jdouble p0 = NEXT_DOUBLE(b); 715 jdouble p1 = NEXT_DOUBLE(b); 716 jdouble p3 = NEXT_DOUBLE(b); 717 jint pixel1 = NEXT_INT(b); 718 jint pixel2 = NEXT_INT(b); 719 res = D3DPaints_SetGradientPaint(d3dc, useMask, cyclic, 720 p0, p1, p3, 721 pixel1, pixel2); 722 } 723 break; 724 case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT: 725 { 726 jboolean useMask = NEXT_BOOLEAN(b); 727 jboolean linear = NEXT_BOOLEAN(b); 728 jint cycleMethod = NEXT_INT(b); 729 jint numStops = NEXT_INT(b); 730 jfloat p0 = NEXT_FLOAT(b); 731 jfloat p1 = NEXT_FLOAT(b); 732 jfloat p3 = NEXT_FLOAT(b); 733 void *fractions, *pixels; 734 fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat)); 735 pixels = b; SKIP_BYTES(b, numStops * sizeof(jint)); 736 res = D3DPaints_SetLinearGradientPaint(d3dc, dstOps, 737 useMask, linear, 738 cycleMethod, numStops, 739 p0, p1, p3, 740 fractions, pixels); 741 } 742 break; 743 case sun_java2d_pipe_BufferedOpCodes_SET_RADIAL_GRADIENT_PAINT: 744 { 745 jboolean useMask = NEXT_BOOLEAN(b); 746 jboolean linear = NEXT_BOOLEAN(b); 747 jint numStops = NEXT_INT(b); 748 jint cycleMethod = NEXT_INT(b); 749 jfloat m00 = NEXT_FLOAT(b); 750 jfloat m01 = NEXT_FLOAT(b); 751 jfloat m02 = NEXT_FLOAT(b); 752 jfloat m10 = NEXT_FLOAT(b); 753 jfloat m11 = NEXT_FLOAT(b); 754 jfloat m12 = NEXT_FLOAT(b); 755 jfloat focusX = NEXT_FLOAT(b); 756 void *fractions, *pixels; 757 fractions = b; SKIP_BYTES(b, numStops * sizeof(jfloat)); 758 pixels = b; SKIP_BYTES(b, numStops * sizeof(jint)); 759 res = D3DPaints_SetRadialGradientPaint(d3dc, dstOps, 760 useMask, linear, 761 cycleMethod, numStops, 762 m00, m01, m02, 763 m10, m11, m12, 764 focusX, 765 fractions, pixels); 766 } 767 break; 768 case sun_java2d_pipe_BufferedOpCodes_SET_TEXTURE_PAINT: 769 { 770 jboolean useMask= NEXT_BOOLEAN(b); 771 jboolean filter = NEXT_BOOLEAN(b); 772 jlong pSrc = NEXT_LONG(b); 773 jdouble xp0 = NEXT_DOUBLE(b); 774 jdouble xp1 = NEXT_DOUBLE(b); 775 jdouble xp3 = NEXT_DOUBLE(b); 776 jdouble yp0 = NEXT_DOUBLE(b); 777 jdouble yp1 = NEXT_DOUBLE(b); 778 jdouble yp3 = NEXT_DOUBLE(b); 779 res = D3DPaints_SetTexturePaint(d3dc, useMask, pSrc, filter, 780 xp0, xp1, xp3, 781 yp0, yp1, yp3); 782 } 783 break; 784 785 // BufferedImageOp-related ops 786 case sun_java2d_pipe_BufferedOpCodes_ENABLE_CONVOLVE_OP: 787 { 788 jlong pSrc = NEXT_LONG(b); 789 jboolean edgeZero = NEXT_BOOLEAN(b); 790 jint kernelWidth = NEXT_INT(b); 791 jint kernelHeight = NEXT_INT(b); 792 res = D3DBufImgOps_EnableConvolveOp(d3dc, pSrc, edgeZero, 793 kernelWidth, kernelHeight, b); 794 SKIP_BYTES(b, kernelWidth * kernelHeight * sizeof(jfloat)); 795 } 796 break; 797 case sun_java2d_pipe_BufferedOpCodes_DISABLE_CONVOLVE_OP: 798 { 799 res = D3DBufImgOps_DisableConvolveOp(d3dc); 800 } 801 break; 802 case sun_java2d_pipe_BufferedOpCodes_ENABLE_RESCALE_OP: 803 { 804 jlong pSrc = NEXT_LONG(b); // unused 805 jboolean nonPremult = NEXT_BOOLEAN(b); 806 jint numFactors = 4; 807 unsigned char *scaleFactors = b; 808 unsigned char *offsets = (b + numFactors * sizeof(jfloat)); 809 res = D3DBufImgOps_EnableRescaleOp(d3dc, nonPremult, 810 scaleFactors, offsets); 811 SKIP_BYTES(b, numFactors * sizeof(jfloat) * 2); 812 } 813 break; 814 case sun_java2d_pipe_BufferedOpCodes_DISABLE_RESCALE_OP: 815 { 816 D3DBufImgOps_DisableRescaleOp(d3dc); 817 } 818 break; 819 case sun_java2d_pipe_BufferedOpCodes_ENABLE_LOOKUP_OP: 820 { 821 jlong pSrc = NEXT_LONG(b); // unused 822 jboolean nonPremult = NEXT_BOOLEAN(b); 823 jboolean shortData = NEXT_BOOLEAN(b); 824 jint numBands = NEXT_INT(b); 825 jint bandLength = NEXT_INT(b); 826 jint offset = NEXT_INT(b); 827 jint bytesPerElem = shortData ? sizeof(jshort):sizeof(jbyte); 828 void *tableValues = b; 829 res = D3DBufImgOps_EnableLookupOp(d3dc, nonPremult, shortData, 830 numBands, bandLength, offset, 831 tableValues); 832 SKIP_BYTES(b, numBands * bandLength * bytesPerElem); 833 } 834 break; 835 case sun_java2d_pipe_BufferedOpCodes_DISABLE_LOOKUP_OP: 836 { 837 res = D3DBufImgOps_DisableLookupOp(d3dc); 838 } 839 break; 840 841 default: 842 J2dRlsTraceLn1(J2D_TRACE_ERROR, 843 "D3DRQ_flushBuffer: invalid opcode=%d", opcode); 844 return; 845 } 846 // we may mark the surface lost repeatedly but that won't do much harm 847 res = D3DRQ_MarkLostIfNeeded(res, dstOps); 848 } 849 850 if (d3dc != NULL) { 851 res = d3dc->EndScene(); 852 // REMIND: EndScene is not really enough to flush the 853 // whole d3d pipeline 854 855 // REMIND: there may be an issue with BeginScene/EndScene 856 // for each flushQueue, because of the blits, which flush 857 // the queue 858 if (bSync) { 859 res = d3dc->Sync(); 860 } 861 } 862 863 // REMIND: we need to also handle hard errors here as well, and disable 864 // particular context if needed 865 D3DRQ_MarkLostIfNeeded(res, dstOps); 866 867 if (!JNU_IsNull(env, pFlush->runnable)) { 868 J2dTraceLn(J2D_TRACE_VERBOSE, " executing runnable"); 869 JNU_CallMethodByName(env, NULL, pFlush->runnable, "run", "()V"); 870 } 871 } 872 873 /** 874 * Returns a pointer to the "current" context, as set by the last SET_SURFACES 875 * or SET_SCRATCH_SURFACE operation. 876 */ 877 D3DContext * 878 D3DRQ_GetCurrentContext() 879 { 880 return d3dc; 881 } 882 883 /** 884 * Returns a pointer to the "current" destination surface, as set by the last 885 * SET_SURFACES operation. 886 */ 887 D3DSDOps * 888 D3DRQ_GetCurrentDestination() 889 { 890 return dstOps; 891 } 892 893 /** 894 * Resets current context and destination surface. 895 */ 896 void 897 D3DRQ_ResetCurrentContextAndDestination() 898 { 899 J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_ResetCurrentContextAndDestination"); 900 901 d3dc = NULL; 902 dstOps = NULL; 903 } 904 905 extern "C" 906 { 907 908 /* 909 * Class: sun_java2d_d3d_D3DRenderQueue 910 * Method: flushBuffer 911 * Signature: (JILjava/lang/Runnable;)V 912 */ 913 JNIEXPORT void JNICALL 914 Java_sun_java2d_d3d_D3DRenderQueue_flushBuffer 915 (JNIEnv *env, jobject d3drq, jlong buf, jint limit, jobject runnable) 916 { 917 FlushBufferStruct bufstr; 918 // just in case we forget to init any new fields 919 ZeroMemory(&bufstr, sizeof(FlushBufferStruct)); 920 921 bufstr.buffer = (unsigned char *)jlong_to_ptr(buf); 922 if (bufstr.buffer == NULL) { 923 J2dRlsTraceLn(J2D_TRACE_ERROR, 924 "D3DRenderQueue_flushBuffer: cannot get direct buffer address"); 925 return; 926 } 927 bufstr.limit = limit; 928 929 bufstr.runnable = JNU_IsNull(env, runnable) ? 930 NULL : env->NewGlobalRef(runnable); 931 AwtToolkit::GetInstance().InvokeFunction(D3DRQ_FlushBuffer, &bufstr); 932 if (!JNU_IsNull(env, bufstr.runnable)) { 933 env->DeleteGlobalRef(bufstr.runnable); 934 } 935 } 936 937 }