1 /* 2 * Copyright (c) 2007, 2016, 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 "jlong.h" 28 29 #include "GraphicsPrimitiveMgr.h" 30 #include "D3DContext.h" 31 #include "D3DSurfaceData.h" 32 #include "D3DBufImgOps.h" 33 #include "D3DPaints.h" 34 #include "D3DRenderQueue.h" 35 #include "D3DShaders.h" 36 #include "D3DTextRenderer.h" 37 #include "D3DPipelineManager.h" 38 #include "D3DGlyphCache.h" 39 #include "Devices.h" 40 41 typedef struct { 42 D3DBLEND src; 43 D3DBLEND dst; 44 } D3DBlendRule; 45 46 /** 47 * This table contains the standard blending rules (or Porter-Duff compositing 48 * factors) used in SetRenderState(), indexed by the rule constants from the 49 * AlphaComposite class. 50 */ 51 D3DBlendRule StdBlendRules[] = { 52 { D3DBLEND_ZERO, D3DBLEND_ZERO }, /* 0 - Nothing */ 53 { D3DBLEND_ZERO, D3DBLEND_ZERO }, /* 1 - RULE_Clear */ 54 { D3DBLEND_ONE, D3DBLEND_ZERO }, /* 2 - RULE_Src */ 55 { D3DBLEND_ONE, D3DBLEND_INVSRCALPHA }, /* 3 - RULE_SrcOver */ 56 { D3DBLEND_INVDESTALPHA, D3DBLEND_ONE }, /* 4 - RULE_DstOver */ 57 { D3DBLEND_DESTALPHA, D3DBLEND_ZERO }, /* 5 - RULE_SrcIn */ 58 { D3DBLEND_ZERO, D3DBLEND_SRCALPHA }, /* 6 - RULE_DstIn */ 59 { D3DBLEND_INVDESTALPHA, D3DBLEND_ZERO }, /* 7 - RULE_SrcOut */ 60 { D3DBLEND_ZERO, D3DBLEND_INVSRCALPHA }, /* 8 - RULE_DstOut */ 61 { D3DBLEND_ZERO, D3DBLEND_ONE }, /* 9 - RULE_Dst */ 62 { D3DBLEND_DESTALPHA, D3DBLEND_INVSRCALPHA }, /*10 - RULE_SrcAtop */ 63 { D3DBLEND_INVDESTALPHA, D3DBLEND_SRCALPHA }, /*11 - RULE_DstAtop */ 64 { D3DBLEND_INVDESTALPHA, D3DBLEND_INVSRCALPHA }, /*12 - RULE_AlphaXor*/ 65 }; 66 67 void 68 D3DUtils_SetOrthoMatrixOffCenterLH(D3DMATRIX *m, 69 float width, float height) 70 { 71 ZeroMemory(m, sizeof(D3DMATRIX)); 72 m->_11 = 2.0f/width; 73 m->_22 = -2.0f/height; 74 m->_33 = 0.5f; 75 m->_44 = 1.0f; 76 77 m->_41 = -1.0f; 78 m->_42 = 1.0f; 79 m->_43 = 0.5f; 80 } 81 82 void 83 D3DUtils_SetIdentityMatrix(D3DMATRIX *m) 84 { 85 m->_12 = m->_13 = m->_14 = m->_21 = m->_23 = m->_24 = 0.0f; 86 m->_31 = m->_32 = m->_34 = m->_41 = m->_42 = m->_43 = 0.0f; 87 m->_11 = m->_22 = m->_33 = m->_44 = 1.0f; 88 } 89 90 // the following methods are copies of the AffineTransform's class 91 // corresponding methods, with these changes to the indexes: 92 // 00 -> 11 93 // 11 -> 22 94 // 01 -> 21 95 // 10 -> 12 96 // 02 -> 41 97 // 12 -> 42 98 99 void 100 D3DUtils_2DConcatenateM(D3DMATRIX *m, D3DMATRIX *m1) 101 { 102 float M0, M1; 103 float T00, T10, T01, T11; 104 float T02, T12; 105 106 T00 = m1->_11; T01 = m1->_21; T02 = m1->_41; 107 T10 = m1->_12; T11 = m1->_22; T12 = m1->_42; 108 109 M0 = m->_11; 110 M1 = m->_21; 111 m->_11 = T00 * M0 + T10 * M1; 112 m->_21 = T01 * M0 + T11 * M1; 113 m->_41 += T02 * M0 + T12 * M1; 114 115 M0 = m->_12; 116 M1 = m->_22; 117 m->_12 = T00 * M0 + T10 * M1; 118 m->_22 = T01 * M0 + T11 * M1; 119 m->_42 += T02 * M0 + T12 * M1; 120 } 121 122 #ifdef UPDATE_TX 123 124 void 125 D3DUtils_2DScaleM(D3DMATRIX *m, float sx, float sy) 126 { 127 m->_11 *= sx; 128 m->_22 *= sy; 129 } 130 131 void 132 D3DUtils_2DInvertM(D3DMATRIX *m) 133 { 134 float M11, M21, M41; 135 float M12, M22, M42; 136 float det; 137 138 M11 = m->_11; M21 = m->_21; M41 = m->_41; 139 M12 = m->_12; M22 = m->_22; M42 = m->_42; 140 det = M11 * M22 - M21 * M12; 141 if (fabs(det) <= 0.0000000001f) { 142 memset(m, 0, sizeof(D3DMATRIX)); 143 return; 144 } 145 m->_11 = M22 / det; 146 m->_12 = -M12 / det; 147 m->_21 = -M21 / det; 148 m->_22 = M11 / det; 149 m->_41 = (M21 * M42 - M22 * M41) / det; 150 m->_42 = (M12 * M41 - M11 * M42) / det; 151 } 152 153 void 154 D3DUtils_2DTranslateM(D3DMATRIX *m, float tx, float ty) 155 { 156 m->_41 = tx * m->_11 + ty * m->_21 + m->_41; 157 m->_42 = tx * m->_12 + ty * m->_22 + m->_42; 158 } 159 160 void 161 D3DUtils_2DTransformXY(D3DMATRIX *m, float *px, float *py) 162 { 163 float x = *px; 164 float y = *py; 165 166 *px = x * m->_11 + y * m->_21 + m->_41; 167 *py = x * m->_12 + y * m->_22 + m->_42; 168 } 169 170 void 171 D3DUtils_2DInverseTransformXY(D3DMATRIX *m, float *px, float *py) 172 { 173 float x = *px, y = *py; 174 175 x -= m->_41; 176 y -= m->_42; 177 178 float det = m->_11 * m->_22 - m->_21 * m->_12; 179 if (fabs(det) < 0.0000000001f) { 180 *px = 0.0f; 181 *py = 0.0f; 182 } else { 183 *px = (x * m->_22 - y * m->_21) / det; 184 *py = (y * m->_11 - x * m->_12) / det; 185 } 186 } 187 188 #endif // UPDATE_TX 189 190 static void 191 D3DContext_DisposeShader(jlong programID) 192 { 193 IDirect3DPixelShader9 *shader = 194 (IDirect3DPixelShader9 *)jlong_to_ptr(programID); 195 196 J2dTraceLn(J2D_TRACE_INFO, "D3DContext_DisposeShader"); 197 198 SAFE_RELEASE(shader); 199 } 200 201 // static 202 HRESULT 203 D3DContext::CreateInstance(IDirect3D9 *pd3d9, UINT adapter, D3DContext **ppCtx) 204 { 205 HRESULT res; 206 *ppCtx = new D3DContext(pd3d9, adapter); 207 if (FAILED(res = (*ppCtx)->InitContext())) { 208 delete *ppCtx; 209 *ppCtx = NULL; 210 } 211 return res; 212 } 213 214 D3DContext::D3DContext(IDirect3D9 *pd3d, UINT adapter) 215 { 216 HMONITOR hMon; 217 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::D3DContext"); 218 J2dTraceLn1(J2D_TRACE_VERBOSE, " pd3d=0x%x", pd3d); 219 pd3dObject = pd3d; 220 pd3dDevice = NULL; 221 adapterOrdinal = adapter; 222 hMon = pd3d->GetAdapterMonitor(adapter); 223 if (hMon && Devices::GetInstance()) { 224 screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(hMon); 225 } else { 226 screen = -1; 227 } 228 229 pResourceMgr = NULL; 230 pMaskCache = NULL; 231 pVCacher = NULL; 232 233 pSyncQuery = NULL; 234 pSyncRTRes = NULL; 235 pStateBlock = NULL; 236 237 D3DC_INIT_SHADER_LIST(convolvePrograms, MAX_CONVOLVE); 238 D3DC_INIT_SHADER_LIST(rescalePrograms, MAX_RESCALE); 239 D3DC_INIT_SHADER_LIST(lookupPrograms, MAX_LOOKUP); 240 D3DC_INIT_SHADER_LIST(basicGradPrograms, 4); 241 D3DC_INIT_SHADER_LIST(linearGradPrograms, 8); 242 D3DC_INIT_SHADER_LIST(radialGradPrograms, 8); 243 244 pLCDGlyphCache= NULL; 245 pGrayscaleGlyphCache= NULL; 246 lcdTextProgram = NULL; 247 aaPgramProgram = NULL; 248 249 contextCaps = CAPS_EMPTY; 250 bBeginScenePending = FALSE; 251 252 ZeroMemory(&devCaps, sizeof(D3DCAPS9)); 253 ZeroMemory(&curParams, sizeof(curParams)); 254 255 extraAlpha = 1.0f; 256 } 257 258 void D3DContext::ReleaseDefPoolResources() 259 { 260 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ReleaseDefPoolResources"); 261 262 EndScene(); 263 264 D3DPipelineManager::NotifyAdapterEventListeners(devCaps.AdapterOrdinal, 265 DEVICE_RESET, screen); 266 267 contextCaps = CAPS_EMPTY; 268 269 SAFE_RELEASE(pSyncQuery); 270 SAFE_RELEASE(pStateBlock); 271 272 if (pVCacher != NULL) { 273 pVCacher->ReleaseDefPoolResources(); 274 } 275 if (pMaskCache != NULL) { 276 pMaskCache->ReleaseDefPoolResources(); 277 } 278 if (pLCDGlyphCache != NULL) { 279 pLCDGlyphCache->ReleaseDefPoolResources(); 280 } 281 if (pGrayscaleGlyphCache != NULL) { 282 pGrayscaleGlyphCache->ReleaseDefPoolResources(); 283 } 284 if (pResourceMgr != NULL) { 285 if (pSyncRTRes != NULL) { 286 pResourceMgr->ReleaseResource(pSyncRTRes); 287 pSyncRTRes = NULL; 288 } 289 pResourceMgr->ReleaseDefPoolResources(); 290 } 291 ZeroMemory(lastTexture, sizeof(lastTexture)); 292 ZeroMemory(lastTextureColorState, sizeof(lastTextureColorState)); 293 } 294 295 void D3DContext::ReleaseContextResources() 296 { 297 J2dTraceLn1(J2D_TRACE_INFO, 298 "D3DContext::ReleaseContextResources: pd3dDevice = 0x%x", 299 pd3dDevice); 300 301 ReleaseDefPoolResources(); 302 303 D3DPipelineManager::NotifyAdapterEventListeners(devCaps.AdapterOrdinal, 304 DEVICE_DISPOSED, screen); 305 306 // dispose shader lists 307 ShaderList_Dispose(&convolvePrograms); 308 ShaderList_Dispose(&rescalePrograms); 309 ShaderList_Dispose(&lookupPrograms); 310 ShaderList_Dispose(&basicGradPrograms); 311 ShaderList_Dispose(&linearGradPrograms); 312 ShaderList_Dispose(&radialGradPrograms); 313 314 SAFE_DELETE(pLCDGlyphCache); 315 SAFE_DELETE(pGrayscaleGlyphCache); 316 317 SAFE_RELEASE(lcdTextProgram); 318 SAFE_RELEASE(aaPgramProgram); 319 320 SAFE_DELETE(pVCacher); 321 SAFE_DELETE(pMaskCache); 322 SAFE_DELETE(pResourceMgr); 323 } 324 325 D3DContext::~D3DContext() { 326 J2dTraceLn2(J2D_TRACE_INFO, 327 "~D3DContext: pd3dDevice=0x%x, pd3dObject =0x%x", 328 pd3dDevice, pd3dObject); 329 ReleaseContextResources(); 330 SAFE_RELEASE(pd3dDevice); 331 } 332 333 HRESULT 334 D3DContext::InitDevice(IDirect3DDevice9 *pd3dDevice) 335 { 336 HRESULT res = S_OK; 337 338 pd3dDevice->GetDeviceCaps(&devCaps); 339 340 J2dRlsTraceLn1(J2D_TRACE_INFO, 341 "D3DContext::InitDevice: device %d", adapterOrdinal); 342 343 // disable some of the unneeded and costly d3d functionality 344 pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 345 pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE); 346 pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 347 pd3dDevice->SetRenderState(D3DRS_CLIPPING, FALSE); 348 pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 349 pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, D3DZB_FALSE); 350 pd3dDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); 351 pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); 352 353 // set the default texture addressing mode 354 pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 355 pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 356 357 // REMIND: check supported filters with 358 // IDirect3D9::CheckDeviceFormat with D3DUSAGE_QUERY_FILTER 359 pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 360 pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 361 362 // these states never change 363 pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 364 pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); 365 pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); 366 pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); 367 pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 368 pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); 369 pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT); 370 pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); 371 372 // init the array of latest textures 373 ZeroMemory(lastTexture, sizeof(lastTexture)); 374 ZeroMemory(lastTextureColorState, sizeof(lastTextureColorState)); 375 376 opState = STATE_CHANGE; 377 378 if (pResourceMgr == NULL) { 379 res = D3DResourceManager::CreateInstance(this, &pResourceMgr); 380 } else { 381 res = pResourceMgr->Init(this); 382 } 383 RETURN_STATUS_IF_FAILED(res); 384 385 if (pVCacher == NULL) { 386 res = D3DVertexCacher::CreateInstance(this, &pVCacher); 387 } else { 388 res = pVCacher->Init(this); 389 } 390 RETURN_STATUS_IF_FAILED(res); 391 392 if (pMaskCache == NULL) { 393 res = D3DMaskCache::CreateInstance(this, &pMaskCache); 394 } else{ 395 res = pMaskCache->Init(this); 396 } 397 RETURN_STATUS_IF_FAILED(res); 398 399 if (pLCDGlyphCache != NULL) { 400 if (FAILED(res = pLCDGlyphCache->Init(this))) { 401 // we can live without the cache 402 SAFE_DELETE(pLCDGlyphCache); 403 res = S_OK; 404 } 405 } 406 407 if (pGrayscaleGlyphCache != NULL) { 408 if (FAILED(res = pGrayscaleGlyphCache->Init(this))) { 409 // we can live without the cache 410 SAFE_DELETE(pGrayscaleGlyphCache); 411 res = S_OK; 412 } 413 } 414 415 D3DMATRIX tx; 416 D3DUtils_SetIdentityMatrix(&tx); 417 pd3dDevice->SetTransform(D3DTS_WORLD, &tx); 418 bIsIdentityTx = TRUE; 419 420 if (pSyncQuery == NULL) { 421 // this is allowed to fail, do not propagate the error 422 if (FAILED(pd3dDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pSyncQuery))) { 423 J2dRlsTraceLn(J2D_TRACE_WARNING, 424 "D3DContext::InitDevice: sync query not available"); 425 pSyncQuery = NULL; 426 } 427 } 428 if (pSyncRTRes == NULL) { 429 D3DFORMAT format; 430 if (FAILED(GetResourceManager()-> 431 CreateRTSurface(32, 32, TRUE, TRUE, &format, &pSyncRTRes))) { 432 J2dRlsTraceLn(J2D_TRACE_WARNING, 433 "D3DContext::InitDevice: " 434 "error creating sync surface"); 435 } 436 } 437 438 bBeginScenePending = FALSE; 439 440 J2dRlsTraceLn1(J2D_TRACE_INFO, 441 "D3DContext::InitDefice: successfully initialized device %d", 442 adapterOrdinal); 443 444 return res; 445 } 446 447 HRESULT 448 D3DContext::CheckAndResetDevice() 449 { 450 HRESULT res = E_FAIL; 451 452 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::CheckAndResetDevice"); 453 454 if (pd3dDevice != NULL) { 455 if (FAILED(res = pd3dDevice->TestCooperativeLevel())) { 456 if (res == D3DERR_DEVICELOST) { 457 J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d is still lost", 458 adapterOrdinal); 459 // nothing to be done here, wait for D3DERR_DEVICENOTRESET 460 return res; 461 } else if (res == D3DERR_DEVICENOTRESET) { 462 J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d needs to be reset", 463 adapterOrdinal); 464 res = ResetContext(); 465 } else { 466 // some unexpected error 467 DebugPrintD3DError(res, "D3DContext::CheckAndResetDevice: "\ 468 "unknown error %x from TestCooperativeLevel"); 469 } 470 } else { 471 J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d is not lost", 472 adapterOrdinal); 473 } 474 } else { 475 J2dTraceLn(J2D_TRACE_VERBOSE, " null device"); 476 } 477 return res; 478 } 479 480 HRESULT 481 D3DContext::ResetContext() 482 { 483 HRESULT res = E_FAIL; 484 485 J2dRlsTraceLn(J2D_TRACE_INFO, "D3DContext::ResetContext"); 486 if (pd3dDevice != NULL) { 487 D3DPRESENT_PARAMETERS newParams; 488 489 newParams = curParams; 490 491 if (newParams.Windowed) { 492 // reset to the current display mode if we're windowed, 493 // otherwise to the display mode we were in when the device 494 // was lost 495 newParams.BackBufferFormat = D3DFMT_UNKNOWN; 496 newParams.FullScreen_RefreshRateInHz = 0; 497 newParams.BackBufferWidth = 0; 498 newParams.BackBufferHeight = 0; 499 } 500 res = ConfigureContext(&newParams); 501 } 502 return res; 503 } 504 505 HRESULT 506 D3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams) 507 { 508 J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DContext::ConfigureContext device %d", 509 adapterOrdinal); 510 HRESULT res = S_OK; 511 D3DFORMAT stencilFormat; 512 HWND focusHWND = D3DPipelineManager::GetInstance()->GetCurrentFocusWindow(); 513 D3DDEVTYPE devType = D3DPipelineManager::GetInstance()->GetDeviceType(); 514 // this is needed so that we can find the stencil buffer format 515 if (pNewParams->BackBufferFormat == D3DFMT_UNKNOWN) { 516 D3DDISPLAYMODE dm; 517 518 pd3dObject->GetAdapterDisplayMode(adapterOrdinal, &dm); 519 pNewParams->BackBufferFormat = dm.Format; 520 } 521 522 stencilFormat = 523 D3DPipelineManager::GetInstance()->GetMatchingDepthStencilFormat( 524 adapterOrdinal, 525 pNewParams->BackBufferFormat, pNewParams->BackBufferFormat); 526 527 pNewParams->EnableAutoDepthStencil = TRUE; 528 pNewParams->AutoDepthStencilFormat = stencilFormat; 529 530 // do not set device window in the windowed mode, we use additional 531 // swap chains for rendering, the default chain is not used. otherwise 532 // our scratch focus window will be made visible 533 J2dTraceLn1(J2D_TRACE_VERBOSE, " windowed=%d",pNewParams->Windowed); 534 if (pNewParams->Windowed) { 535 pNewParams->hDeviceWindow = (HWND)0; 536 } 537 538 // The focus window may change when we're entering/exiting the full-screen 539 // mode. It may either be set to the default focus window (when there are 540 // no more devices in fs mode), or to fs window for another device 541 // in fs mode. See D3DPipelineManager::GetCurrentFocusWindow. 542 if (pd3dDevice != NULL) { 543 D3DDEVICE_CREATION_PARAMETERS cParams; 544 pd3dDevice->GetCreationParameters(&cParams); 545 if (cParams.hFocusWindow != focusHWND) { 546 J2dTraceLn(J2D_TRACE_VERBOSE, 547 " focus window changed, need to recreate the device"); 548 549 // if fs -> windowed, first exit fs, then recreate, otherwise 550 // the screen might be left in a different display mode 551 if (pNewParams->Windowed && !curParams.Windowed) { 552 J2dTraceLn(J2D_TRACE_VERBOSE, 553 " exiting full-screen mode, reset the device"); 554 curParams.Windowed = FALSE; 555 ReleaseDefPoolResources(); 556 res = pd3dDevice->Reset(&curParams); 557 558 if (FAILED(res)) { 559 DebugPrintD3DError(res, "D3DContext::ConfigureContext: "\ 560 "cound not reset the device"); 561 } 562 } 563 564 // note that here we should release all device resources, not only 565 // thos in the default pool since the device is released 566 ReleaseContextResources(); 567 SAFE_RELEASE(pd3dDevice); 568 } 569 } 570 571 if (pd3dDevice != NULL) { 572 J2dTraceLn(J2D_TRACE_VERBOSE, " resetting the device"); 573 574 ReleaseDefPoolResources(); 575 576 if (pNewParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE && 577 !IsImmediateIntervalSupported()) 578 { 579 pNewParams->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 580 } 581 582 res = pd3dDevice->Reset(pNewParams); 583 if (FAILED(res)) { 584 DebugPrintD3DError(res, 585 "D3DContext::ConfigureContext: cound not reset the device"); 586 return res; 587 } 588 J2dRlsTraceLn1(J2D_TRACE_INFO, 589 "D3DContext::ConfigureContext: successfully reset device: %d", 590 adapterOrdinal); 591 } else { 592 D3DCAPS9 d3dCaps; 593 DWORD dwBehaviorFlags; 594 595 J2dTraceLn(J2D_TRACE_VERBOSE, " creating a new device"); 596 597 if (FAILED(res = pd3dObject->GetDeviceCaps(adapterOrdinal, 598 devType, &d3dCaps))) 599 { 600 DebugPrintD3DError(res, 601 "D3DContext::ConfigureContext: failed to get caps"); 602 return res; 603 } 604 605 if (pNewParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE && 606 !(d3dCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)) 607 { 608 pNewParams->PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 609 } 610 611 // not preserving fpu control word could cause issues (4860749) 612 dwBehaviorFlags = D3DCREATE_FPU_PRESERVE; 613 614 J2dRlsTrace(J2D_TRACE_VERBOSE, 615 "[V] dwBehaviorFlags=D3DCREATE_FPU_PRESERVE|"); 616 if (d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { 617 J2dRlsTrace(J2D_TRACE_VERBOSE, 618 "D3DCREATE_HARDWARE_VERTEXPROCESSING"); 619 dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; 620 } else { 621 J2dRlsTrace(J2D_TRACE_VERBOSE, 622 "D3DCREATE_SOFTWARE_VERTEXPROCESSING"); 623 dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; 624 } 625 // Handling focus changes by ourselves proved to be problematic, 626 // so we're reverting back to D3D handling 627 // dwBehaviorFlags |= D3DCREATE_NOWINDOWCHANGES; 628 J2dRlsTrace(J2D_TRACE_VERBOSE,"\n"); 629 630 if (FAILED(res = pd3dObject->CreateDevice(adapterOrdinal, devType, 631 focusHWND, 632 dwBehaviorFlags, 633 pNewParams, &pd3dDevice))) 634 { 635 DebugPrintD3DError(res, 636 "D3DContext::ConfigureContext: error creating d3d device"); 637 return res; 638 } 639 J2dRlsTraceLn1(J2D_TRACE_INFO, 640 "D3DContext::ConfigureContext: successfully created device: %d", 641 adapterOrdinal); 642 bIsHWRasterizer = (devType == D3DDEVTYPE_HAL); 643 } 644 645 curParams = *pNewParams; 646 // during the creation of the device d3d modifies this field, we reset 647 // it back to 0 648 curParams.Flags = 0; 649 650 if (FAILED(res = InitDevice(pd3dDevice))) { 651 ReleaseContextResources(); 652 return res; 653 } 654 655 res = InitContextCaps(); 656 657 return res; 658 } 659 660 HRESULT 661 D3DContext::InitContext() 662 { 663 J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DContext::InitContext device %d", 664 adapterOrdinal); 665 666 D3DPRESENT_PARAMETERS params; 667 ZeroMemory(¶ms, sizeof(D3DPRESENT_PARAMETERS)); 668 669 params.hDeviceWindow = 0; 670 params.Windowed = TRUE; 671 params.BackBufferCount = 1; 672 params.BackBufferFormat = D3DFMT_UNKNOWN; 673 params.SwapEffect = D3DSWAPEFFECT_DISCARD; 674 params.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; 675 676 return ConfigureContext(¶ms); 677 } 678 679 HRESULT 680 D3DContext::Sync() 681 { 682 HRESULT res = S_OK; 683 684 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::Sync"); 685 686 if (pSyncQuery != NULL) { 687 J2dTrace(J2D_TRACE_VERBOSE, " flushing the device queue.."); 688 while (S_FALSE == 689 (res = pSyncQuery->GetData(NULL, 0, D3DGETDATA_FLUSH))) ; 690 J2dTrace(J2D_TRACE_VERBOSE, ".. done\n"); 691 } 692 if (pSyncRTRes != NULL) { 693 D3DLOCKED_RECT lr; 694 IDirect3DSurface9 *pSurface = pSyncRTRes->GetSurface(); 695 if (SUCCEEDED(pSurface->LockRect(&lr, NULL, D3DLOCK_NOSYSLOCK))) { 696 pSurface->UnlockRect(); 697 } 698 } 699 return res; 700 } 701 702 HRESULT 703 D3DContext::SaveState() 704 { 705 HRESULT res; 706 707 RETURN_STATUS_IF_NULL(pd3dDevice, S_OK); 708 709 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SaveState"); 710 711 FlushVertexQueue(); 712 UpdateState(STATE_CHANGE); 713 714 if (pStateBlock != NULL) { 715 J2dTraceLn(J2D_TRACE_WARNING, 716 "D3DContext::SaveState: existing state block!"); 717 SAFE_RELEASE(pStateBlock); 718 } 719 720 if (SUCCEEDED(res = 721 pd3dDevice->CreateStateBlock(D3DSBT_ALL, &pStateBlock))) 722 { 723 J2dTraceLn(J2D_TRACE_VERBOSE, " created state block"); 724 } else { 725 J2dTraceLn(J2D_TRACE_WARNING, 726 "D3DContext::SaveState: failed to create state block"); 727 } 728 ZeroMemory(lastTexture, sizeof(lastTexture)); 729 730 return res; 731 } 732 733 HRESULT 734 D3DContext::RestoreState() 735 { 736 HRESULT res = S_OK; 737 738 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::RestoreState"); 739 740 FlushVertexQueue(); 741 UpdateState(STATE_CHANGE); 742 743 if (pStateBlock != NULL) { 744 if (SUCCEEDED(res = pStateBlock->Apply())) { 745 J2dTraceLn(J2D_TRACE_VERBOSE, " restored device state"); 746 } else { 747 J2dTraceLn(J2D_TRACE_WARNING, 748 "D3DContext::RestoreState: failed to restore state"); 749 } 750 SAFE_RELEASE(pStateBlock); 751 } else { 752 J2dTraceLn(J2D_TRACE_WARNING, 753 "D3DContext::RestoreState: empty state block!"); 754 } 755 ZeroMemory(lastTexture, sizeof(lastTexture)); 756 757 return res; 758 } 759 760 #define POINT_FILTER_CAP (D3DPTFILTERCAPS_MAGFPOINT|D3DPTFILTERCAPS_MINFPOINT) 761 #define LINEAR_FILTER_CAP (D3DPTFILTERCAPS_MAGFLINEAR|D3DPTFILTERCAPS_MINFLINEAR) 762 763 BOOL 764 D3DContext::IsStretchRectFilteringSupported(D3DTEXTUREFILTERTYPE fType) 765 { 766 if (fType == D3DTEXF_POINT) { 767 return ((devCaps.StretchRectFilterCaps & POINT_FILTER_CAP) != 0); 768 } 769 if (fType == D3DTEXF_LINEAR) { 770 return ((devCaps.StretchRectFilterCaps & LINEAR_FILTER_CAP) != 0); 771 } 772 return FALSE; 773 } 774 775 BOOL 776 D3DContext::IsTextureFilteringSupported(D3DTEXTUREFILTERTYPE fType) 777 { 778 if (fType == D3DTEXF_POINT) { 779 return ((devCaps.TextureFilterCaps & POINT_FILTER_CAP) != 0); 780 } 781 if (fType == D3DTEXF_LINEAR) { 782 return ((devCaps.TextureFilterCaps & LINEAR_FILTER_CAP) != 0); 783 } 784 return FALSE; 785 } 786 787 BOOL 788 D3DContext::IsTextureFormatSupported(D3DFORMAT format, DWORD usage) 789 { 790 HRESULT hr = pd3dObject->CheckDeviceFormat(adapterOrdinal, 791 devCaps.DeviceType, 792 curParams.BackBufferFormat, 793 usage, 794 D3DRTYPE_TEXTURE, 795 format); 796 return SUCCEEDED( hr ); 797 } 798 799 BOOL 800 D3DContext::IsDepthStencilBufferOk(D3DSURFACE_DESC *pTargetDesc) 801 { 802 IDirect3DSurface9 *pStencil; 803 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::IsDepthStencilBufferOk"); 804 805 if (SUCCEEDED(pd3dDevice->GetDepthStencilSurface(&pStencil))) { 806 D3DSURFACE_DESC descStencil; 807 pStencil->GetDesc(&descStencil); 808 pStencil->Release(); 809 810 D3DDISPLAYMODE dm; 811 return 812 (SUCCEEDED(pd3dDevice->GetDisplayMode(0, &dm)) && 813 pTargetDesc->Width <= descStencil.Width && 814 pTargetDesc->Height <= descStencil.Height && 815 SUCCEEDED(pd3dObject->CheckDepthStencilMatch( 816 adapterOrdinal, 817 devCaps.DeviceType, 818 dm.Format, pTargetDesc->Format, 819 descStencil.Format))); 820 } 821 J2dTraceLn(J2D_TRACE_VERBOSE, 822 " current stencil buffer is not compatible with new Render Target"); 823 824 return false; 825 } 826 827 828 829 HRESULT 830 D3DContext::InitDepthStencilBuffer(D3DSURFACE_DESC *pTargetDesc) 831 { 832 HRESULT res; 833 IDirect3DSurface9 *pBB; 834 D3DDISPLAYMODE dm; 835 836 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::InitDepthStencilBuffer"); 837 838 if (FAILED(res = pd3dDevice->GetDisplayMode(0, &dm))) { 839 return res; 840 } 841 842 D3DFORMAT newFormat = 843 D3DPipelineManager::GetInstance()->GetMatchingDepthStencilFormat( 844 adapterOrdinal, dm.Format, pTargetDesc->Format); 845 846 res = pd3dDevice->CreateDepthStencilSurface( 847 pTargetDesc->Width, pTargetDesc->Height, 848 newFormat, D3DMULTISAMPLE_NONE, 0, false, &pBB, 0); 849 if (SUCCEEDED(res)) { 850 res = pd3dDevice->SetDepthStencilSurface(pBB); 851 pBB->Release(); 852 } 853 854 return res; 855 } 856 857 858 HRESULT 859 D3DContext::SetRenderTarget(IDirect3DSurface9 *pSurface) 860 { 861 static D3DMATRIX tx; 862 HRESULT res; 863 D3DSURFACE_DESC descNew; 864 IDirect3DSurface9 *pCurrentTarget; 865 866 J2dTraceLn1(J2D_TRACE_INFO, 867 "D3DContext::SetRenderTarget: pSurface=0x%x", 868 pSurface); 869 870 RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); 871 RETURN_STATUS_IF_NULL(pSurface, E_FAIL); 872 873 pSurface->GetDesc(&descNew); 874 875 if (SUCCEEDED(res = pd3dDevice->GetRenderTarget(0, &pCurrentTarget))) { 876 if (pCurrentTarget != pSurface) { 877 FlushVertexQueue(); 878 if (FAILED(res = pd3dDevice->SetRenderTarget(0, pSurface))) { 879 DebugPrintD3DError(res, "D3DContext::SetRenderTarget: "\ 880 "error setting render target"); 881 SAFE_RELEASE(pCurrentTarget); 882 return res; 883 } 884 885 if (!IsDepthStencilBufferOk(&descNew)) { 886 if (FAILED(res = InitDepthStencilBuffer(&descNew))) { 887 SAFE_RELEASE(pCurrentTarget); 888 return res; 889 } 890 } 891 } 892 SAFE_RELEASE(pCurrentTarget); 893 } 894 // we set the transform even if the render target didn't change; 895 // this is because in some cases (fs mode) we use the default SwapChain of 896 // the device, and its render target will be the same as the device's, and 897 // we have to set the matrix correctly. This shouldn't be a performance 898 // issue as render target changes are relatively rare 899 D3DUtils_SetOrthoMatrixOffCenterLH(&tx, 900 (float)descNew.Width, 901 (float)descNew.Height); 902 pd3dDevice->SetTransform(D3DTS_PROJECTION, &tx); 903 904 J2dTraceLn1(J2D_TRACE_VERBOSE, " current render target=0x%x", pSurface); 905 return res; 906 } 907 908 HRESULT 909 D3DContext::ResetTransform() 910 { 911 HRESULT res = S_OK; 912 D3DMATRIX tx; 913 914 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ResetTransform"); 915 if (pd3dDevice == NULL) { 916 return E_FAIL; 917 } 918 919 // no need for state change, just flush the queue 920 FlushVertexQueue(); 921 922 D3DUtils_SetIdentityMatrix(&tx); 923 if (FAILED(res = pd3dDevice->SetTransform(D3DTS_WORLD, &tx))) { 924 DebugPrintD3DError(res, "D3DContext::SetTransform failed"); 925 } 926 bIsIdentityTx = TRUE; 927 return res; 928 } 929 930 HRESULT 931 D3DContext::SetTransform(jdouble m00, jdouble m10, 932 jdouble m01, jdouble m11, 933 jdouble m02, jdouble m12) 934 { 935 HRESULT res = S_OK; 936 D3DMATRIX tx, tx1; 937 938 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetTransform"); 939 if (pd3dDevice == NULL) { 940 return E_FAIL; 941 } 942 943 // no need for state change, just flush the queue 944 FlushVertexQueue(); 945 946 // In order to correctly map texels to pixels we need to 947 // adjust geometry by -0.5f in the transformed space. 948 // In order to do that we first create a translated matrix 949 // and then concatenate it with the world transform. 950 // 951 // Note that we only use non-id transform with DrawTexture, 952 // the rest is rendered pre-transformed. 953 // 954 // The identity transform for textures is handled in 955 // D3DVertexCacher::DrawTexture() because shifting by -0.5 for id 956 // transform breaks lines rendering. 957 958 ZeroMemory(&tx1, sizeof(D3DMATRIX)); 959 960 tx1._11 = (float)m00; 961 tx1._12 = (float)m10; 962 tx1._21 = (float)m01; 963 tx1._22 = (float)m11; 964 tx1._41 = (float)m02; 965 tx1._42 = (float)m12; 966 967 tx1._33 = 1.0f; 968 tx1._44 = 1.0f; 969 970 D3DUtils_SetIdentityMatrix(&tx); 971 tx._41 = -0.5f; 972 tx._42 = -0.5f; 973 D3DUtils_2DConcatenateM(&tx, &tx1); 974 975 J2dTraceLn4(J2D_TRACE_VERBOSE, 976 " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14); 977 J2dTraceLn4(J2D_TRACE_VERBOSE, 978 " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24); 979 J2dTraceLn4(J2D_TRACE_VERBOSE, 980 " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34); 981 J2dTraceLn4(J2D_TRACE_VERBOSE, 982 " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44); 983 if (FAILED(res = pd3dDevice->SetTransform(D3DTS_WORLD, &tx))) { 984 DebugPrintD3DError(res, "D3DContext::SetTransform failed"); 985 } 986 bIsIdentityTx = FALSE; 987 988 return res; 989 } 990 991 HRESULT 992 D3DContext::SetRectClip(int x1, int y1, int x2, int y2) 993 { 994 HRESULT res = S_OK; 995 D3DSURFACE_DESC desc; 996 IDirect3DSurface9 *pCurrentTarget; 997 998 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetRectClip"); 999 J2dTraceLn4(J2D_TRACE_VERBOSE, 1000 " x1=%-4d y1=%-4d x2=%-4d y2=%-4d", 1001 x1, y1, x2, y2); 1002 1003 RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); 1004 1005 // no need for state change, just flush the queue 1006 FlushVertexQueue(); 1007 1008 pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 1009 1010 res = pd3dDevice->GetRenderTarget(0, &pCurrentTarget); 1011 RETURN_STATUS_IF_FAILED(res); 1012 1013 pCurrentTarget->GetDesc(&desc); 1014 SAFE_RELEASE(pCurrentTarget); 1015 1016 if (x1 <= 0 && y1 <= 0 && 1017 (UINT)x2 >= desc.Width && (UINT)y2 >= desc.Height) 1018 { 1019 J2dTraceLn(J2D_TRACE_VERBOSE, 1020 " disabling clip (== render target dimensions)"); 1021 return pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 1022 } 1023 1024 // clip to the dimensions of the target surface, otherwise 1025 // SetScissorRect will fail 1026 if (x1 < 0) x1 = 0; 1027 if (y1 < 0) y1 = 0; 1028 if ((UINT)x2 > desc.Width) x2 = desc.Width; 1029 if ((UINT)y2 > desc.Height) y2 = desc.Height; 1030 if (x1 > x2) x2 = x1 = 0; 1031 if (y1 > y2) y2 = y1 = 0; 1032 RECT newRect = { x1, y1, x2, y2 }; 1033 if (SUCCEEDED(res = pd3dDevice->SetScissorRect(&newRect))) { 1034 res = pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 1035 } else { 1036 DebugPrintD3DError(res, "Error setting scissor rect"); 1037 J2dRlsTraceLn4(J2D_TRACE_ERROR, 1038 " x1=%-4d y1=%-4d x2=%-4d y2=%-4d", 1039 x1, y1, x2, y2); 1040 } 1041 1042 return res; 1043 } 1044 1045 HRESULT 1046 D3DContext::ResetClip() 1047 { 1048 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ResetClip"); 1049 // no need for state change, just flush the queue 1050 FlushVertexQueue(); 1051 pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 1052 return pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 1053 } 1054 1055 ClipType 1056 D3DContext::GetClipType() 1057 { 1058 // REMIND: this method could be optimized: we could keep the 1059 // clip state around when re/setting the clip instead of asking 1060 // every time. 1061 DWORD zEnabled = 0; 1062 DWORD stEnabled = 0; 1063 1064 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::GetClipType"); 1065 pd3dDevice->GetRenderState(D3DRS_SCISSORTESTENABLE, &stEnabled); 1066 if (stEnabled) { 1067 return CLIP_RECT; 1068 } 1069 pd3dDevice->GetRenderState(D3DRS_ZENABLE, &zEnabled); 1070 if (zEnabled) { 1071 return CLIP_SHAPE; 1072 } 1073 return CLIP_NONE; 1074 } 1075 1076 1077 /** 1078 * This method assumes that ::SetRenderTarget has already 1079 * been called. SetRenderTarget creates and attaches a 1080 * depth buffer to the target surface prior to setting it 1081 * as target surface to the device. 1082 */ 1083 DWORD dwAlphaSt, dwSrcBlendSt, dwDestBlendSt; 1084 D3DMATRIX tx, idTx; 1085 1086 HRESULT 1087 D3DContext::BeginShapeClip() 1088 { 1089 HRESULT res = S_OK; 1090 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::BeginShapeClip"); 1091 1092 UpdateState(STATE_CHANGE); 1093 1094 pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); 1095 1096 // save alpha blending state 1097 pd3dDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &dwAlphaSt); 1098 pd3dDevice->GetRenderState(D3DRS_SRCBLEND, &dwSrcBlendSt); 1099 pd3dDevice->GetRenderState(D3DRS_DESTBLEND, &dwDestBlendSt); 1100 1101 pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 1102 pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); 1103 pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); 1104 1105 pd3dDevice->GetTransform(D3DTS_WORLD, &tx); 1106 D3DUtils_SetIdentityMatrix(&idTx); 1107 // translate the clip spans by 1.0f in z direction so that the 1108 // clip spans are rendered to the z buffer 1109 idTx._43 = 1.0f; 1110 pd3dDevice->SetTransform(D3DTS_WORLD, &idTx); 1111 1112 // The depth buffer is first cleared with zeroes, which is the farthest 1113 // plane from the viewer (our projection matrix is an inversed orthogonal 1114 // transform). 1115 // To set the clip we'll render the clip spans with Z coordinates of 1.0f 1116 // (the closest to the viewer). Since all rendering primitives 1117 // have their vertices' Z coordinate set to 0.0, they will effectively be 1118 // clipped because the Z depth test for them will fail (vertex with 1.0 1119 // depth is closer than the one with 0.0f) 1120 pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 1121 pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); 1122 pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); 1123 pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0L, 0.0f, 0x0L); 1124 1125 //res = BeginScene(STATE_SHAPE_CLIPOP); 1126 1127 return res; 1128 } 1129 1130 HRESULT 1131 D3DContext::EndShapeClip() 1132 { 1133 HRESULT res; 1134 1135 // no need for state change, just flush the queue 1136 res = FlushVertexQueue(); 1137 1138 // restore alpha blending state 1139 pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, dwAlphaSt); 1140 pd3dDevice->SetRenderState(D3DRS_SRCBLEND, dwSrcBlendSt); 1141 pd3dDevice->SetRenderState(D3DRS_DESTBLEND, dwDestBlendSt); 1142 1143 // resore the transform 1144 pd3dDevice->SetTransform(D3DTS_WORLD, &tx); 1145 1146 // Enable the depth buffer. 1147 // We disable further updates to the depth buffer: it should only 1148 // be updated in SetClip method. 1149 pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); 1150 pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); 1151 1152 return res; 1153 } 1154 1155 HRESULT 1156 D3DContext::UploadTileToTexture(D3DResource *pTextureRes, void *pixels, 1157 jint dstx, jint dsty, 1158 jint srcx, jint srcy, 1159 jint srcWidth, jint srcHeight, 1160 jint srcStride, 1161 TileFormat srcFormat, 1162 jint *pPixelsTouchedL, 1163 jint* pPixelsTouchedR) 1164 { 1165 #ifndef PtrAddBytes 1166 #define PtrAddBytes(p, b) ((void *) (((intptr_t) (p)) + (b))) 1167 #define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, (y)*(yinc) + (x)*(xinc)) 1168 #endif // PtrAddBytes 1169 1170 HRESULT res = S_OK; 1171 IDirect3DTexture9 *pTexture = pTextureRes->GetTexture(); 1172 D3DSURFACE_DESC *pDesc = pTextureRes->GetDesc(); 1173 RECT r = { dstx, dsty, dstx+srcWidth, dsty+srcHeight }; 1174 RECT *pR = &r; 1175 D3DLOCKED_RECT lockedRect; 1176 DWORD dwLockFlags = D3DLOCK_NOSYSLOCK; 1177 // these are only counted for LCD glyph uploads 1178 jint pixelsTouchedL = 0, pixelsTouchedR = 0; 1179 1180 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::UploadTileToTexture"); 1181 J2dTraceLn4(J2D_TRACE_VERBOSE, 1182 " rect={%-4d, %-4d, %-4d, %-4d}", 1183 r.left, r.top, r.right, r.bottom); 1184 1185 if (pDesc->Usage == D3DUSAGE_DYNAMIC) { 1186 // it is safe to lock with discard because we don't care about the 1187 // contents of dynamic textures and dstx,dsty for this case is 1188 // always 0,0 because we are uploading into a tile texture 1189 dwLockFlags |= D3DLOCK_DISCARD; 1190 pR = NULL; 1191 } 1192 1193 if (FAILED(res = pTexture->LockRect(0, &lockedRect, pR, dwLockFlags))) { 1194 DebugPrintD3DError(res, 1195 "D3DContext::UploadImageToTexture: could "\ 1196 "not lock texture"); 1197 return res; 1198 } 1199 1200 if (srcFormat == TILEFMT_1BYTE_ALPHA) { 1201 // either a MaskFill tile, or a grayscale glyph 1202 if (pDesc->Format == D3DFMT_A8) { 1203 void *pSrcPixels = PtrCoord(pixels, srcx, 1, srcy, srcStride); 1204 void *pDstPixels = lockedRect.pBits; 1205 do { 1206 memcpy(pDstPixels, pSrcPixels, srcWidth); 1207 pSrcPixels = PtrAddBytes(pSrcPixels, srcStride); 1208 pDstPixels = PtrAddBytes(pDstPixels, lockedRect.Pitch); 1209 } while (--srcHeight > 0); 1210 } 1211 else if (pDesc->Format == D3DFMT_A8R8G8B8) { 1212 jubyte *pSrcPixels = (jubyte*) 1213 PtrCoord(pixels, srcx, 1, srcy, srcStride); 1214 jint *pDstPixels = (jint*)lockedRect.pBits; 1215 for (int yy = 0; yy < srcHeight; yy++) { 1216 for (int xx = 0; xx < srcWidth; xx++) { 1217 // only need to set the alpha channel (the D3D texture 1218 // state will be setup in this case to replicate the 1219 // alpha channel as needed) 1220 pDstPixels[xx] = pSrcPixels[xx] << 24; 1221 } 1222 pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride); 1223 pDstPixels = (jint*)PtrAddBytes(pDstPixels, lockedRect.Pitch); 1224 } 1225 } 1226 } else if (srcFormat == TILEFMT_3BYTE_RGB) { 1227 // LCD glyph with RGB order 1228 if (pDesc->Format == D3DFMT_R8G8B8) { 1229 jubyte *pSrcPixels = (jubyte*) 1230 PtrCoord(pixels, srcx, 3, srcy, srcStride); 1231 jubyte *pDstPixels = (jubyte*)lockedRect.pBits; 1232 for (int yy = 0; yy < srcHeight; yy++) { 1233 for (int xx = 0; xx < srcWidth*3; xx+=3) { 1234 // alpha channel is ignored in this case 1235 // (note that this is backwards from what one might 1236 // expect; it appears that D3DFMT_R8G8B8 is actually 1237 // laid out in BGR order in memory) 1238 pDstPixels[xx+0] = pSrcPixels[xx+2]; 1239 pDstPixels[xx+1] = pSrcPixels[xx+1]; 1240 pDstPixels[xx+2] = pSrcPixels[xx+0]; 1241 } 1242 pixelsTouchedL += 1243 (pDstPixels[0+0]|pDstPixels[0+1]|pDstPixels[0+2]) ? 1 : 0; 1244 jint i = 3*(srcWidth-1); 1245 pixelsTouchedR += 1246 (pDstPixels[i+0]|pDstPixels[i+1]|pDstPixels[i+2]) ? 1 : 0; 1247 1248 pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride); 1249 pDstPixels = (jubyte*)PtrAddBytes(pDstPixels, lockedRect.Pitch); 1250 } 1251 } 1252 else if (pDesc->Format == D3DFMT_A8R8G8B8) { 1253 jubyte *pSrcPixels = (jubyte*) 1254 PtrCoord(pixels, srcx, 3, srcy, srcStride); 1255 jint *pDstPixels = (jint*)lockedRect.pBits; 1256 for (int yy = 0; yy < srcHeight; yy++) { 1257 for (int dx = 0, sx = 0; dx < srcWidth; dx++, sx+=3) { 1258 // alpha channel is ignored in this case 1259 jubyte r = pSrcPixels[sx+0]; 1260 jubyte g = pSrcPixels[sx+1]; 1261 jubyte b = pSrcPixels[sx+2]; 1262 pDstPixels[dx] = (r << 16) | (g << 8) | (b); 1263 } 1264 pixelsTouchedL += (pDstPixels[0] ? 1 : 0); 1265 pixelsTouchedR += (pDstPixels[srcWidth-1] ? 1 : 0); 1266 1267 pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride); 1268 pDstPixels = (jint*)PtrAddBytes(pDstPixels, lockedRect.Pitch); 1269 } 1270 } 1271 } else if (srcFormat == TILEFMT_3BYTE_BGR) { 1272 // LCD glyph with BGR order 1273 if (pDesc->Format == D3DFMT_R8G8B8) { 1274 void *pSrcPixels = PtrCoord(pixels, srcx, 3, srcy, srcStride); 1275 void *pDstPixels = lockedRect.pBits; 1276 jubyte *pbDst; 1277 do { 1278 // alpha channel is ignored in this case 1279 // (note that this is backwards from what one might 1280 // expect; it appears that D3DFMT_R8G8B8 is actually 1281 // laid out in BGR order in memory) 1282 memcpy(pDstPixels, pSrcPixels, srcWidth * 3); 1283 1284 pbDst = (jubyte*)pDstPixels; 1285 pixelsTouchedL +=(pbDst[0+0]|pbDst[0+1]|pbDst[0+2]) ? 1 : 0; 1286 jint i = 3*(srcWidth-1); 1287 pixelsTouchedR +=(pbDst[i+0]|pbDst[i+1]|pbDst[i+2]) ? 1 : 0; 1288 1289 pSrcPixels = PtrAddBytes(pSrcPixels, srcStride); 1290 pDstPixels = PtrAddBytes(pDstPixels, lockedRect.Pitch); 1291 } while (--srcHeight > 0); 1292 } 1293 else if (pDesc->Format == D3DFMT_A8R8G8B8) { 1294 jubyte *pSrcPixels = (jubyte*) 1295 PtrCoord(pixels, srcx, 3, srcy, srcStride); 1296 jint *pDstPixels = (jint*)lockedRect.pBits; 1297 for (int yy = 0; yy < srcHeight; yy++) { 1298 for (int dx = 0, sx = 0; dx < srcWidth; dx++, sx+=3) { 1299 // alpha channel is ignored in this case 1300 jubyte b = pSrcPixels[sx+0]; 1301 jubyte g = pSrcPixels[sx+1]; 1302 jubyte r = pSrcPixels[sx+2]; 1303 pDstPixels[dx] = (r << 16) | (g << 8) | (b); 1304 } 1305 pixelsTouchedL += (pDstPixels[0] ? 1 : 0); 1306 pixelsTouchedR += (pDstPixels[srcWidth-1] ? 1 : 0); 1307 1308 pSrcPixels = (jubyte*)PtrAddBytes(pSrcPixels, srcStride); 1309 pDstPixels = (jint*)PtrAddBytes(pDstPixels, lockedRect.Pitch); 1310 } 1311 } 1312 } else if (srcFormat == TILEFMT_4BYTE_ARGB_PRE) { 1313 // MaskBlit tile 1314 if (pDesc->Format == D3DFMT_A8R8G8B8) { 1315 void *pSrcPixels = PtrCoord(pixels, srcx, 4, srcy, srcStride); 1316 void *pDstPixels = lockedRect.pBits; 1317 do { 1318 memcpy(pDstPixels, pSrcPixels, srcWidth * 4); 1319 pSrcPixels = PtrAddBytes(pSrcPixels, srcStride); 1320 pDstPixels = PtrAddBytes(pDstPixels, lockedRect.Pitch); 1321 } while (--srcHeight > 0); 1322 } 1323 } else { 1324 // should not happen, no-op just in case... 1325 } 1326 1327 if (pPixelsTouchedL) { 1328 *pPixelsTouchedL = pixelsTouchedL; 1329 } 1330 if (pPixelsTouchedR) { 1331 *pPixelsTouchedR = pixelsTouchedR; 1332 } 1333 1334 return pTexture->UnlockRect(0); 1335 } 1336 1337 HRESULT 1338 D3DContext::InitLCDGlyphCache() 1339 { 1340 if (pLCDGlyphCache == NULL) { 1341 return D3DGlyphCache::CreateInstance(this, CACHE_LCD, &pLCDGlyphCache); 1342 } 1343 return S_OK; 1344 } 1345 1346 HRESULT 1347 D3DContext::InitGrayscaleGlyphCache() 1348 { 1349 if (pGrayscaleGlyphCache == NULL) { 1350 return D3DGlyphCache::CreateInstance(this, CACHE_GRAY, 1351 &pGrayscaleGlyphCache); 1352 } 1353 return S_OK; 1354 } 1355 1356 HRESULT 1357 D3DContext::ResetComposite() 1358 { 1359 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::ResetComposite"); 1360 1361 RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); 1362 1363 HRESULT res = UpdateState(STATE_CHANGE); 1364 pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1365 extraAlpha = 1.0f; 1366 return res; 1367 } 1368 1369 HRESULT 1370 D3DContext::SetAlphaComposite(jint rule, jfloat ea, jint flags) 1371 { 1372 HRESULT res; 1373 J2dTraceLn3(J2D_TRACE_INFO, 1374 "D3DContext::SetAlphaComposite: rule=%-1d ea=%f flags=%d", 1375 rule, ea, flags); 1376 1377 RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); 1378 1379 res = UpdateState(STATE_CHANGE); 1380 1381 // we can safely disable blending when: 1382 // - comp is SrcNoEa or SrcOverNoEa, and 1383 // - the source is opaque 1384 // (turning off blending can have a large positive impact on performance) 1385 if ((rule == RULE_Src || rule == RULE_SrcOver) && 1386 (ea == 1.0f) && 1387 (flags & D3DC_SRC_IS_OPAQUE)) 1388 { 1389 J2dTraceLn1(J2D_TRACE_VERBOSE, 1390 " disabling alpha comp rule=%-1d ea=1.0 src=opq)", rule); 1391 pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 1392 } else { 1393 J2dTraceLn2(J2D_TRACE_VERBOSE, 1394 " enabling alpha comp (rule=%-1d ea=%f)", rule, ea); 1395 pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 1396 1397 pd3dDevice->SetRenderState(D3DRS_SRCBLEND, 1398 StdBlendRules[rule].src); 1399 pd3dDevice->SetRenderState(D3DRS_DESTBLEND, 1400 StdBlendRules[rule].dst); 1401 } 1402 1403 extraAlpha = ea; 1404 return res; 1405 } 1406 1407 #ifdef UPDATE_TX 1408 1409 // Note: this method of adjusting pixel to texel mapping proved to be 1410 // difficult to perfect. The current variation works great for id, 1411 // scale (including all kinds of flips) transforms, but not still not 1412 // for generic transforms. 1413 // 1414 // Since we currently only do DrawTexture with non-id transform we instead 1415 // adjust the geometry (see D3DVertexCacher::DrawTexture(), SetTransform()) 1416 // 1417 // In order to enable this code path UpdateTextureTransforms needs to 1418 // be called in SetTexture(), SetTransform() and ResetTranform(). 1419 HRESULT 1420 D3DContext::UpdateTextureTransforms(DWORD dwSamplerToUpdate) 1421 { 1422 HRESULT res = S_OK; 1423 DWORD dwSampler, dwMaxSampler; 1424 1425 if (dwSamplerToUpdate == -1) { 1426 // update all used samplers, dwMaxSampler will be set to max 1427 dwSampler = 0; 1428 dwSampler = MAX_USED_TEXTURE_SAMPLER; 1429 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::UpdateTextureTransforms: "\ 1430 "updating all samplers"); 1431 } else { 1432 // update only given sampler, dwMaxSampler will be set to it as well 1433 dwSampler = dwSamplerToUpdate; 1434 dwMaxSampler = dwSamplerToUpdate; 1435 J2dTraceLn1(J2D_TRACE_INFO, "D3DContext::UpdateTextureTransforms: "\ 1436 "updating sampler %d", dwSampler); 1437 } 1438 1439 do { 1440 D3DTRANSFORMSTATETYPE state = 1441 (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + dwSampler); 1442 IDirect3DTexture9 *pTexture = lastTexture[dwSampler]; 1443 1444 if (pTexture != NULL) { 1445 D3DMATRIX mt, tx; 1446 D3DSURFACE_DESC texDesc; 1447 1448 pd3dDevice->GetTransform(D3DTS_WORLD, &tx); 1449 J2dTraceLn4(10, 1450 " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14); 1451 J2dTraceLn4(10, 1452 " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24); 1453 J2dTraceLn4(10, 1454 " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34); 1455 J2dTraceLn4(10, 1456 " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44); 1457 1458 // this formula works for scales and flips 1459 if (tx._11 == 0.0f) { 1460 tx._11 = tx._12; 1461 } 1462 if (tx._22 == 0.0f) { 1463 tx._22 = tx._21; 1464 } 1465 1466 pTexture->GetLevelDesc(0, &texDesc); 1467 1468 // shift by .5 texel, but take into account 1469 // the scale factor of the device transform 1470 1471 // REMIND: this approach is not entirely correct, 1472 // as it only takes into account the scale of the device 1473 // transform. 1474 mt._31 = (1.0f / (2.0f * texDesc.Width * tx._11)); 1475 mt._32 = (1.0f / (2.0f * texDesc.Height * tx._22)); 1476 J2dTraceLn2(J2D_TRACE_VERBOSE, " offsets: tx=%f ty=%f", 1477 mt._31, mt._32); 1478 1479 pd3dDevice->SetTextureStageState(dwSampler, 1480 D3DTSS_TEXTURETRANSFORMFLAGS, 1481 D3DTTFF_COUNT2); 1482 res = pd3dDevice->SetTransform(state, &mt); 1483 } else { 1484 res = pd3dDevice->SetTextureStageState(dwSampler, 1485 D3DTSS_TEXTURETRANSFORMFLAGS, 1486 D3DTTFF_DISABLE); 1487 } 1488 dwSampler++; 1489 } while (dwSampler <= dwMaxSampler); 1490 1491 return res; 1492 } 1493 #endif // UPDATE_TX 1494 1495 /** 1496 * We go into the pains of maintaining the list of set textures 1497 * instead of just calling GetTexture() and comparing the old one 1498 * with the new one because it's actually noticeably slower to call 1499 * GetTexture() (note that we'd have to then call Release() on the 1500 * texture since GetTexture() increases texture's ref. count). 1501 */ 1502 HRESULT 1503 D3DContext::SetTexture(IDirect3DTexture9 *pTexture, DWORD dwSampler) 1504 { 1505 HRESULT res = S_OK; 1506 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetTexture"); 1507 1508 if (dwSampler < 0 || dwSampler > MAX_USED_TEXTURE_SAMPLER) { 1509 J2dTraceLn1(J2D_TRACE_ERROR, 1510 "D3DContext::SetTexture: incorrect sampler: %d", dwSampler); 1511 return E_FAIL; 1512 } 1513 if (lastTexture[dwSampler] != pTexture) { 1514 if (FAILED(res = FlushVertexQueue())) { 1515 return res; 1516 } 1517 J2dTraceLn2(J2D_TRACE_VERBOSE, 1518 " new texture=0x%x on sampler %d", pTexture, dwSampler); 1519 res = pd3dDevice->SetTexture(dwSampler, pTexture); 1520 if (SUCCEEDED(res)) { 1521 lastTexture[dwSampler] = pTexture; 1522 // REMIND: see comment at UpdateTextureTransforms 1523 #ifdef UPDATE_TX 1524 res = UpdateTextureTransforms(dwSampler); 1525 #endif 1526 } else { 1527 lastTexture[dwSampler] = NULL; 1528 } 1529 } 1530 return res; 1531 } 1532 1533 HRESULT 1534 D3DContext::UpdateTextureColorState(DWORD dwState, DWORD dwSampler) 1535 { 1536 HRESULT res = S_OK; 1537 1538 if (dwState != lastTextureColorState[dwSampler]) { 1539 res = pd3dDevice->SetTextureStageState(dwSampler, 1540 D3DTSS_ALPHAARG1, dwState); 1541 res = pd3dDevice->SetTextureStageState(dwSampler, 1542 D3DTSS_COLORARG1, dwState); 1543 lastTextureColorState[dwSampler] = dwState; 1544 } 1545 1546 return res; 1547 } 1548 1549 HRESULT /*NOLOCK*/ 1550 D3DContext::UpdateState(jbyte newState) 1551 { 1552 HRESULT res = S_OK; 1553 1554 if (opState == newState) { 1555 // The op is the same as last time, so we can return immediately. 1556 return res; 1557 } else if (opState != STATE_CHANGE) { 1558 res = FlushVertexQueue(); 1559 } 1560 1561 switch (opState) { 1562 case STATE_MASKOP: 1563 pMaskCache->Disable(); 1564 break; 1565 case STATE_GLYPHOP: 1566 D3DTR_DisableGlyphVertexCache(this); 1567 break; 1568 case STATE_TEXTUREOP: 1569 // optimization: certain state changes (those marked STATE_CHANGE) 1570 // are allowed while texturing is enabled. 1571 // In this case, we can allow previousOp to remain as it is and 1572 // then return early. 1573 if (newState == STATE_CHANGE) { 1574 return res; 1575 } 1576 // REMIND: not necessary if we are switching to MASKOP or GLYPHOP 1577 // (or a complex paint, for that matter), but would that be a 1578 // worthwhile optimization? 1579 SetTexture(NULL); 1580 break; 1581 case STATE_AAPGRAMOP: 1582 res = DisableAAParallelogramProgram(); 1583 break; 1584 default: 1585 break; 1586 } 1587 1588 switch (newState) { 1589 case STATE_MASKOP: 1590 pMaskCache->Enable(); 1591 UpdateTextureColorState(D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE); 1592 break; 1593 case STATE_GLYPHOP: 1594 D3DTR_EnableGlyphVertexCache(this); 1595 UpdateTextureColorState(D3DTA_TEXTURE | D3DTA_ALPHAREPLICATE); 1596 break; 1597 case STATE_TEXTUREOP: 1598 UpdateTextureColorState(D3DTA_TEXTURE); 1599 break; 1600 case STATE_AAPGRAMOP: 1601 res = EnableAAParallelogramProgram(); 1602 break; 1603 default: 1604 break; 1605 } 1606 1607 opState = newState; 1608 1609 return res; 1610 } 1611 1612 HRESULT D3DContext::FlushVertexQueue() 1613 { 1614 if (pVCacher != NULL) { 1615 return pVCacher->Render(); 1616 } 1617 return E_FAIL; 1618 } 1619 1620 HRESULT D3DContext::BeginScene(jbyte newState) 1621 { 1622 if (!pd3dDevice) { 1623 return E_FAIL; 1624 } else { 1625 UpdateState(newState); 1626 if (!bBeginScenePending) { 1627 bBeginScenePending = TRUE; 1628 HRESULT res = pd3dDevice->BeginScene(); 1629 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::BeginScene"); 1630 if (FAILED(res)) { 1631 // this will cause context reinitialization 1632 opState = STATE_CHANGE; 1633 } 1634 return res; 1635 } 1636 return S_OK; 1637 } 1638 } 1639 1640 HRESULT D3DContext::EndScene() { 1641 if (bBeginScenePending) { 1642 FlushVertexQueue(); 1643 bBeginScenePending = FALSE; 1644 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EndScene"); 1645 return pd3dDevice->EndScene(); 1646 } 1647 return S_OK; 1648 } 1649 1650 /** 1651 * Compiles and links the given fragment shader program. If 1652 * successful, this function returns a handle to the newly created shader 1653 * program; otherwise returns 0. 1654 */ 1655 IDirect3DPixelShader9 *D3DContext::CreateFragmentProgram(DWORD **shaders, 1656 ShaderList *programs, 1657 jint flags) 1658 { 1659 DWORD *sourceCode; 1660 IDirect3DPixelShader9 *pProgram; 1661 1662 J2dTraceLn1(J2D_TRACE_INFO, 1663 "D3DContext::CreateFragmentProgram: flags=%d", 1664 flags); 1665 1666 sourceCode = shaders[flags]; 1667 if (FAILED(pd3dDevice->CreatePixelShader(sourceCode, &pProgram))) { 1668 J2dRlsTraceLn(J2D_TRACE_ERROR, 1669 "D3DContext::CreateFragmentProgram: error creating program"); 1670 return NULL; 1671 } 1672 1673 // add it to the cache 1674 ShaderList_AddProgram(programs, ptr_to_jlong(pProgram), 1675 0 /*unused*/, 0 /*unused*/, flags); 1676 1677 return pProgram; 1678 } 1679 1680 /** 1681 * Locates and enables a fragment program given a list of shader programs 1682 * (ShaderInfos), using this context's state and flags as search 1683 * parameters. The "flags" parameter is a bitwise-or'd value that helps 1684 * differentiate one program for another; the interpretation of this value 1685 * varies depending on the type of shader (BufImgOp, Paint, etc) but here 1686 * it is only used to find another ShaderInfo with that same "flags" value. 1687 */ 1688 HRESULT D3DContext::EnableFragmentProgram(DWORD **shaders, 1689 ShaderList *programList, 1690 jint flags) 1691 { 1692 HRESULT res; 1693 jlong programID; 1694 IDirect3DPixelShader9 *pProgram; 1695 1696 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EnableFragmentProgram"); 1697 1698 programID = 1699 ShaderList_FindProgram(programList, 1700 0 /*unused*/, 0 /*unused*/, flags); 1701 1702 pProgram = (IDirect3DPixelShader9 *)jlong_to_ptr(programID); 1703 if (pProgram == NULL) { 1704 pProgram = CreateFragmentProgram(shaders, programList, flags); 1705 if (pProgram == NULL) { 1706 return E_FAIL; 1707 } 1708 } 1709 1710 if (FAILED(res = pd3dDevice->SetPixelShader(pProgram))) { 1711 J2dRlsTraceLn(J2D_TRACE_ERROR, 1712 "D3DContext::EnableFragmentProgram: error setting pixel shader"); 1713 return res; 1714 } 1715 1716 return S_OK; 1717 } 1718 1719 HRESULT D3DContext::EnableBasicGradientProgram(jint flags) 1720 { 1721 return EnableFragmentProgram((DWORD **)gradShaders, 1722 &basicGradPrograms, flags); 1723 } 1724 1725 HRESULT D3DContext::EnableLinearGradientProgram(jint flags) 1726 { 1727 return EnableFragmentProgram((DWORD **)linearShaders, 1728 &linearGradPrograms, flags); 1729 } 1730 1731 HRESULT D3DContext::EnableRadialGradientProgram(jint flags) 1732 { 1733 return EnableFragmentProgram((DWORD **)radialShaders, 1734 &radialGradPrograms, flags); 1735 } 1736 1737 HRESULT D3DContext::EnableConvolveProgram(jint flags) 1738 { 1739 return EnableFragmentProgram((DWORD **)convolveShaders, 1740 &convolvePrograms, flags); 1741 } 1742 1743 HRESULT D3DContext::EnableRescaleProgram(jint flags) 1744 { 1745 return EnableFragmentProgram((DWORD **)rescaleShaders, 1746 &rescalePrograms, flags); 1747 } 1748 1749 HRESULT D3DContext::EnableLookupProgram(jint flags) 1750 { 1751 return EnableFragmentProgram((DWORD **)lookupShaders, 1752 &lookupPrograms, flags); 1753 } 1754 1755 HRESULT D3DContext::EnableLCDTextProgram() 1756 { 1757 HRESULT res; 1758 1759 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EnableLCDTextProgram"); 1760 1761 if (lcdTextProgram == NULL) { 1762 if (FAILED(res = pd3dDevice->CreatePixelShader(lcdtext0, 1763 &lcdTextProgram))) 1764 { 1765 return res; 1766 } 1767 } 1768 1769 if (FAILED(res = pd3dDevice->SetPixelShader(lcdTextProgram))) { 1770 J2dRlsTraceLn(J2D_TRACE_ERROR, 1771 "D3DContext::EnableLCDTextProgram: error setting pixel shader"); 1772 return res; 1773 } 1774 1775 return S_OK; 1776 } 1777 1778 HRESULT D3DContext::EnableAAParallelogramProgram() 1779 { 1780 HRESULT res; 1781 1782 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::EnableAAParallelogramProgram"); 1783 1784 if (aaPgramProgram == NULL) { 1785 if (FAILED(res = pd3dDevice->CreatePixelShader(aapgram0, 1786 &aaPgramProgram))) { 1787 DebugPrintD3DError(res, "D3DContext::EnableAAParallelogramProgram: " 1788 "error creating pixel shader"); 1789 return res; 1790 } 1791 } 1792 1793 if (FAILED(res = pd3dDevice->SetPixelShader(aaPgramProgram))) { 1794 DebugPrintD3DError(res, "D3DContext::EnableAAParallelogramProgram: " 1795 "error setting pixel shader"); 1796 return res; 1797 } 1798 1799 return S_OK; 1800 } 1801 1802 HRESULT D3DContext::DisableAAParallelogramProgram() 1803 { 1804 HRESULT res; 1805 1806 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::DisableAAParallelogramProgram"); 1807 1808 if (aaPgramProgram != NULL) { 1809 if (FAILED(res = pd3dDevice->SetPixelShader(NULL))) { 1810 DebugPrintD3DError(res, 1811 "D3DContext::DisableAAParallelogramProgram: " 1812 "error clearing pixel shader"); 1813 return res; 1814 } 1815 } 1816 1817 return S_OK; 1818 } 1819 1820 BOOL D3DContext::IsAlphaRTSurfaceSupported() 1821 { 1822 HRESULT res = pd3dObject->CheckDeviceFormat(adapterOrdinal, 1823 devCaps.DeviceType, 1824 curParams.BackBufferFormat, 1825 D3DUSAGE_RENDERTARGET, 1826 D3DRTYPE_SURFACE, 1827 D3DFMT_A8R8G8B8); 1828 return SUCCEEDED(res); 1829 } 1830 1831 BOOL D3DContext::IsAlphaRTTSupported() 1832 { 1833 HRESULT res = pd3dObject->CheckDeviceFormat(adapterOrdinal, 1834 devCaps.DeviceType, 1835 curParams.BackBufferFormat, 1836 D3DUSAGE_RENDERTARGET, 1837 D3DRTYPE_TEXTURE, 1838 D3DFMT_A8R8G8B8); 1839 return SUCCEEDED(res); 1840 } 1841 1842 BOOL D3DContext::IsOpaqueRTTSupported() 1843 { 1844 HRESULT res = pd3dObject->CheckDeviceFormat(adapterOrdinal, 1845 devCaps.DeviceType, 1846 curParams.BackBufferFormat, 1847 D3DUSAGE_RENDERTARGET, 1848 D3DRTYPE_TEXTURE, 1849 curParams.BackBufferFormat); 1850 return SUCCEEDED(res); 1851 } 1852 1853 HRESULT D3DContext::InitContextCaps() { 1854 J2dTraceLn(J2D_TRACE_INFO, "D3DContext::InitContextCaps"); 1855 J2dTraceLn1(J2D_TRACE_VERBOSE, " caps for adapter %d :", adapterOrdinal); 1856 1857 if (pd3dDevice == NULL || pd3dObject == NULL) { 1858 contextCaps = CAPS_EMPTY; 1859 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_EMPTY"); 1860 return E_FAIL; 1861 } 1862 1863 contextCaps = CAPS_DEVICE_OK; 1864 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_DEVICE_OK"); 1865 1866 if (IsAlphaRTSurfaceSupported()) { 1867 contextCaps |= CAPS_RT_PLAIN_ALPHA; 1868 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_RT_PLAIN_ALPHA"); 1869 } 1870 if (IsAlphaRTTSupported()) { 1871 contextCaps |= CAPS_RT_TEXTURE_ALPHA; 1872 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_RT_TEXTURE_ALPHA"); 1873 } 1874 if (IsOpaqueRTTSupported()) { 1875 contextCaps |= CAPS_RT_TEXTURE_OPAQUE; 1876 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_RT_TEXTURE_OPAQUE"); 1877 } 1878 if (IsPixelShader20Supported()) { 1879 contextCaps |= CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20; 1880 J2dRlsTraceLn(J2D_TRACE_VERBOSE, 1881 " | CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20"); 1882 // Pre-PS3.0 video boards are very slow with the AA shader, so 1883 // we will require PS30 hw even though the shader is compiled for 2.0a 1884 // if (IsGradientInstructionExtensionSupported()) { 1885 // contextCaps |= CAPS_AA_SHADER; 1886 // J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_AA_SHADER"); 1887 // } 1888 } 1889 if (IsPixelShader30Supported()) { 1890 if ((contextCaps & CAPS_AA_SHADER) == 0) { 1891 // This flag was not already mentioned above... 1892 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_AA_SHADER"); 1893 } 1894 contextCaps |= CAPS_PS30 | CAPS_AA_SHADER; 1895 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_PS30"); 1896 } 1897 if (IsMultiTexturingSupported()) { 1898 contextCaps |= CAPS_MULTITEXTURE; 1899 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_MULTITEXTURE"); 1900 } 1901 if (!IsPow2TexturesOnly()) { 1902 contextCaps |= CAPS_TEXNONPOW2; 1903 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_TEXNONPOW2"); 1904 } 1905 if (!IsSquareTexturesOnly()) { 1906 contextCaps |= CAPS_TEXNONSQUARE; 1907 J2dRlsTraceLn(J2D_TRACE_VERBOSE, " | CAPS_TEXNONSQUARE"); 1908 } 1909 return S_OK; 1910 }