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