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