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