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/D3DBlitLoops.cpp
32288 views
1
/*
2
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include <jni.h>
27
#include "jlong.h"
28
29
#include "D3DPipeline.h"
30
31
#include "SurfaceData.h"
32
#include "D3DBlitLoops.h"
33
#include "D3DRenderQueue.h"
34
#include "D3DSurfaceData.h"
35
#include "GraphicsPrimitiveMgr.h"
36
37
#include "IntArgb.h"
38
#include "IntArgbPre.h"
39
#include "IntRgb.h"
40
#include "IntBgr.h"
41
#include "Ushort555Rgb.h"
42
#include "Ushort565Rgb.h"
43
#include "ByteIndexed.h"
44
45
46
extern "C" BlitFunc IntArgbToIntArgbPreConvert;
47
extern "C" BlitFunc IntArgbPreToIntArgbConvert;
48
extern "C" BlitFunc IntArgbBmToIntArgbConvert;
49
extern "C" BlitFunc IntRgbToIntArgbConvert;
50
extern "C" BlitFunc ThreeByteBgrToIntArgbConvert;
51
extern "C" BlitFunc Ushort565RgbToIntArgbConvert;
52
extern "C" BlitFunc Ushort555RgbToIntArgbConvert;
53
extern "C" BlitFunc IntBgrToIntArgbConvert;
54
extern "C" BlitFunc AnyIntIsomorphicCopy;
55
extern "C" BlitFunc ByteIndexedToIntArgbConvert;
56
extern "C" BlitFunc ByteIndexedToIntArgbPreConvert;
57
58
#define GETMIN(v1, v2) (((v1) > (t=(v2))) && ((v1) = t))
59
#define GETMAX(v1, v2) (((v1) < (t=(v2))) && ((v1) = t))
60
61
#ifdef D3D_PPL_DLL
62
63
JNIEXPORT void JNICALL
64
SurfaceData_IntersectBounds(SurfaceDataBounds *dst, SurfaceDataBounds *src)
65
{
66
int t;
67
GETMAX(dst->x1, src->x1);
68
GETMAX(dst->y1, src->y1);
69
GETMIN(dst->x2, src->x2);
70
GETMIN(dst->y2, src->y2);
71
}
72
73
JNIEXPORT void JNICALL
74
SurfaceData_IntersectBoundsXYXY(SurfaceDataBounds *bounds,
75
jint x1, jint y1, jint x2, jint y2)
76
{
77
int t;
78
GETMAX(bounds->x1, x1);
79
GETMAX(bounds->y1, y1);
80
GETMIN(bounds->x2, x2);
81
GETMIN(bounds->y2, y2);
82
}
83
84
JNIEXPORT void JNICALL
85
SurfaceData_IntersectBoundsXYWH(SurfaceDataBounds *bounds,
86
jint x, jint y, jint w, jint h)
87
{
88
w = (w <= 0) ? x : x+w;
89
if (w < x) {
90
w = 0x7fffffff;
91
}
92
if (bounds->x1 < x) {
93
bounds->x1 = x;
94
}
95
if (bounds->x2 > w) {
96
bounds->x2 = w;
97
}
98
h = (h <= 0) ? y : y+h;
99
if (h < y) {
100
h = 0x7fffffff;
101
}
102
if (bounds->y1 < y) {
103
bounds->y1 = y;
104
}
105
if (bounds->y2 > h) {
106
bounds->y2 = h;
107
}
108
}
109
110
JNIEXPORT void JNICALL
111
SurfaceData_IntersectBlitBounds(SurfaceDataBounds *src,
112
SurfaceDataBounds *dst,
113
jint dx, jint dy)
114
{
115
int t;
116
GETMAX(dst->x1, src->x1 + dx);
117
GETMAX(dst->y1, src->y1 + dy);
118
GETMIN(dst->x2, src->x2 + dx);
119
GETMIN(dst->y2, src->y2 + dy);
120
GETMAX(src->x1, dst->x1 - dx);
121
GETMAX(src->y1, dst->y1 - dy);
122
GETMIN(src->x2, dst->x2 - dx);
123
GETMIN(src->y2, dst->y2 - dy);
124
}
125
126
#endif /* D3D_PPL_DLL */
127
128
D3DPIPELINE_API HRESULT
129
D3DBL_CopySurfaceToIntArgbImage(IDirect3DSurface9 *pSurface,
130
SurfaceDataRasInfo *pDstInfo,
131
jint srcx, jint srcy,
132
jint srcWidth, jint srcHeight,
133
jint dstx, jint dsty)
134
{
135
HRESULT res = S_OK;
136
D3DLOCKED_RECT lockedRect;
137
RECT r = { srcx, srcy, srcx+srcWidth, srcy+srcHeight };
138
D3DSURFACE_DESC desc;
139
SurfaceDataRasInfo srcInfo;
140
141
J2dTraceLn(J2D_TRACE_INFO, "D3DBL_CopySurfaceToIntArgbImage");
142
J2dTraceLn4(J2D_TRACE_VERBOSE,
143
" rect={%-4d, %-4d, %-4d, %-4d}",
144
r.left, r.top, r.right, r.bottom);
145
146
res = pSurface->LockRect(&lockedRect, &r, D3DLOCK_NOSYSLOCK);
147
RETURN_STATUS_IF_FAILED(res);
148
pSurface->GetDesc(&desc);
149
150
ZeroMemory(&srcInfo, sizeof(SurfaceDataRasInfo));
151
// srcInfo.bounds.x1 = 0;
152
// srcInfo.bounds.y1 = 0;
153
srcInfo.bounds.x2 = srcWidth;
154
srcInfo.bounds.y2 = srcHeight;
155
srcInfo.scanStride = lockedRect.Pitch;
156
157
void *pSrcBase = lockedRect.pBits;
158
void *pDstBase = PtrCoord(pDstInfo->rasBase,
159
dstx, pDstInfo->pixelStride,
160
dsty, pDstInfo->scanStride);
161
162
switch (desc.Format) {
163
case D3DFMT_A8R8G8B8:
164
srcInfo.pixelStride = 4;
165
IntArgbPreToIntArgbConvert(pSrcBase, pDstBase,
166
srcWidth, srcHeight,
167
&srcInfo, pDstInfo, NULL, NULL);
168
break;
169
case D3DFMT_X8R8G8B8:
170
srcInfo.pixelStride = 4;
171
IntRgbToIntArgbConvert(pSrcBase, pDstBase,
172
srcWidth, srcHeight,
173
&srcInfo, pDstInfo, NULL, NULL);
174
break;
175
case D3DFMT_X8B8G8R8:
176
srcInfo.pixelStride = 4;
177
IntBgrToIntArgbConvert(pSrcBase, pDstBase,
178
srcWidth, srcHeight,
179
&srcInfo, pDstInfo, NULL, NULL);
180
break;
181
case D3DFMT_X1R5G5B5:
182
srcInfo.pixelStride = 2;
183
Ushort555RgbToIntArgbConvert(pSrcBase, pDstBase,
184
srcWidth, srcHeight,
185
&srcInfo, pDstInfo, NULL, NULL);
186
break;
187
case D3DFMT_R5G6B5:
188
srcInfo.pixelStride = 2;
189
Ushort565RgbToIntArgbConvert(pSrcBase, pDstBase,
190
srcWidth, srcHeight,
191
&srcInfo, pDstInfo, NULL, NULL);
192
break;
193
default:
194
J2dRlsTraceLn1(J2D_TRACE_ERROR,
195
"D3DBL_CopySurfaceToIntArgbImage: unknown format %d",
196
desc.Format);
197
}
198
199
return pSurface->UnlockRect();
200
}
201
202
D3DPIPELINE_API HRESULT
203
D3DBL_CopyImageToIntXrgbSurface(SurfaceDataRasInfo *pSrcInfo,
204
int srctype,
205
D3DResource *pDstSurfaceRes,
206
jint srcx, jint srcy,
207
jint srcWidth, jint srcHeight,
208
jint dstx, jint dsty)
209
{
210
HRESULT res = S_OK;
211
D3DLOCKED_RECT lockedRect;
212
RECT r = { dstx, dsty, dstx+srcWidth, dsty+srcHeight };
213
RECT *pR = &r;
214
SurfaceDataRasInfo dstInfo;
215
IDirect3DSurface9 *pDstSurface = pDstSurfaceRes->GetSurface();
216
D3DSURFACE_DESC *pDesc = pDstSurfaceRes->GetDesc();
217
DWORD dwLockFlags = D3DLOCK_NOSYSLOCK;
218
219
J2dTraceLn(J2D_TRACE_INFO, "D3DBL_CopyImageToIntXrgbSurface");
220
J2dTraceLn5(J2D_TRACE_VERBOSE,
221
" srctype=%d rect={%-4d, %-4d, %-4d, %-4d}",
222
srctype, r.left, r.top, r.right, r.bottom);
223
224
if (pDesc->Usage == D3DUSAGE_DYNAMIC) {
225
// it is safe to lock with discard because we don't care about the
226
// contents of dynamic textures, and some drivers are happier if
227
// dynamic textures are always locked with DISCARD
228
dwLockFlags |= D3DLOCK_DISCARD;
229
pR = NULL;
230
} else {
231
// in non-DYNAMIC case we lock the exact rect so there's no need to
232
// offset the destination pointer
233
dstx = 0;
234
dsty = 0;
235
}
236
237
res = pDstSurface->LockRect(&lockedRect, pR, dwLockFlags);
238
RETURN_STATUS_IF_FAILED(res);
239
240
ZeroMemory(&dstInfo, sizeof(SurfaceDataRasInfo));
241
// dstInfo.bounds.x1 = 0;
242
// dstInfo.bounds.y1 = 0;
243
dstInfo.bounds.x2 = srcWidth;
244
dstInfo.bounds.y2 = srcHeight;
245
dstInfo.scanStride = lockedRect.Pitch;
246
dstInfo.pixelStride = 4;
247
248
void *pSrcBase = PtrCoord(pSrcInfo->rasBase,
249
srcx, pSrcInfo->pixelStride,
250
srcy, pSrcInfo->scanStride);
251
void *pDstBase = PtrCoord(lockedRect.pBits,
252
dstx, dstInfo.pixelStride,
253
dsty, dstInfo.scanStride);
254
255
switch (srctype) {
256
case ST_INT_ARGB:
257
IntArgbToIntArgbPreConvert(pSrcBase, pDstBase,
258
srcWidth, srcHeight,
259
pSrcInfo, &dstInfo, NULL, NULL);
260
break;
261
case ST_INT_ARGB_PRE:
262
AnyIntIsomorphicCopy(pSrcBase, pDstBase,
263
srcWidth, srcHeight,
264
pSrcInfo, &dstInfo, NULL, NULL);
265
break;
266
case ST_INT_RGB:
267
IntRgbToIntArgbConvert(pSrcBase, pDstBase,
268
srcWidth, srcHeight,
269
pSrcInfo, &dstInfo, NULL, NULL);
270
break;
271
case ST_INT_ARGB_BM:
272
// REMIND: we don't have such sw loop
273
// so this path is disabled for now on java level
274
// IntArgbBmToIntArgbPreConvert(pSrcBase, pDstBase,
275
// srcWidth, srcHeight,
276
// pSrcInfo, &dstInfo, NULL, NULL);
277
break;
278
case ST_INT_BGR:
279
IntBgrToIntArgbConvert(pSrcBase, pDstBase,
280
srcWidth, srcHeight,
281
pSrcInfo, &dstInfo, NULL, NULL);
282
break;
283
case ST_3BYTE_BGR:
284
ThreeByteBgrToIntArgbConvert(pSrcBase, pDstBase,
285
srcWidth, srcHeight,
286
pSrcInfo, &dstInfo, NULL, NULL);
287
break;
288
case ST_USHORT_555_RGB:
289
Ushort555RgbToIntArgbConvert(pSrcBase, pDstBase,
290
srcWidth, srcHeight,
291
pSrcInfo, &dstInfo, NULL, NULL);
292
break;
293
case ST_USHORT_565_RGB:
294
Ushort565RgbToIntArgbConvert(pSrcBase, pDstBase,
295
srcWidth, srcHeight,
296
pSrcInfo, &dstInfo, NULL, NULL);
297
break;
298
case ST_BYTE_INDEXED:
299
ByteIndexedToIntArgbPreConvert(pSrcBase, pDstBase,
300
srcWidth, srcHeight,
301
pSrcInfo, &dstInfo, NULL, NULL);
302
break;
303
case ST_BYTE_INDEXED_BM:
304
// REMIND: we don't have such sw loop
305
// so this path is disabled for now on java level
306
// ByteIndexedBmToIntArgbPreConvert(pSrcBase, pDstBase,
307
// srcWidth, srcHeight,
308
// pSrcInfo, &dstInfo, NULL, NULL);
309
break;
310
default:
311
J2dRlsTraceLn1(J2D_TRACE_ERROR,
312
"D3DBL_CopyImageToIntXrgbSurface: unknown type %d",
313
srctype);
314
}
315
316
return pDstSurface->UnlockRect();
317
}
318
319
/**
320
* Inner loop used for copying a source "render-to" D3D "Surface" to a
321
* destination D3D "Surface". Note that the same surface can
322
* not be used as both the source and destination, as is the case in a copyArea()
323
* operation. This method is invoked from D3DBlitLoops_IsoBlit().
324
*
325
* The standard StretchRect() mechanism is used to copy the source region
326
* into the destination region. If the regions have different dimensions,
327
* the source will be scaled into the destination as appropriate (only
328
* nearest neighbor filtering will be applied for simple scale operations).
329
*/
330
HRESULT
331
D3DBlitSurfaceToSurface(D3DContext *d3dc, D3DSDOps *srcOps, D3DSDOps *dstOps,
332
D3DTEXTUREFILTERTYPE hint,
333
jint sx1, jint sy1, jint sx2, jint sy2,
334
jint dx1, jint dy1, jint dx2, jint dy2)
335
{
336
IDirect3DSurface9 *pSrc, *pDst;
337
338
J2dTraceLn(J2D_TRACE_INFO, "D3DBlitSurfaceToSurface");
339
340
RETURN_STATUS_IF_NULL(srcOps->pResource, E_FAIL);
341
RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL);
342
RETURN_STATUS_IF_NULL(pSrc = srcOps->pResource->GetSurface(), E_FAIL);
343
RETURN_STATUS_IF_NULL(pDst = dstOps->pResource->GetSurface(), E_FAIL);
344
345
d3dc->UpdateState(STATE_OTHEROP);
346
IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
347
348
// need to clip the destination bounds,
349
// otherwise StretchRect could fail
350
jint sw = sx2 - sx1;
351
jint sh = sy2 - sy1;
352
jdouble dw = dx2 - dx1;
353
jdouble dh = dy2 - dy1;
354
355
SurfaceDataBounds dstBounds;
356
dstBounds.x1 = dx1;
357
dstBounds.y1 = dy1;
358
dstBounds.x2 = dx2;
359
dstBounds.y2 = dy2;
360
SurfaceData_IntersectBoundsXYXY(&dstBounds, 0, 0,
361
dstOps->width, dstOps->height);
362
if (d3dc->GetClipType() == CLIP_RECT) {
363
J2dTraceLn(J2D_TRACE_VERBOSE, " rect clip, clip dest manually");
364
RECT clipRect;
365
pd3dDevice->GetScissorRect(&clipRect);
366
SurfaceData_IntersectBoundsXYXY(&dstBounds,
367
clipRect.left, clipRect.top,
368
clipRect.right, clipRect.bottom);
369
}
370
371
if (dstBounds.x1 != dx1) {
372
sx1 += (int)((dstBounds.x1 - dx1) * (sw / dw));
373
}
374
if (dstBounds.y1 != dy1) {
375
sy1 += (int)((dstBounds.y1 - dy1) * (sh / dh));
376
}
377
if (dstBounds.x2 != dx2) {
378
sx2 += (int)((dstBounds.x2 - dx2) * (sw / dw));
379
}
380
if (dstBounds.y2 != dy2) {
381
sy2 += (int)((dstBounds.y2 - dy2) * (sh / dh));
382
}
383
384
// check if the rects are empty (StretchRect will fail if so)
385
if (dstBounds.x1 >= dstBounds.x2 || dstBounds.y1 >= dstBounds.y2 ||
386
sx1 >= sx2 || sy1 >= sy2)
387
{
388
return S_OK;
389
}
390
391
RECT srcRect = { sx1, sy1, sx2, sy2 };
392
RECT dstRect = { dstBounds.x1, dstBounds.y1, dstBounds.x2, dstBounds.y2 };
393
394
return pd3dDevice->StretchRect(pSrc, &srcRect, pDst, &dstRect, hint);
395
}
396
397
/**
398
* A convenience method for issuing DrawTexture calls depending on the
399
* hint. See detailed explanation below.
400
*/
401
static inline HRESULT
402
D3DDrawTextureWithHint(D3DContext *d3dc, D3DTEXTUREFILTERTYPE hint,
403
jint srcWidth, jint srcHeight,
404
float tw, float th,
405
jint sx1, jint sy1, jint sx2, jint sy2,
406
float dx1, float dy1, float dx2, float dy2,
407
float tx1, float ty1, float tx2, float ty2)
408
{
409
HRESULT res;
410
411
if (hint == D3DTEXF_LINEAR &&
412
(srcWidth != tw || srcHeight != th ||
413
srcWidth != sx2 || srcHeight != sy2 ))
414
{
415
/*
416
* When the image bounds are smaller than the bounds of the
417
* texture that the image resides in, D3DTEXF_LINEAR will use pixels
418
* from outside the valid image bounds, which could result in garbage
419
* pixels showing up at the edges of the transformed result. We set
420
* the texture wrap mode to D3DTADDRESS_CLAMP, which solves the problem
421
* for the top and left edges. But when the source bounds do not
422
* match the texture bounds, we need to perform this as a four-part
423
* operation in order to prevent the filter used by D3D from using
424
* invalid pixels at the bottom and right edges.
425
*
426
* Note that we only need to apply this technique when the source
427
* bounds are equal to the actual image bounds. If the source bounds
428
* fall within the image bounds there is no need to apply this hack
429
* because the filter used by D3D will access valid pixels.
430
* Likewise, if the image bounds are equal to the texture bounds,
431
* then the edge conditions are handled properly by D3DTADDRESS_CLAMP.
432
*/
433
434
// These values represent the bottom-right corner of source texture
435
// region pulled in by 1/2 of a source texel.
436
float tx2adj = tx2 - (1.0f / (2.0f * tw));
437
float ty2adj = ty2 - (1.0f / (2.0f * th));
438
439
// These values represent the above coordinates pulled in by a
440
// tiny fraction. As an example, if we sample the tiny area from
441
// tx2adj2 to tx2adj, the result should be the solid color at the
442
// texel center corresponding to tx2adj.
443
float tx2adj2 = tx2adj - 0.0001f;
444
float ty2adj2 = ty2adj - 0.0001f;
445
446
// These values represent the bottom-right corner of the destination
447
// region pulled in by 1/2 of a destination pixel.
448
float dx2adj = dx2 - 0.5f;
449
float dy2adj = dy2 - 0.5f;
450
451
// First, render a majority of the source texture, from the top-left
452
// corner to the bottom-right, but not including the right or bottom
453
// edges.
454
d3dc->pVCacher->DrawTexture(dx1, dy1, dx2adj, dy2adj,
455
tx1, ty1, tx2adj, ty2adj);
456
457
// Second, render the remaining sliver on the right edge.
458
d3dc->pVCacher->DrawTexture(dx2adj, dy1, dx2, dy2adj,
459
tx2adj2, ty1, tx2adj, ty2adj);
460
461
// Third, render the remaining sliver on the bottom edge.
462
d3dc->pVCacher->DrawTexture(dx1, dy2adj, dx2adj, dy2,
463
tx1, ty2adj2, tx2adj, ty2adj);
464
465
// Finally, render the remaining speck at the bottom-right corner.
466
res = d3dc->pVCacher->DrawTexture(dx2adj, dy2adj, dx2, dy2,
467
tx2adj2, ty2adj2, tx2adj, ty2adj);
468
} else {
469
/*
470
* As mentioned above, we can issue a simple textured quad if:
471
* - the hint is D3DTEXF_POINT or
472
* - the source bounds are sufficiently inside the texture bounds or
473
* - the image bounds are equal to the texture bounds (as is the
474
* case when the image has power-of-two dimensions, or when the
475
* device supports non-pow2 textures)
476
*/
477
res = d3dc->pVCacher->DrawTexture(dx1, dy1, dx2, dy2,
478
tx1, ty1, tx2, ty2);
479
}
480
return res;
481
}
482
483
/**
484
* Inner loop used for copying a source D3D "Texture" to a destination
485
* D3D "Surface". This method is invoked from D3DBlitLoops_IsoBlit().
486
*
487
* This method will copy, scale, or transform the source texture into the
488
* destination depending on the transform state, as established in
489
* and D3DContext::SetTransform(). If the source texture is
490
* transformed in any way when rendered into the destination, the filtering
491
* method applied is determined by the hint parameter.
492
*/
493
static HRESULT
494
D3DBlitTextureToSurface(D3DContext *d3dc,
495
D3DSDOps *srcOps, D3DSDOps *dstOps,
496
jboolean rtt, D3DTEXTUREFILTERTYPE hint,
497
jint sx1, jint sy1, jint sx2, jint sy2,
498
float dx1, float dy1, float dx2, float dy2)
499
{
500
HRESULT res;
501
IDirect3DTexture9 *pSrc;
502
IDirect3DDevice9 *pd3dDevice;
503
float tx1, ty1, tx2, ty2;
504
float tw, th;
505
506
J2dTraceLn(J2D_TRACE_INFO, "D3DBlitTextureToSurface");
507
508
RETURN_STATUS_IF_NULL(srcOps->pResource, E_FAIL);
509
RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL);
510
511
pSrc = srcOps->pResource->GetTexture();
512
RETURN_STATUS_IF_NULL(pSrc, E_FAIL);
513
514
if (FAILED(res = d3dc->BeginScene(STATE_TEXTUREOP) ||
515
FAILED(res = d3dc->SetTexture(pSrc))))
516
{
517
J2dRlsTraceLn(J2D_TRACE_ERROR,
518
"D3DBlitTextureToSurface: BeginScene or SetTexture failed");
519
return res;
520
}
521
522
pd3dDevice = d3dc->Get3DDevice();
523
pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, hint);
524
pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, hint);
525
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
526
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
527
528
tw = (float)srcOps->pResource->GetDesc()->Width;
529
th = (float)srcOps->pResource->GetDesc()->Height;
530
531
// convert the source bounds into the range [0,1]
532
tx1 = ((float)sx1) / tw;
533
ty1 = ((float)sy1) / th;
534
tx2 = ((float)sx2) / tw;
535
ty2 = ((float)sy2) / th;
536
537
return D3DDrawTextureWithHint(d3dc, hint,
538
srcOps->width, srcOps->height,
539
tw, th,
540
sx1, sy1, sx2, sy2,
541
dx1, dy1, dx2, dy2,
542
tx1, ty1, tx2, ty2);
543
}
544
545
/**
546
* Inner loop used for copying a source system memory ("Sw") surface or
547
* D3D "Surface" to a destination D3D "Surface", using an D3D texture
548
* tile as an intermediate surface. This method is invoked from
549
* D3DBlitLoops_Blit() for "Sw" surfaces and D3DBlitLoops_IsoBlit() for
550
* "Surface" surfaces.
551
*
552
* This method is used to transform the source surface into the destination.
553
* Pixel rectangles cannot be arbitrarily transformed. However, texture
554
* mapped quads do respect the modelview transform matrix, so we use
555
* textures here to perform the transform operation. This method uses a
556
* tile-based approach in which a small subregion of the source surface is
557
* copied into a cached texture tile. The texture tile is then mapped
558
* into the appropriate location in the destination surface.
559
*
560
*/
561
D3DPIPELINE_API HRESULT
562
D3DBlitToSurfaceViaTexture(D3DContext *d3dc, SurfaceDataRasInfo *srcInfo,
563
int srctype, D3DSDOps *srcOps,
564
jboolean swsurface, jint hint,
565
jint sx1, jint sy1, jint sx2, jint sy2,
566
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
567
{
568
double tx1, ty1, tx2, ty2;
569
double dx, dy, dw, dh, cdw, cdh;
570
jint tw, th;
571
jint sx, sy, sw, sh;
572
HRESULT res = S_OK;
573
D3DResource *pBlitTextureRes = NULL;
574
IDirect3DTexture9 *pBlitTexture = NULL;
575
IDirect3DSurface9 *pBlitSurface = NULL, *pSrc = NULL;
576
D3DTEXTUREFILTERTYPE fhint =
577
(hint == D3DSD_XFORM_BILINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
578
fhint = d3dc->IsTextureFilteringSupported(fhint) ? fhint : D3DTEXF_NONE;
579
580
if (swsurface) {
581
res = d3dc->GetResourceManager()->GetBlitTexture(&pBlitTextureRes);
582
} else {
583
RETURN_STATUS_IF_NULL(srcOps->pResource, E_FAIL);
584
RETURN_STATUS_IF_NULL(pSrc = srcOps->pResource->GetSurface(), E_FAIL);
585
586
res = d3dc->GetResourceManager()->
587
GetBlitRTTexture(D3DC_BLIT_TILE_SIZE, D3DC_BLIT_TILE_SIZE,
588
srcOps->pResource->GetDesc()->Format,
589
&pBlitTextureRes);
590
}
591
if (FAILED(res)) {
592
J2dRlsTraceLn(J2D_TRACE_ERROR,
593
"D3DBlitToSurfaceViaTexture: could not init blit tile");
594
return res;
595
}
596
pBlitSurface = pBlitTextureRes->GetSurface();
597
pBlitTexture = pBlitTextureRes->GetTexture();
598
599
D3DSURFACE_DESC *pDesc = pBlitTextureRes->GetDesc();
600
601
tx1 = 0.0f;
602
ty1 = 0.0f;
603
tw = pDesc->Width;
604
th = pDesc->Height;
605
cdw = (dx2-dx1) / (((double)(sx2-sx1)) / tw);
606
cdh = (dy2-dy1) / (((double)(sy2-sy1)) / th);
607
608
res = d3dc->BeginScene(STATE_TEXTUREOP);
609
RETURN_STATUS_IF_FAILED(res);
610
res = d3dc->SetTexture(pBlitTexture);
611
RETURN_STATUS_IF_FAILED(res);
612
613
IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
614
pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, fhint);
615
pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, fhint);
616
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
617
pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
618
619
for (sy = sy1, dy = dy1; sy < sy2; sy += th, dy += cdh) {
620
sh = ((sy + th) > sy2) ? (sy2 - sy) : th;
621
dh = ((dy + cdh) > dy2) ? (dy2 - dy) : cdh;
622
623
for (sx = sx1, dx = dx1; sx < sx2; sx += tw, dx += cdw) {
624
sw = ((sx + tw) > sx2) ? (sx2 - sx) : tw;
625
dw = ((dx + cdw) > dx2) ? (dx2 - dx) : cdw;
626
627
tx2 = ((double)sw) / tw;
628
ty2 = ((double)sh) / th;
629
630
if (swsurface) {
631
D3DBL_CopyImageToIntXrgbSurface(srcInfo,
632
srctype, pBlitTextureRes,
633
sx, sy, sw, sh,
634
0, 0);
635
} else {
636
RECT srcRect = { (LONG)sx, (LONG)sy,
637
(LONG)(sx+dw), (LONG)(sy+dh) };
638
RECT dstRect = { 0l, 0l, (LONG)dw, (LONG)dh };
639
pd3dDevice->StretchRect(pSrc,
640
&srcRect, pBlitSurface, &dstRect,
641
D3DTEXF_NONE);
642
}
643
D3DDrawTextureWithHint(d3dc, fhint,
644
tw, th,
645
(float)tw, (float)th,
646
sx, sy, sw, sh,
647
(float)dx, (float)dy, (float)(dx+dw), (float)(dy+dh),
648
(float)tx1, (float)ty1, (float)tx2, (float)ty2);
649
res = d3dc->pVCacher->Render();
650
}
651
}
652
return res;
653
}
654
655
/**
656
* Inner loop used for copying a source system memory ("Sw") surface to a
657
* destination D3D "Texture". This method is invoked from
658
* D3DBlitLoops_Blit().
659
*
660
* The source surface is effectively loaded into the D3D texture object,
661
* which must have already been initialized by D3DSD_initTexture(). Note
662
* that this method is only capable of copying the source surface into the
663
* destination surface (i.e. no scaling or general transform is allowed).
664
* This restriction should not be an issue as this method is only used
665
* currently to cache a static system memory image into an D3D texture in
666
* a hidden-acceleration situation.
667
*/
668
static HRESULT
669
D3DBlitSwToTexture(D3DContext *d3dc,
670
SurfaceDataRasInfo *srcInfo, int srctype,
671
D3DSDOps *dstOps,
672
jint sx1, jint sy1, jint sx2, jint sy2)
673
{
674
RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL);
675
RETURN_STATUS_IF_NULL(dstOps->pResource->GetSurface(), E_FAIL);
676
677
return D3DBL_CopyImageToIntXrgbSurface(srcInfo, srctype,
678
dstOps->pResource,
679
sx1, sy1, sx2-sx1, sy2-sy1,
680
0, 0);
681
}
682
683
/**
684
* General blit method for copying a native D3D surface (of type "Surface"
685
* or "Texture") to another D3D "Surface". If texture is JNI_TRUE, this
686
* method will invoke the Texture->Surface inner loop; otherwise, one of the
687
* Surface->Surface inner loops will be invoked, depending on the transform
688
* state.
689
*/
690
D3DPIPELINE_API HRESULT
691
D3DBlitLoops_IsoBlit(JNIEnv *env,
692
D3DContext *d3dc, jlong pSrcOps, jlong pDstOps,
693
jboolean xform, jint hint,
694
jboolean texture, jboolean rtt,
695
jint sx1, jint sy1, jint sx2, jint sy2,
696
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
697
{
698
D3DSDOps *srcOps = (D3DSDOps *)jlong_to_ptr(pSrcOps);
699
D3DSDOps *dstOps = (D3DSDOps *)jlong_to_ptr(pDstOps);
700
SurfaceDataRasInfo srcInfo;
701
jint sw = sx2 - sx1;
702
jint sh = sy2 - sy1;
703
jdouble dw = dx2 - dx1;
704
jdouble dh = dy2 - dy1;
705
706
J2dTraceLn(J2D_TRACE_INFO, "D3DBlitLoops_IsoBlit");
707
708
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) {
709
J2dTraceLn(J2D_TRACE_WARNING,
710
"D3DBlitLoops_IsoBlit: invalid dimensions");
711
return E_FAIL;
712
}
713
714
RETURN_STATUS_IF_NULL(srcOps, E_FAIL);
715
RETURN_STATUS_IF_NULL(dstOps, E_FAIL);
716
RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
717
RETURN_STATUS_IF_NULL(d3dc->Get3DDevice(), E_FAIL);
718
719
srcInfo.bounds.x1 = sx1;
720
srcInfo.bounds.y1 = sy1;
721
srcInfo.bounds.x2 = sx2;
722
srcInfo.bounds.y2 = sy2;
723
724
SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds,
725
0, 0, srcOps->width, srcOps->height);
726
727
728
HRESULT res = S_OK;
729
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
730
srcInfo.bounds.y2 > srcInfo.bounds.y1)
731
{
732
if (srcInfo.bounds.x1 != sx1) {
733
dx1 += (srcInfo.bounds.x1 - sx1) * (dw / sw);
734
sx1 = srcInfo.bounds.x1;
735
}
736
if (srcInfo.bounds.y1 != sy1) {
737
dy1 += (srcInfo.bounds.y1 - sy1) * (dh / sh);
738
sy1 = srcInfo.bounds.y1;
739
}
740
if (srcInfo.bounds.x2 != sx2) {
741
dx2 += (srcInfo.bounds.x2 - sx2) * (dw / sw);
742
sx2 = srcInfo.bounds.x2;
743
}
744
if (srcInfo.bounds.y2 != sy2) {
745
dy2 += (srcInfo.bounds.y2 - sy2) * (dh / sh);
746
sy2 = srcInfo.bounds.y2;
747
}
748
749
J2dTraceLn2(J2D_TRACE_VERBOSE, " texture=%d hint=%d", texture, hint);
750
J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d",
751
sx1, sy1, sx2, sy2);
752
J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f",
753
dx1, dy1, dx2, dy2);
754
755
D3DTEXTUREFILTERTYPE fhint =
756
(hint == D3DSD_XFORM_BILINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
757
if (texture) {
758
fhint = d3dc->IsTextureFilteringSupported(fhint) ?
759
fhint : D3DTEXF_NONE;
760
res = D3DBlitTextureToSurface(d3dc, srcOps, dstOps, rtt, fhint,
761
sx1, sy1, sx2, sy2,
762
(float)dx1, (float)dy1,
763
(float)dx2, (float)dy2);
764
} else {
765
// StretchRect does not do compositing or clipping
766
IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
767
DWORD abEnabled = 0;
768
769
pd3dDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &abEnabled);
770
J2dTraceLn3(J2D_TRACE_VERBOSE, " xform=%d clip=%d abEnabled=%d",
771
xform, d3dc->GetClipType(), abEnabled);
772
if (!xform && d3dc->GetClipType() != CLIP_SHAPE && !abEnabled) {
773
fhint = d3dc->IsStretchRectFilteringSupported(fhint) ?
774
fhint : D3DTEXF_NONE;
775
776
res = D3DBlitSurfaceToSurface(d3dc, srcOps, dstOps, fhint,
777
sx1, sy1, sx2, sy2,
778
(int)dx1, (int)dy1,
779
(int)dx2, (int)dy2);
780
} else {
781
res = D3DBlitToSurfaceViaTexture(d3dc, &srcInfo,
782
// surface type is unused here
783
ST_INT_ARGB_PRE,
784
srcOps,
785
JNI_FALSE, hint,
786
sx1, sy1, sx2, sy2,
787
dx1, dy1, dx2, dy2);
788
}
789
}
790
}
791
return res;
792
}
793
794
/**
795
* General blit method for copying a system memory ("Sw") surface to a native
796
* D3D surface (of type "Surface" or "Texture"). If texture is JNI_TRUE,
797
* this method will invoke the Sw->Texture inner loop; otherwise, one of the
798
* Sw->Surface inner loops will be invoked, depending on the transform state.
799
*/
800
HRESULT
801
D3DBlitLoops_Blit(JNIEnv *env,
802
D3DContext *d3dc, jlong pSrcOps, jlong pDstOps,
803
jboolean xform, jint hint,
804
jint srctype, jboolean texture,
805
jint sx1, jint sy1, jint sx2, jint sy2,
806
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
807
{
808
SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
809
D3DSDOps *dstOps = (D3DSDOps *)jlong_to_ptr(pDstOps);
810
SurfaceDataRasInfo srcInfo;
811
HRESULT res = S_OK;
812
jint sw = sx2 - sx1;
813
jint sh = sy2 - sy1;
814
jdouble dw = dx2 - dx1;
815
jdouble dh = dy2 - dy1;
816
jint lockFlags = SD_LOCK_READ;
817
818
J2dTraceLn(J2D_TRACE_INFO, "D3DBlitLoops_Blit");
819
820
if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0 || srctype < 0) {
821
J2dTraceLn(J2D_TRACE_WARNING,
822
"D3DBlitLoops_Blit: invalid dimensions or srctype");
823
return E_FAIL;
824
}
825
826
RETURN_STATUS_IF_NULL(srcOps, E_FAIL);
827
RETURN_STATUS_IF_NULL(dstOps, E_FAIL);
828
RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
829
RETURN_STATUS_IF_NULL(d3dc->Get3DDevice(), E_FAIL);
830
831
srcInfo.bounds.x1 = sx1;
832
srcInfo.bounds.y1 = sy1;
833
srcInfo.bounds.x2 = sx2;
834
srcInfo.bounds.y2 = sy2;
835
836
if (srctype == ST_BYTE_INDEXED || srctype == ST_BYTE_INDEXED_BM) {
837
lockFlags |= SD_LOCK_LUT;
838
}
839
if (srcOps->Lock(env, srcOps, &srcInfo, lockFlags) != SD_SUCCESS) {
840
J2dTraceLn(J2D_TRACE_WARNING,
841
"D3DBlitLoops_Blit: could not acquire lock");
842
return E_FAIL;
843
}
844
845
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
846
srcInfo.bounds.y2 > srcInfo.bounds.y1)
847
{
848
srcOps->GetRasInfo(env, srcOps, &srcInfo);
849
if (srcInfo.rasBase) {
850
if (srcInfo.bounds.x1 != sx1) {
851
dx1 += (srcInfo.bounds.x1 - sx1) * (dw / sw);
852
sx1 = srcInfo.bounds.x1;
853
}
854
if (srcInfo.bounds.y1 != sy1) {
855
dy1 += (srcInfo.bounds.y1 - sy1) * (dh / sh);
856
sy1 = srcInfo.bounds.y1;
857
}
858
if (srcInfo.bounds.x2 != sx2) {
859
dx2 += (srcInfo.bounds.x2 - sx2) * (dw / sw);
860
sx2 = srcInfo.bounds.x2;
861
}
862
if (srcInfo.bounds.y2 != sy2) {
863
dy2 += (srcInfo.bounds.y2 - sy2) * (dh / sh);
864
sy2 = srcInfo.bounds.y2;
865
}
866
867
J2dTraceLn3(J2D_TRACE_VERBOSE, " texture=%d srctype=%d hint=%d",
868
texture, srctype, hint);
869
J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d",
870
sx1, sy1, sx2, sy2);
871
J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f",
872
dx1, dy1, dx2, dy2);
873
874
if (texture) {
875
// These coordinates will always be integers since we
876
// only ever do a straight copy from sw to texture.
877
// Thus these casts are "safe" - no loss of precision.
878
res = D3DBlitSwToTexture(d3dc, &srcInfo, srctype, dstOps,
879
(jint)dx1, (jint)dy1,
880
(jint)dx2, (jint)dy2);
881
} else {
882
res = D3DBlitToSurfaceViaTexture(d3dc, &srcInfo, srctype, NULL,
883
JNI_TRUE, hint,
884
sx1, sy1, sx2, sy2,
885
dx1, dy1, dx2, dy2);
886
}
887
}
888
SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
889
}
890
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
891
return res;
892
}
893
894
/**
895
* Specialized blit method for copying a native D3D "Surface" (pbuffer,
896
* window, etc.) to a system memory ("Sw") surface.
897
*/
898
HRESULT
899
D3DBlitLoops_SurfaceToSwBlit(JNIEnv *env, D3DContext *d3dc,
900
jlong pSrcOps, jlong pDstOps, jint dsttype,
901
jint srcx, jint srcy, jint dstx, jint dsty,
902
jint width, jint height)
903
{
904
D3DSDOps *srcOps = (D3DSDOps *)jlong_to_ptr(pSrcOps);
905
SurfaceDataOps *dstOps = (SurfaceDataOps *)jlong_to_ptr(pDstOps);
906
SurfaceDataRasInfo srcInfo, dstInfo;
907
HRESULT res = S_OK;
908
909
J2dTraceLn(J2D_TRACE_INFO, "D3DBlitLoops_SurfaceToSwBlit");
910
911
if (width <= 0 || height <= 0) {
912
J2dTraceLn(J2D_TRACE_WARNING,
913
"D3DBlitLoops_SurfaceToSwBlit: dimensions are non-positive");
914
return S_OK;
915
}
916
917
RETURN_STATUS_IF_NULL(srcOps, E_FAIL);
918
RETURN_STATUS_IF_NULL(srcOps->pResource, E_FAIL);
919
RETURN_STATUS_IF_NULL(dstOps, E_FAIL);
920
RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
921
RETURN_STATUS_IF_NULL(d3dc->Get3DDevice(), E_FAIL);
922
923
srcInfo.bounds.x1 = srcx;
924
srcInfo.bounds.y1 = srcy;
925
srcInfo.bounds.x2 = srcx + width;
926
srcInfo.bounds.y2 = srcy + height;
927
dstInfo.bounds.x1 = dstx;
928
dstInfo.bounds.y1 = dsty;
929
dstInfo.bounds.x2 = dstx + width;
930
dstInfo.bounds.y2 = dsty + height;
931
932
if (dstOps->Lock(env, dstOps, &dstInfo, SD_LOCK_WRITE) != SD_SUCCESS) {
933
J2dTraceLn(J2D_TRACE_WARNING,
934
"D3DBlitLoops_SurfaceToSwBlit: could not acquire dst lock");
935
return S_OK;
936
}
937
938
SurfaceData_IntersectBoundsXYXY(&srcInfo.bounds,
939
0, 0, srcOps->width, srcOps->height);
940
SurfaceData_IntersectBlitBounds(&dstInfo.bounds, &srcInfo.bounds,
941
srcx - dstx, srcy - dsty);
942
943
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
944
srcInfo.bounds.y2 > srcInfo.bounds.y1)
945
{
946
dstOps->GetRasInfo(env, dstOps, &dstInfo);
947
if (dstInfo.rasBase) {
948
IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
949
IDirect3DSurface9 *pSrc = srcOps->pResource->GetSurface();
950
D3DFORMAT srcFmt = srcOps->pResource->GetDesc()->Format;
951
UINT srcw = srcOps->pResource->GetDesc()->Width;
952
UINT srch = srcOps->pResource->GetDesc()->Height;
953
D3DResource *pLockableRes;
954
955
srcx = srcInfo.bounds.x1;
956
srcy = srcInfo.bounds.y1;
957
dstx = dstInfo.bounds.x1;
958
dsty = dstInfo.bounds.y1;
959
width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
960
height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
961
962
J2dTraceLn4(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d",
963
srcx, srcy, width, height);
964
J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d",
965
dstx, dsty);
966
967
d3dc->UpdateState(STATE_OTHEROP);
968
969
// if we read more than 50% of the image it is faster
970
// to get the whole thing (50% is pulled out of a hat)
971
BOOL fullRead = ((width * height) >= (srcw * srch * 0.5f));
972
UINT lockSrcX = 0, lockSrcY = 0;
973
974
if (fullRead) {
975
// read whole surface into a sysmem surface
976
lockSrcX = srcx;
977
lockSrcY = srcy;
978
// the dest surface must have the same dimensions and format as
979
// the source, GetBlitOSPSurface ensures that
980
res = d3dc->GetResourceManager()->
981
GetBlitOSPSurface(srcw, srch, srcFmt, &pLockableRes);
982
} else {
983
// we first copy the source region to a temp
984
// render target surface of the same format as the
985
// source, then copy the pixels to the
986
// target buffered image surface
987
res = d3dc->GetResourceManager()->
988
GetLockableRTSurface(width, height, srcFmt, &pLockableRes);
989
}
990
if (SUCCEEDED(res)) {
991
IDirect3DSurface9 *pTmpSurface = pLockableRes->GetSurface();
992
993
if (fullRead) {
994
res = pd3dDevice->GetRenderTargetData(pSrc, pTmpSurface);
995
} else {
996
RECT srcRect = { srcx, srcy, srcx+width, srcy+height};
997
RECT dstRect = { 0l, 0l, width, height };
998
999
res = pd3dDevice->StretchRect(pSrc,
1000
&srcRect, pTmpSurface,
1001
&dstRect, D3DTEXF_NONE);
1002
}
1003
1004
if (SUCCEEDED(res)) {
1005
res = D3DBL_CopySurfaceToIntArgbImage(
1006
pTmpSurface, /* src surface */
1007
&dstInfo, /* dst info */
1008
lockSrcX, lockSrcY, width, height, /* src rect */
1009
dstx, dsty); /* dst coords */
1010
}
1011
}
1012
}
1013
SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
1014
}
1015
SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
1016
return res;
1017
}
1018
1019
HRESULT
1020
D3DBlitLoops_CopyArea(JNIEnv *env,
1021
D3DContext *d3dc, D3DSDOps *dstOps,
1022
jint x, jint y, jint width, jint height,
1023
jint dx, jint dy)
1024
{
1025
SurfaceDataBounds srcBounds, dstBounds;
1026
HRESULT res = S_OK;
1027
1028
J2dTraceLn(J2D_TRACE_INFO, "D3DBlitLoops_CopyArea");
1029
1030
RETURN_STATUS_IF_NULL(d3dc, E_FAIL);
1031
RETURN_STATUS_IF_NULL(dstOps, E_FAIL);
1032
RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL);
1033
1034
J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d",
1035
x, y, width, height);
1036
J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d",
1037
dx, dy);
1038
1039
IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice();
1040
RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL);
1041
ClipType clipType = d3dc->GetClipType();
1042
1043
srcBounds.x1 = x;
1044
srcBounds.y1 = y;
1045
srcBounds.x2 = srcBounds.x1 + width;
1046
srcBounds.y2 = srcBounds.y1 + height;
1047
dstBounds.x1 = x + dx;
1048
dstBounds.y1 = y + dy;
1049
dstBounds.x2 = dstBounds.x1 + width;
1050
dstBounds.y2 = dstBounds.y1 + height;
1051
1052
SurfaceData_IntersectBoundsXYXY(&srcBounds,
1053
0, 0, dstOps->width, dstOps->height);
1054
if (clipType == CLIP_RECT) {
1055
J2dTraceLn(J2D_TRACE_VERBOSE, " rect clip, clip dest manually");
1056
RECT clipRect;
1057
pd3dDevice->GetScissorRect(&clipRect);
1058
SurfaceData_IntersectBoundsXYXY(&dstBounds,
1059
clipRect.left, clipRect.top,
1060
clipRect.right, clipRect.bottom);
1061
}
1062
SurfaceData_IntersectBoundsXYXY(&dstBounds,
1063
0, 0, dstOps->width, dstOps->height);
1064
SurfaceData_IntersectBlitBounds(&dstBounds, &srcBounds, -dx, -dy);
1065
1066
if (dstBounds.x1 < dstBounds.x2 && dstBounds.y1 < dstBounds.y2) {
1067
jint sx1 = srcBounds.x1, sy1 = srcBounds.y1,
1068
sx2 = srcBounds.x2, sy2 = srcBounds.y2;
1069
jint dx1 = dstBounds.x1, dy1 = dstBounds.y1,
1070
dx2 = dstBounds.x2, dy2 = dstBounds.y2;
1071
jint dw = dx2 - dx1, dh = dy2 - dy1;
1072
1073
IDirect3DTexture9 *pBlitTexture = NULL;
1074
IDirect3DSurface9 *pBlitSurface = NULL;
1075
D3DResource *pBlitTextureRes;
1076
1077
res = d3dc->GetResourceManager()->
1078
GetBlitRTTexture(dw, dh,
1079
dstOps->pResource->GetDesc()->Format,
1080
&pBlitTextureRes);
1081
if (SUCCEEDED(res)) {
1082
pBlitSurface = pBlitTextureRes->GetSurface();
1083
pBlitTexture = pBlitTextureRes->GetTexture();
1084
}
1085
if (!pBlitTexture || !pBlitSurface) {
1086
J2dRlsTraceLn(J2D_TRACE_ERROR,
1087
"D3DBlitLoops_CopyArea: could not init blit tile");
1088
return E_FAIL;
1089
}
1090
1091
// flush the rendering first
1092
d3dc->UpdateState(STATE_OTHEROP);
1093
1094
// REMIND: see if we could always use texture mapping;
1095
// the assumption here is that StretchRect is faster,
1096
// if it's not, then we should always use texture mapping
1097
1098
// from src surface to the temp texture
1099
RECT srcRect = { sx1, sy1, sx2, sy2 };
1100
RECT tmpDstRect = { 0l, 0l, 0+dw, 0+dh };
1101
res = pd3dDevice->StretchRect(dstOps->pResource->GetSurface(), &srcRect,
1102
pBlitSurface, &tmpDstRect,
1103
D3DTEXF_NONE);
1104
if (clipType != CLIP_SHAPE) {
1105
J2dTraceLn(J2D_TRACE_VERBOSE, " rect or no clip, use StretchRect");
1106
// just do stretch rect to the destination
1107
RECT dstRect = { dx1, dy1, dx2, dy2 };
1108
// from temp surface to the destination
1109
res = pd3dDevice->StretchRect(pBlitSurface, &tmpDstRect,
1110
dstOps->pResource->GetSurface(),
1111
&dstRect,
1112
D3DTEXF_NONE);
1113
} else {
1114
J2dTraceLn(J2D_TRACE_VERBOSE, " shape clip, use texture mapping");
1115
// shape clip - have to use texture mapping
1116
D3DTEXTUREFILTERTYPE fhint =
1117
d3dc->IsTextureFilteringSupported(D3DTEXF_NONE) ?
1118
D3DTEXF_NONE: D3DTEXF_POINT;
1119
pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, fhint);
1120
pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, fhint);
1121
res = d3dc->BeginScene(STATE_TEXTUREOP);
1122
RETURN_STATUS_IF_FAILED(res);
1123
res = d3dc->SetTexture(pBlitTexture);
1124
1125
float tx2 = (float)dw/(float)pBlitTextureRes->GetDesc()->Width;
1126
float ty2 = (float)dh/(float)pBlitTextureRes->GetDesc()->Height;
1127
res = d3dc->pVCacher->DrawTexture(
1128
(float)dx1, (float)dy1, (float)dx2, (float)dy2,
1129
0.0f, 0.0f, tx2, ty2);
1130
}
1131
}
1132
return res;
1133
}
1134
1135