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/D3DVertexCacher.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 "D3DVertexCacher.h"
28
#include "D3DPaints.h"
29
30
#include "math.h"
31
32
// non-texturized macros
33
34
#define ADD_VERTEX_XYC(X, Y, VCOLOR) \
35
do { \
36
vertices[firstUnusedVertex].x = (X); \
37
vertices[firstUnusedVertex].y = (Y); \
38
vertices[firstUnusedVertex].color = (DWORD)(VCOLOR); \
39
firstUnusedVertex++; \
40
} while (0)
41
42
#define ADD_LINE_XYC(X1, Y1, X2, Y2, VCOLOR) \
43
do { \
44
ADD_VERTEX_XYC(X1, Y1, VCOLOR); \
45
ADD_VERTEX_XYC(X2, Y2, VCOLOR); \
46
batches[currentBatch].pNum++; \
47
} while (0)
48
49
#define ADD_LINE_SEG_XYC(X, Y, VCOLOR) \
50
do { \
51
ADD_VERTEX_XYC(X, Y, VCOLOR); \
52
batches[currentBatch].pNum++; \
53
} while (0)
54
55
#define ADD_TRIANGLE_XYC(X1, Y1, X2, Y2, X3, Y3, VCOLOR) \
56
do { \
57
ADD_VERTEX_XYC(X1, Y1, VCOLOR); \
58
ADD_VERTEX_XYC(X2, Y2, VCOLOR); \
59
ADD_VERTEX_XYC(X3, Y3, VCOLOR); \
60
batches[currentBatch].pNum++; \
61
} while (0)
62
63
// texturized macros
64
65
#define ADD_VERTEX_XYUVC(X, Y, U1, V1, VCOLOR) \
66
do { \
67
vertices[firstUnusedVertex].x = (X); \
68
vertices[firstUnusedVertex].y = (Y); \
69
vertices[firstUnusedVertex].tu1 = (U1); \
70
vertices[firstUnusedVertex].tv1 = (V1); \
71
vertices[firstUnusedVertex].color = (DWORD)(VCOLOR); \
72
firstUnusedVertex++; \
73
} while (0)
74
75
#define ADD_VERTEX_XYUVUVC(X, Y, U1, V1, U2, V2, VCOLOR) \
76
do { \
77
vertices[firstUnusedVertex].tu2 = (U2); \
78
vertices[firstUnusedVertex].tv2 = (V2); \
79
ADD_VERTEX_XYUVC(X, Y, U1, V1, VCOLOR); \
80
} while (0)
81
82
#define ADD_TRIANGLE_XYUVC(X1, Y1, X2, Y2, X3, Y3, \
83
U1, V1, U2, V2, U3, V3, VCOLOR) \
84
do { \
85
ADD_VERTEX_XYUVC(X1, Y1, U1, V1, VCOLOR); \
86
ADD_VERTEX_XYUVC(X2, Y2, U2, V2, VCOLOR); \
87
ADD_VERTEX_XYUVC(X3, Y3, U3, V3, VCOLOR); \
88
batches[currentBatch].pNum++; \
89
} while (0)
90
91
#define ADD_TRIANGLE_XYUVUVC(X1, Y1, X2, Y2, X3, Y3, \
92
U11, V11, U12, V12, U13, V13, \
93
U21, V21, U22, V22, U23, V23, \
94
VCOLOR) \
95
do { \
96
ADD_VERTEX_XYUVUVC(X1, Y1, U11, V11, U21, V21, VCOLOR); \
97
ADD_VERTEX_XYUVUVC(X2, Y2, U12, V12, U22, V22, VCOLOR); \
98
ADD_VERTEX_XYUVUVC(X3, Y3, U13, V13, U23, V23, VCOLOR); \
99
batches[currentBatch].pNum++; \
100
} while (0)
101
102
// These are fudge factors for rendering lines found by experimenting.
103
// They are used to tweak the geometry such that the rendering (mostly) matches
104
// our software rendering on most hardware. The main goal was to pick the
105
// numbers such that the beginning and ending pixels of lines match.
106
#define LINE_FUDGE
107
// fudge factors
108
#ifdef LINE_FUDGE
109
110
// Horiz/vertical
111
#define HV_FF1 ( 0.0f)
112
#define HV_FF2 ( 0.51f)
113
// For the record: value below (or larger) is required for Intel 855, but
114
// breaks Nvidia, ATI and Intel 965, and since the pipeline is disabled on
115
// 855 anyway we'll use 0.51f.
116
//#define HV_FF2 ( 0.5315f)
117
#define HV_FF3 (-0.2f)
118
// single pixel
119
#define SP_FF4 ( 0.3f)
120
121
// diagonal, down
122
#define DD_FX1 (-0.1f)
123
#define DD_FY1 (-0.25f)
124
#define DD_FX2 ( 0.2f)
125
#define DD_FY2 ( 0.304f)
126
// For the record: with this value diagonal-down lines with Texture paint
127
// are a bit off on all chipsets but Intel 965. So instead we'll use
128
// .304f which makes it better for the rest, but at a price of a bit
129
// of pixel/texel shifting on 965G
130
//#define DD_FY2 ( 0.4f)
131
// diagonal, up
132
#define DU_FX1 (-0.1f)
133
#define DU_FY1 ( 0.4f)
134
#define DU_FX2 ( 0.3f)
135
#define DU_FY2 (-0.3f)
136
137
#else
138
139
#define HV_FF1 (0.0f)
140
#define HV_FF2 (0.0f)
141
#define HV_FF3 (0.0f)
142
#define SP_FF4 (0.0f)
143
144
#define DD_FX1 (0.0f)
145
#define DD_FY1 (0.0f)
146
#define DD_FX2 (0.0f)
147
#define DD_FY2 (0.0f)
148
#define DU_FX1 (0.0f)
149
#define DU_FY1 (0.0f)
150
#define DU_FX2 (0.0f)
151
#define DU_FY2 (0.0f)
152
153
#endif
154
155
HRESULT
156
D3DVertexCacher::CreateInstance(D3DContext *pCtx, D3DVertexCacher **ppVC)
157
{
158
HRESULT res;
159
160
J2dTraceLn(J2D_TRACE_INFO, "D3DVertexCacher::CreateInstance");
161
162
*ppVC = new D3DVertexCacher();
163
if (FAILED(res = (*ppVC)->Init(pCtx))) {
164
delete *ppVC;
165
*ppVC = NULL;
166
}
167
return res;
168
}
169
170
D3DVertexCacher::D3DVertexCacher()
171
{
172
lpD3DDevice = NULL;
173
lpD3DVertexBuffer = NULL;
174
}
175
176
HRESULT
177
D3DVertexCacher::Init(D3DContext *pCtx)
178
{
179
D3DCAPS9 caps;
180
181
RETURN_STATUS_IF_NULL(pCtx, E_FAIL);
182
183
ReleaseDefPoolResources();
184
185
this->pCtx = pCtx;
186
187
firstPendingBatch = 0;
188
firstPendingVertex = 0;
189
firstUnusedVertex = 0;
190
currentBatch = 0;
191
ZeroMemory(vertices, sizeof(vertices));
192
ZeroMemory(batches, sizeof(batches));
193
194
lpD3DDevice = pCtx->Get3DDevice();
195
RETURN_STATUS_IF_NULL(lpD3DDevice, E_FAIL);
196
197
ZeroMemory(&caps, sizeof(caps));
198
lpD3DDevice->GetDeviceCaps(&caps);
199
200
D3DPOOL pool = (caps.DeviceType == D3DDEVTYPE_HAL) ?
201
D3DPOOL_DEFAULT : D3DPOOL_SYSTEMMEM;
202
// usage depends on whether we use hw or sw vertex processing
203
HRESULT res =
204
lpD3DDevice->CreateVertexBuffer(MAX_BATCH_SIZE*sizeof(J2DLVERTEX),
205
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, D3DFVF_J2DLVERTEX,
206
pool, &lpD3DVertexBuffer, NULL);
207
RETURN_STATUS_IF_FAILED(res);
208
209
res = lpD3DDevice->SetStreamSource(0, lpD3DVertexBuffer, 0,
210
sizeof(J2DLVERTEX));
211
RETURN_STATUS_IF_FAILED(res);
212
213
lpD3DDevice->SetFVF(D3DFVF_J2DLVERTEX);
214
return res;
215
}
216
217
void
218
D3DVertexCacher::ReleaseDefPoolResources()
219
{
220
SAFE_RELEASE(lpD3DVertexBuffer);
221
pCtx = NULL;
222
}
223
224
HRESULT D3DVertexCacher::DrawLine(int x1, int y1, int x2, int y2)
225
{
226
HRESULT res;
227
if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINELIST, 1*2))) {
228
float fx1, fy1, fx2, fy2;
229
if (y1 == y2) {
230
// horizontal
231
fy1 = (float)y1+HV_FF1;
232
fy2 = fy1;
233
234
if (x1 > x2) {
235
fx1 = (float)x2+HV_FF3;
236
fx2 = (float)x1+HV_FF2;
237
} else if (x1 < x2) {
238
fx1 = (float)x1+HV_FF3;
239
fx2 = (float)x2+HV_FF2;
240
} else {
241
// single point, offset a little so that a single
242
// pixel is rendered
243
fx1 = (float)x1-SP_FF4;
244
fy1 = (float)y1-SP_FF4;
245
fx2 = (float)x2+SP_FF4;
246
fy2 = (float)y2+SP_FF4;
247
}
248
} else if (x1 == x2) {
249
// vertical
250
fx1 = (float)x1+HV_FF1;
251
fx2 = fx1;
252
if (y1 > y2) {
253
fy1 = (float)y2+HV_FF3;
254
fy2 = (float)y1+HV_FF2;
255
} else {
256
fy1 = (float)y1+HV_FF3;
257
fy2 = (float)y2+HV_FF2;
258
}
259
} else {
260
// diagonal
261
if (x1 > x2 && y1 > y2) {
262
// ^
263
// \ case -> inverse
264
fx1 = (float)x2;
265
fy1 = (float)y2;
266
fx2 = (float)x1;
267
fy2 = (float)y1;
268
} else if (x1 > x2 && y2 > y1) {
269
// /
270
// v case - inverse
271
fx1 = (float)x2;
272
fy1 = (float)y2;
273
fx2 = (float)x1;
274
fy2 = (float)y1;
275
} else {
276
// \ ^
277
// v or / - leave as is
278
fx1 = (float)x1;
279
fy1 = (float)y1;
280
fx2 = (float)x2;
281
fy2 = (float)y2;
282
}
283
284
if (fx2 > fx1 && fy2 > fy1) {
285
// \
286
// v
287
fx1 += DD_FX1;
288
fy1 += DD_FY1;
289
fx2 += DD_FX2;
290
fy2 += DD_FY2;
291
} else {
292
// ^
293
// /
294
fx1 += DU_FX1;
295
fy1 += DU_FY1;
296
fx2 += DU_FX2;
297
fy2 += DU_FY2;
298
}
299
}
300
ADD_LINE_XYC(fx1, fy1, fx2, fy2, color);
301
}
302
return res;
303
}
304
305
HRESULT
306
D3DVertexCacher::DrawPoly(jint nPoints, jboolean isClosed,
307
jint transX, jint transY,
308
jint *xPoints, jint *yPoints)
309
{
310
HRESULT res;
311
jfloat mx = (jfloat)xPoints[0];
312
jfloat my = (jfloat)yPoints[0];
313
jboolean isEmpty = TRUE;
314
315
if (nPoints == 0) {
316
return S_OK;
317
}
318
319
if (isClosed &&
320
xPoints[nPoints - 1] == xPoints[0] &&
321
yPoints[nPoints - 1] == yPoints[0])
322
{
323
isClosed = FALSE;
324
}
325
326
// npoints is exactly the number of vertices we need,
327
// possibly plus one (if the path is closed)
328
UINT reqVerts = nPoints * 1;
329
int i = 0;
330
do {
331
// leave room for one possible additional closing point
332
UINT vertsInBatch = min(MAX_BATCH_SIZE-1, max(2, reqVerts));
333
if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINESTRIP, vertsInBatch+1))) {
334
reqVerts -= vertsInBatch;
335
do {
336
jfloat x = (jfloat)xPoints[i];
337
jfloat y = (jfloat)yPoints[i];
338
339
isEmpty = isEmpty && (x == mx && y == my);
340
341
ADD_LINE_SEG_XYC(x + transX, y + transY, color);
342
i++;
343
vertsInBatch--;
344
} while (vertsInBatch > 0);
345
// include the last point from the current batch into the next
346
if (reqVerts > 0) {
347
i--;
348
reqVerts++;
349
// loop continues
350
} else if (isClosed && !isEmpty) {
351
// if this was the last batch, see if the closing point is needed;
352
// note that we have left the room for it
353
ADD_LINE_SEG_XYC(mx + transX, my + transY, color);
354
// for clarity, the loop is ended anyway
355
break;
356
} else if (isEmpty || !isClosed) {
357
// - either we went nowhere, then change the last point
358
// so that a single pixel is rendered
359
// - or it's not empty and not closed - add another
360
// point because on some boards the last point is not rendered
361
mx = xPoints[nPoints-1] + transX +SP_FF4;
362
my = yPoints[nPoints-1] + transY +SP_FF4;
363
ADD_LINE_SEG_XYC(mx, my, color);
364
// for clarity
365
break;
366
}
367
}
368
} while (reqVerts > 0 && SUCCEEDED(res));
369
370
return res;
371
}
372
373
HRESULT
374
D3DVertexCacher::DrawScanlines(jint scanlineCount, jint *scanlines)
375
{
376
HRESULT res;
377
float x1, x2, y;
378
UINT reqVerts = scanlineCount*2/*vertices per line*/;
379
380
if (scanlineCount == 0) {
381
return S_OK;
382
}
383
384
do {
385
UINT vertsInBatch = min(2*(MAX_BATCH_SIZE/2), reqVerts);
386
if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINELIST, vertsInBatch))) {
387
reqVerts -= vertsInBatch;
388
do {
389
x1 = ((float)*(scanlines++)) +HV_FF3;
390
x2 = ((float)*(scanlines++)) +HV_FF2;
391
y = ((float)*(scanlines++)) +HV_FF1;
392
ADD_LINE_XYC(x1, y, x2, y, color);
393
vertsInBatch -= 2;
394
} while (vertsInBatch > 0);
395
}
396
} while (reqVerts > 0 && SUCCEEDED(res));
397
return res;
398
}
399
400
HRESULT
401
D3DVertexCacher::FillSpans(jint spanCount, jint *spans)
402
{
403
HRESULT res;
404
float x1, y1, x2, y2;
405
UINT reqVerts = spanCount*2*3/*vertices per span: two triangles*/;
406
407
if (spanCount == 0) {
408
return S_OK;
409
}
410
411
do {
412
UINT vertsInBatch = min(6*(MAX_BATCH_SIZE/6), reqVerts);
413
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, vertsInBatch))) {
414
reqVerts -= vertsInBatch;
415
do {
416
x1 = ((float)*(spans++));
417
y1 = ((float)*(spans++));
418
x2 = ((float)*(spans++));
419
y2 = ((float)*(spans++));
420
421
ADD_TRIANGLE_XYC(x1, y1, x2, y1, x1, y2, color);
422
ADD_TRIANGLE_XYC(x1, y2, x2, y1, x2, y2, color);
423
vertsInBatch -= 6;
424
} while (vertsInBatch > 0);
425
}
426
} while (reqVerts > 0 && SUCCEEDED(res));
427
428
return res;
429
}
430
431
HRESULT D3DVertexCacher::DrawRect(int x1, int y1, int x2, int y2)
432
{
433
HRESULT res;
434
435
if ((x2 - x1) < 2 || (y2 - y1) < 2) {
436
return FillRect(x1, y1, x2+1, y2+1);
437
}
438
if (SUCCEEDED(res = EnsureCapacity(D3DPT_LINELIST, 4*2))) {
439
440
float fx1 = (float)x1;
441
float fy1 = (float)y1;
442
float fx2 = (float)x2;
443
float fy2 = (float)y2;
444
445
// horiz: top left - top right
446
ADD_LINE_XYC(fx1+HV_FF3, fy1+HV_FF1, fx2-1.0f+HV_FF2, fy1+HV_FF1,color);
447
// horiz: bottom left - bottom right
448
ADD_LINE_XYC(fx1+1.0f+HV_FF3, fy2+HV_FF1, fx2+HV_FF2, fy2+HV_FF1,color);
449
// vert : top right - bottom right
450
ADD_LINE_XYC(fx2+HV_FF1, fy1+HV_FF3, fx2+HV_FF1, fy2-1.0f+HV_FF2,color);
451
// vert : top left - bottom left
452
ADD_LINE_XYC(fx1+HV_FF1, fy1+1.0f+HV_FF3, fx1+HV_FF1, fy2+HV_FF2,color);
453
}
454
return res;
455
}
456
457
HRESULT D3DVertexCacher::FillRect(int x1, int y1, int x2, int y2)
458
{
459
HRESULT res;
460
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {
461
float fx1 = (float)x1;
462
float fy1 = (float)y1;
463
float fx2 = (float)x2;
464
float fy2 = (float)y2;
465
ADD_TRIANGLE_XYUVC(fx1, fy1, fx2, fy1, fx1, fy2,
466
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
467
color);
468
ADD_TRIANGLE_XYUVC(fx1, fy2, fx2, fy1, fx2, fy2,
469
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
470
color);
471
}
472
return res;
473
}
474
475
HRESULT D3DVertexCacher::FillParallelogram(float fx11, float fy11,
476
float dx21, float dy21,
477
float dx12, float dy12)
478
{
479
HRESULT res;
480
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {
481
// correct texel to pixel mapping; see D3DContext::SetTransform()
482
// for non-id tx case
483
if (pCtx->IsIdentityTx()) {
484
fx11 -= 0.5f;
485
fy11 -= 0.5f;
486
}
487
dx21 += fx11;
488
dy21 += fy11;
489
float fx22 = dx21 + dx12;
490
float fy22 = dy21 + dy12;
491
dx12 += fx11;
492
dy12 += fy11;
493
494
ADD_TRIANGLE_XYUVC(fx11, fy11, dx21, dy21, dx12, dy12,
495
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
496
color);
497
ADD_TRIANGLE_XYUVC(dx12, dy12, dx21, dy21, fx22, fy22,
498
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
499
color);
500
}
501
return res;
502
}
503
504
#define ADJUST_PGRAM(V, DV, DIM) \
505
do { \
506
if ((DV) >= 0) { \
507
(DIM) += (DV); \
508
} else { \
509
(DIM) -= (DV); \
510
(V) += (DV); \
511
} \
512
} while (0)
513
514
// Invert the following transform:
515
// DeltaT(0, 0) == (0, 0)
516
// DeltaT(1, 0) == (DX1, DY1)
517
// DeltaT(0, 1) == (DX2, DY2)
518
// DeltaT(1, 1) == (DX1+DX2, DY1+DY2)
519
// TM00 = DX1, TM01 = DX2, (TM02 = X11)
520
// TM10 = DY1, TM11 = DY2, (TM12 = Y11)
521
// Determinant = TM00*TM11 - TM01*TM10
522
// = DX1*DY2 - DX2*DY1
523
// Inverse is:
524
// IM00 = TM11/det, IM01 = -TM01/det
525
// IM10 = -TM10/det, IM11 = TM00/det
526
// IM02 = (TM01 * TM12 - TM11 * TM02) / det,
527
// IM12 = (TM10 * TM02 - TM00 * TM12) / det,
528
529
#define DECLARE_MATRIX(MAT) \
530
float MAT ## 00, MAT ## 01, MAT ## 02, MAT ## 10, MAT ## 11, MAT ## 12
531
532
#define GET_INVERTED_MATRIX(MAT, X11, Y11, DX1, DY1, DX2, DY2, RET_CODE) \
533
do { \
534
float det = DX1*DY2 - DX2*DY1; \
535
if (det == 0) { \
536
RET_CODE; \
537
} \
538
MAT ## 00 = DY2/det; \
539
MAT ## 01 = -DX2/det; \
540
MAT ## 10 = -DY1/det; \
541
MAT ## 11 = DX1/det; \
542
MAT ## 02 = (DX2 * Y11 - DY2 * X11) / det; \
543
MAT ## 12 = (DY1 * X11 - DX1 * Y11) / det; \
544
} while (0)
545
546
#define TRANSFORM(MAT, TX, TY, X, Y) \
547
do { \
548
TX = (X) * MAT ## 00 + (Y) * MAT ## 01 + MAT ## 02; \
549
TY = (X) * MAT ## 10 + (Y) * MAT ## 11 + MAT ## 12; \
550
} while (0)
551
552
HRESULT D3DVertexCacher::FillParallelogramAA(float fx11, float fy11,
553
float dx21, float dy21,
554
float dx12, float dy12)
555
{
556
HRESULT res;
557
DECLARE_MATRIX(om);
558
559
GET_INVERTED_MATRIX(om, fx11, fy11, dx21, dy21, dx12, dy12,
560
return D3D_OK);
561
562
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {
563
float px = fx11, py = fy11;
564
float pw = 0.0f, ph = 0.0f;
565
ADJUST_PGRAM(px, dx21, pw);
566
ADJUST_PGRAM(py, dy21, ph);
567
ADJUST_PGRAM(px, dx12, pw);
568
ADJUST_PGRAM(py, dy12, ph);
569
float px1 = floor(px);
570
float py1 = floor(py);
571
float px2 = ceil(px + pw);
572
float py2 = ceil(py + ph);
573
float u11, v11, u12, v12, u21, v21, u22, v22;
574
TRANSFORM(om, u11, v11, px1, py1);
575
TRANSFORM(om, u21, v21, px2, py1);
576
TRANSFORM(om, u12, v12, px1, py2);
577
TRANSFORM(om, u22, v22, px2, py2);
578
ADD_TRIANGLE_XYUVUVC(px1, py1, px2, py1, px1, py2,
579
u11, v11, u21, v21, u12, v12,
580
5.0, 5.0, 6.0, 5.0, 5.0, 6.0,
581
color);
582
ADD_TRIANGLE_XYUVUVC(px1, py2, px2, py1, px2, py2,
583
u12, v12, u21, v21, u22, v22,
584
5.0, 6.0, 6.0, 5.0, 6.0, 6.0,
585
color);
586
}
587
return res;
588
}
589
590
HRESULT D3DVertexCacher::DrawParallelogramAA(float ox11, float oy11,
591
float ox21, float oy21,
592
float ox12, float oy12,
593
float ix11, float iy11,
594
float ix21, float iy21,
595
float ix12, float iy12)
596
{
597
HRESULT res;
598
DECLARE_MATRIX(om);
599
DECLARE_MATRIX(im);
600
601
GET_INVERTED_MATRIX(im, ix11, iy11, ix21, iy21, ix12, iy12,
602
// inner parallelogram is degenerate
603
// therefore it encloses no area
604
// fill outer
605
return FillParallelogramAA(ox11, oy11,
606
ox21, oy21,
607
ox12, oy12));
608
GET_INVERTED_MATRIX(om, ox11, oy11, ox21, oy21, ox12, oy12,
609
return D3D_OK);
610
611
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {
612
float ox = ox11, oy = oy11;
613
float ow = 0.0f, oh = 0.0f;
614
ADJUST_PGRAM(ox, ox21, ow);
615
ADJUST_PGRAM(oy, oy21, oh);
616
ADJUST_PGRAM(ox, ox12, ow);
617
ADJUST_PGRAM(oy, oy12, oh);
618
float ox11 = floor(ox);
619
float oy11 = floor(oy);
620
float ox22 = ceil(ox + ow);
621
float oy22 = ceil(oy + oh);
622
float ou11, ov11, ou12, ov12, ou21, ov21, ou22, ov22;
623
TRANSFORM(om, ou11, ov11, ox11, oy11);
624
TRANSFORM(om, ou21, ov21, ox22, oy11);
625
TRANSFORM(om, ou12, ov12, ox11, oy22);
626
TRANSFORM(om, ou22, ov22, ox22, oy22);
627
float iu11, iv11, iu12, iv12, iu21, iv21, iu22, iv22;
628
TRANSFORM(im, iu11, iv11, ox11, oy11);
629
TRANSFORM(im, iu21, iv21, ox22, oy11);
630
TRANSFORM(im, iu12, iv12, ox11, oy22);
631
TRANSFORM(im, iu22, iv22, ox22, oy22);
632
ADD_TRIANGLE_XYUVUVC(ox11, oy11, ox22, oy11, ox11, oy22,
633
ou11, ov11, ou21, ov21, ou12, ov12,
634
iu11, iv11, iu21, iv21, iu12, iv12,
635
color);
636
ADD_TRIANGLE_XYUVUVC(ox11, oy22, ox22, oy11, ox22, oy22,
637
ou12, ov12, ou21, ov21, ou22, ov22,
638
iu12, iv12, iu21, iv21, iu22, iv22,
639
color);
640
}
641
return res;
642
}
643
644
HRESULT
645
D3DVertexCacher::DrawTexture(float x1, float y1, float x2, float y2,
646
float u1, float v1, float u2, float v2)
647
{
648
HRESULT res;
649
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {
650
// correct texel to pixel mapping; see D3DContext::SetTransform()
651
// for non-id tx case
652
if (pCtx->IsIdentityTx()) {
653
x1 -= 0.5f;
654
y1 -= 0.5f;
655
x2 -= 0.5f;
656
y2 -= 0.5f;
657
}
658
659
ADD_TRIANGLE_XYUVC(x1, y1, x2, y1, x1, y2,
660
u1, v1, u2, v1, u1, v2,
661
color);
662
ADD_TRIANGLE_XYUVC(x1, y2, x2, y1, x2, y2,
663
u1, v2, u2, v1, u2, v2,
664
color);
665
}
666
return res;
667
}
668
669
HRESULT
670
D3DVertexCacher::DrawTexture(float x1, float y1, float x2, float y2,
671
float u11, float v11, float u12, float v12,
672
float u21, float v21, float u22, float v22)
673
{
674
HRESULT res;
675
if (SUCCEEDED(res = EnsureCapacity(D3DPT_TRIANGLELIST, 2*3))) {
676
// correct texel to pixel mapping; see D3DContext::SetTransform()
677
// for non-id tx case
678
if (pCtx->IsIdentityTx()) {
679
x1 -= 0.5f;
680
y1 -= 0.5f;
681
x2 -= 0.5f;
682
y2 -= 0.5f;
683
}
684
685
ADD_TRIANGLE_XYUVUVC(x1, y1, x2, y1, x1, y2,
686
u11, v11, u12, v11, u11, v12,
687
u21, v21, u22, v21, u21, v22,
688
color);
689
ADD_TRIANGLE_XYUVUVC(x1, y2, x2, y1, x2, y2,
690
u11, v12, u12, v11, u12, v12,
691
u21, v22, u22, v21, u22, v22,
692
color);
693
}
694
return res;
695
}
696
697
HRESULT D3DVertexCacher::Render(int actionType)
698
{
699
J2DLVERTEX *lpVert;
700
HRESULT res;
701
DWORD dwLockFlags;
702
UINT pendingVertices = firstUnusedVertex - firstPendingVertex;
703
704
// nothing to render
705
if (pendingVertices == 0) {
706
if (actionType == RESET_ACTION) {
707
firstPendingBatch = 0;
708
firstPendingVertex = 0;
709
firstUnusedVertex = 0;
710
currentBatch = 0;
711
}
712
return D3D_OK;
713
}
714
715
if (firstPendingVertex == 0) {
716
// no data in the buffer yet, we don't care about
717
// vertex buffer's contents
718
dwLockFlags = D3DLOCK_DISCARD;
719
} else {
720
// append to the existing data in the vertex buffer
721
dwLockFlags = D3DLOCK_NOOVERWRITE;
722
}
723
724
if (SUCCEEDED(res =
725
lpD3DVertexBuffer->Lock((UINT)firstPendingVertex*sizeof(J2DLVERTEX),
726
(UINT)pendingVertices*sizeof(J2DLVERTEX),
727
(void**)&lpVert, dwLockFlags)))
728
{
729
// copy only new vertices
730
memcpy((void *)lpVert,
731
(void *)(vertices + firstPendingVertex),
732
pendingVertices * sizeof(J2DLVERTEX));
733
res = lpD3DVertexBuffer->Unlock();
734
UINT currentVertex = firstPendingVertex;
735
UINT batchSize;
736
J2dTraceLn2(J2D_TRACE_VERBOSE,
737
"D3DVC::Render Starting flushing of %d vertices "\
738
"in %d batches",
739
pendingVertices,
740
(currentBatch - firstPendingBatch + 1));
741
742
743
for (UINT b = firstPendingBatch; b <= currentBatch; b++) {
744
D3DPRIMITIVETYPE pType = batches[b].pType;
745
UINT primCount = batches[b].pNum;
746
switch (pType) {
747
// the macro for adding a line segment adds one too many prims
748
case D3DPT_LINESTRIP: batchSize = primCount; primCount--; break;
749
case D3DPT_LINELIST: batchSize = primCount*2; break;
750
default: batchSize = primCount*3; break;
751
}
752
res = lpD3DDevice->DrawPrimitive(pType, currentVertex, primCount);
753
currentVertex += batchSize;
754
// init to something it can never be
755
batches[b].pType = (D3DPRIMITIVETYPE)0;
756
batches[b].pNum = 0;
757
}
758
} else {
759
DebugPrintD3DError(res, "Can't lock vertex buffer");
760
}
761
762
// REMIND: may need to rethink what to do in case of an error,
763
// should we try to render them later?
764
if (actionType == RESET_ACTION) {
765
firstPendingBatch = 0;
766
firstPendingVertex = 0;
767
firstUnusedVertex = 0;
768
currentBatch = 0;
769
} else {
770
firstPendingBatch = currentBatch;
771
firstPendingVertex = firstUnusedVertex;
772
}
773
774
return res;
775
}
776
777
HRESULT D3DVertexCacher::EnsureCapacity(D3DPRIMITIVETYPE newPType, UINT vNum)
778
{
779
HRESULT res = D3D_OK;
780
if (vNum > MAX_BATCH_SIZE) {
781
// REMIND: need to define our own errors
782
return D3DERR_NOTAVAILABLE;
783
}
784
if ((firstUnusedVertex + vNum) > MAX_BATCH_SIZE) {
785
// if we can't fit new vertices in the vertex buffer,
786
// render whatever we have in the buffer and start
787
// from the beginning of the vertex buffer
788
J2dTraceLn2(J2D_TRACE_VERBOSE,
789
"D3DVC::EnsureCapacity exceeded capacity. "\
790
"current v: %d, requested vertices: %d\n",
791
firstUnusedVertex, vNum);
792
if (FAILED(res = Render(RESET_ACTION))) {
793
return res;
794
}
795
}
796
797
J2dTraceLn5(J2D_TRACE_VERBOSE,
798
"D3DVC::EnsureCapacity current batch: %d "\
799
" batch.type=%d newType=%d vNum=%d firstUnusedV=%d",
800
currentBatch, batches[currentBatch].pType, newPType, vNum,
801
firstUnusedVertex);
802
// there should not be multiple linestrips in a batch,
803
// or they will be counted as a single line strip
804
if (batches[currentBatch].pType != newPType ||
805
batches[currentBatch].pType == D3DPT_LINESTRIP)
806
{
807
// if this is a first unused batch, use it
808
if (firstUnusedVertex == firstPendingVertex) {
809
// record the first batch and vertex scheduled for rendering
810
firstPendingBatch = currentBatch;
811
firstPendingVertex = firstUnusedVertex;
812
} else {
813
// otherwise go to the next batch
814
currentBatch++;
815
}
816
batches[currentBatch].pType = newPType;
817
batches[currentBatch].pNum = 0;
818
}
819
// firstUnusedVertex is updated when new vertices are added
820
// to the vertices array
821
822
return res;
823
}
824
825