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