Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/windows/classes/sun/java2d/d3d/D3DSurfaceData.java
41159 views
1
/*
2
* Copyright (c) 2007, 2014, 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
package sun.java2d.d3d;
27
28
import java.awt.AlphaComposite;
29
import java.awt.BufferCapabilities;
30
import java.awt.Component;
31
import java.awt.GraphicsConfiguration;
32
import java.awt.GraphicsDevice;
33
import java.awt.GraphicsEnvironment;
34
import java.awt.Image;
35
import java.awt.Rectangle;
36
import java.awt.Transparency;
37
import java.awt.image.ColorModel;
38
import java.awt.image.DataBuffer;
39
import java.awt.image.DirectColorModel;
40
import java.awt.image.Raster;
41
import java.awt.image.SampleModel;
42
import java.awt.image.SinglePixelPackedSampleModel;
43
import sun.awt.SunHints;
44
import sun.awt.image.DataBufferNative;
45
import sun.awt.image.PixelConverter;
46
import sun.awt.image.SurfaceManager;
47
import sun.awt.image.WritableRasterNative;
48
import sun.awt.windows.WComponentPeer;
49
import sun.java2d.pipe.hw.AccelSurface;
50
import sun.java2d.InvalidPipeException;
51
import sun.java2d.SunGraphics2D;
52
import sun.java2d.SurfaceData;
53
import sun.java2d.loops.GraphicsPrimitive;
54
import sun.java2d.loops.MaskFill;
55
import sun.java2d.loops.SurfaceType;
56
import sun.java2d.loops.CompositeType;
57
import sun.java2d.pipe.ParallelogramPipe;
58
import sun.java2d.pipe.PixelToParallelogramConverter;
59
import sun.java2d.pipe.RenderBuffer;
60
import sun.java2d.pipe.TextPipe;
61
import sun.java2d.pipe.Region;
62
import static sun.java2d.pipe.BufferedOpCodes.*;
63
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
64
import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
65
import sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType;
66
import java.awt.BufferCapabilities.FlipContents;
67
import java.awt.Dimension;
68
import java.awt.Window;
69
import java.awt.geom.AffineTransform;
70
import sun.awt.SunToolkit;
71
import sun.awt.image.SunVolatileImage;
72
import sun.awt.windows.WWindowPeer;
73
import sun.java2d.ScreenUpdateManager;
74
import sun.java2d.StateTracker;
75
import sun.java2d.SurfaceDataProxy;
76
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
77
78
/**
79
* This class describes a D3D "surface", that is, a region of pixels
80
* managed via D3D. An D3DSurfaceData can be tagged with one of three
81
* different SurfaceType objects for the purpose of registering loops, etc.
82
* This diagram shows the hierarchy of D3D SurfaceTypes:
83
*
84
* Any
85
* / \
86
* D3DSurface D3DTexture
87
* |
88
* D3DSurfaceRTT
89
*
90
* D3DSurface
91
* This kind of surface can be rendered to using D3D APIs. It is also
92
* possible to copy a D3DSurface to another D3DSurface (or to itself).
93
*
94
* D3DTexture
95
* This kind of surface cannot be rendered to using D3D (in the same sense
96
* as in D3DSurface). However, it is possible to upload a region of pixels
97
* to a D3DTexture object via Lock/UnlockRect(). One can also copy a
98
* surface of type D3DTexture to a D3DSurface by binding the texture
99
* to a quad and then rendering it to the destination surface (this process
100
* is known as "texture mapping").
101
*
102
* D3DSurfaceRTT
103
* This kind of surface can be thought of as a sort of hybrid between
104
* D3DSurface and D3DTexture, in that one can render to this kind of
105
* surface as if it were of type D3DSurface, but the process of copying
106
* this kind of surface to another is more like a D3DTexture. (Note that
107
* "RTT" stands for "render-to-texture".)
108
*
109
* In addition to these SurfaceType variants, we have also defined some
110
* constants that describe in more detail the type of underlying D3D
111
* surface. This table helps explain the relationships between those
112
* "type" constants and their corresponding SurfaceType:
113
*
114
* D3D Type Corresponding SurfaceType
115
* -------- -------------------------
116
* RT_PLAIN D3DSurface
117
* TEXTURE D3DTexture
118
* FLIP_BACKBUFFER D3DSurface
119
* RT_TEXTURE D3DSurfaceRTT
120
*/
121
public class D3DSurfaceData extends SurfaceData implements AccelSurface {
122
123
/**
124
* To be used with getNativeResource() only.
125
* @see #getNativeResource
126
*/
127
public static final int D3D_DEVICE_RESOURCE= 100;
128
/*
129
* Surface types.
130
* We use these surface types when copying from a sw surface
131
* to a surface or texture.
132
*/
133
public static final int ST_INT_ARGB = 0;
134
public static final int ST_INT_ARGB_PRE = 1;
135
public static final int ST_INT_ARGB_BM = 2;
136
public static final int ST_INT_RGB = 3;
137
public static final int ST_INT_BGR = 4;
138
public static final int ST_USHORT_565_RGB = 5;
139
public static final int ST_USHORT_555_RGB = 6;
140
public static final int ST_BYTE_INDEXED = 7;
141
public static final int ST_BYTE_INDEXED_BM = 8;
142
public static final int ST_3BYTE_BGR = 9;
143
144
/** Equals to D3DSWAPEFFECT_DISCARD */
145
public static final int SWAP_DISCARD = 1;
146
/** Equals to D3DSWAPEFFECT_FLIP */
147
public static final int SWAP_FLIP = 2;
148
/** Equals to D3DSWAPEFFECT_COPY */
149
public static final int SWAP_COPY = 3;
150
/*
151
* SurfaceTypes
152
*/
153
private static final String DESC_D3D_SURFACE = "D3D Surface";
154
private static final String DESC_D3D_SURFACE_RTT =
155
"D3D Surface (render-to-texture)";
156
private static final String DESC_D3D_TEXTURE = "D3D Texture";
157
158
// REMIND: regarding ArgbPre??
159
static final SurfaceType D3DSurface =
160
SurfaceType.Any.deriveSubType(DESC_D3D_SURFACE,
161
PixelConverter.ArgbPre.instance);
162
static final SurfaceType D3DSurfaceRTT =
163
D3DSurface.deriveSubType(DESC_D3D_SURFACE_RTT);
164
static final SurfaceType D3DTexture =
165
SurfaceType.Any.deriveSubType(DESC_D3D_TEXTURE);
166
167
private int type;
168
private int width, height;
169
private final double scaleX;
170
private final double scaleY;
171
// these fields are set from the native code when the surface is
172
// initialized
173
private int nativeWidth, nativeHeight;
174
protected WComponentPeer peer;
175
private Image offscreenImage;
176
protected D3DGraphicsDevice graphicsDevice;
177
178
private int swapEffect;
179
private VSyncType syncType;
180
private int backBuffersNum;
181
182
private WritableRasterNative wrn;
183
184
protected static D3DRenderer d3dRenderPipe;
185
protected static PixelToParallelogramConverter d3dTxRenderPipe;
186
protected static ParallelogramPipe d3dAAPgramPipe;
187
protected static D3DTextRenderer d3dTextPipe;
188
protected static D3DDrawImage d3dImagePipe;
189
190
private native boolean initTexture(long pData, boolean isRTT,
191
boolean isOpaque);
192
private native boolean initFlipBackbuffer(long pData, long pPeerData,
193
int numbuffers,
194
int swapEffect, int syncType);
195
private native boolean initRTSurface(long pData, boolean isOpaque);
196
private native void initOps(int screen, int width, int height);
197
198
static {
199
D3DRenderQueue rq = D3DRenderQueue.getInstance();
200
d3dImagePipe = new D3DDrawImage();
201
d3dTextPipe = new D3DTextRenderer(rq);
202
d3dRenderPipe = new D3DRenderer(rq);
203
if (GraphicsPrimitive.tracingEnabled()) {
204
d3dTextPipe = d3dTextPipe.traceWrap();
205
d3dRenderPipe = d3dRenderPipe.traceWrap();
206
//The wrapped d3dRenderPipe will wrap the AA pipe as well...
207
//d3dAAPgramPipe = d3dRenderPipe.traceWrap();
208
}
209
d3dAAPgramPipe = d3dRenderPipe.getAAParallelogramPipe();
210
d3dTxRenderPipe =
211
new PixelToParallelogramConverter(d3dRenderPipe, d3dRenderPipe,
212
1.0, 0.25, true);
213
214
D3DBlitLoops.register();
215
D3DMaskFill.register();
216
D3DMaskBlit.register();
217
}
218
219
protected D3DSurfaceData(WComponentPeer peer, D3DGraphicsConfig gc,
220
int width, int height, Image image,
221
ColorModel cm, int numBackBuffers,
222
int swapEffect, VSyncType vSyncType,
223
int type)
224
{
225
super(getCustomSurfaceType(type), cm);
226
this.graphicsDevice = gc.getD3DDevice();
227
this.scaleX = type == TEXTURE ? 1 : graphicsDevice.getDefaultScaleX();
228
this.scaleY = type == TEXTURE ? 1 : graphicsDevice.getDefaultScaleY();
229
this.peer = peer;
230
this.type = type;
231
232
if (scaleX == 1 && scaleY == 1) {
233
this.width = width;
234
this.height = height;
235
} else if (peer instanceof WWindowPeer) {
236
Dimension scaledSize = ((WWindowPeer) peer).getScaledWindowSize();
237
this.width = scaledSize.width;
238
this.height = scaledSize.height;
239
} else {
240
this.width = Region.clipRound(width * scaleX);
241
this.height = Region.clipRound(height * scaleY);
242
}
243
244
this.offscreenImage = image;
245
this.backBuffersNum = numBackBuffers;
246
this.swapEffect = swapEffect;
247
this.syncType = vSyncType;
248
249
initOps(graphicsDevice.getScreen(), this.width, this.height);
250
if (type == WINDOW) {
251
// we put the surface into the "lost"
252
// state; it will be restored by the D3DScreenUpdateManager
253
// prior to rendering to it for the first time. This is done
254
// so that vram is not wasted for surfaces never rendered to
255
setSurfaceLost(true);
256
} else {
257
initSurface();
258
}
259
setBlitProxyKey(gc.getProxyKey());
260
}
261
262
@Override
263
public double getDefaultScaleX() {
264
return scaleX;
265
}
266
267
@Override
268
public double getDefaultScaleY() {
269
return scaleY;
270
}
271
272
@Override
273
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
274
return D3DSurfaceDataProxy.
275
createProxy(srcData,
276
(D3DGraphicsConfig)graphicsDevice.getDefaultConfiguration());
277
}
278
279
/**
280
* Creates a SurfaceData object representing the back buffer of a
281
* double-buffered on-screen Window.
282
*/
283
public static D3DSurfaceData createData(WComponentPeer peer, Image image) {
284
D3DGraphicsConfig gc = getGC(peer);
285
if (gc == null || !peer.isAccelCapable()) {
286
return null;
287
}
288
BufferCapabilities caps = peer.getBackBufferCaps();
289
VSyncType vSyncType = VSYNC_DEFAULT;
290
if (caps instanceof ExtendedBufferCapabilities) {
291
vSyncType = ((ExtendedBufferCapabilities)caps).getVSync();
292
}
293
Rectangle r = peer.getBounds();
294
BufferCapabilities.FlipContents flip = caps.getFlipContents();
295
int swapEffect;
296
if (flip == FlipContents.COPIED) {
297
swapEffect = SWAP_COPY;
298
} else if (flip == FlipContents.PRIOR) {
299
swapEffect = SWAP_FLIP;
300
} else { // flip == FlipContents.UNDEFINED || .BACKGROUND
301
swapEffect = SWAP_DISCARD;
302
}
303
return new D3DSurfaceData(peer, gc, r.width, r.height,
304
image, peer.getColorModel(),
305
peer.getBackBuffersNum(),
306
swapEffect, vSyncType, FLIP_BACKBUFFER);
307
}
308
309
/**
310
* Returns a WINDOW type of surface - a
311
* swap chain which serves as an on-screen surface,
312
* handled by the D3DScreenUpdateManager.
313
*
314
* Note that the native surface is not initialized
315
* when the surface is created to avoid using excessive
316
* resources, and the surface is placed into the lost
317
* state. It will be restored prior to any rendering
318
* to it.
319
*
320
* @param peer peer for which the onscreen surface is to be created
321
* @return a D3DWindowSurfaceData (flip chain) surface
322
*/
323
public static D3DSurfaceData createData(WComponentPeer peer) {
324
D3DGraphicsConfig gc = getGC(peer);
325
if (gc == null || !peer.isAccelCapable()) {
326
return null;
327
}
328
return new D3DWindowSurfaceData(peer, gc);
329
}
330
331
/**
332
* Creates a SurfaceData object representing an off-screen buffer (either
333
* a plain surface or Texture).
334
*/
335
public static D3DSurfaceData createData(D3DGraphicsConfig gc,
336
int width, int height,
337
ColorModel cm,
338
Image image, int type)
339
{
340
if (type == RT_TEXTURE) {
341
boolean isOpaque = cm.getTransparency() == Transparency.OPAQUE;
342
int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
343
if (!gc.getD3DDevice().isCapPresent(cap)) {
344
type = RT_PLAIN;
345
}
346
}
347
D3DSurfaceData ret = null;
348
try {
349
ret = new D3DSurfaceData(null, gc, width, height,
350
image, cm, 0, SWAP_DISCARD, VSYNC_DEFAULT,
351
type);
352
} catch (InvalidPipeException ipe) {
353
// try again - we might have ran out of vram, and rt textures
354
// could take up more than a plain surface, so it might succeed
355
if (type == RT_TEXTURE) {
356
// If a RT_TEXTURE was requested do not attempt to create a
357
// plain surface. (note that RT_TEXTURE can only be requested
358
// from a VI so the cast is safe)
359
if (((SunVolatileImage)image).getForcedAccelSurfaceType() !=
360
RT_TEXTURE)
361
{
362
type = RT_PLAIN;
363
ret = new D3DSurfaceData(null, gc, width, height,
364
image, cm, 0, SWAP_DISCARD,
365
VSYNC_DEFAULT, type);
366
}
367
}
368
}
369
return ret;
370
}
371
372
/**
373
* Returns the appropriate SurfaceType corresponding to the given D3D
374
* surface type constant (e.g. TEXTURE -> D3DTexture).
375
*/
376
private static SurfaceType getCustomSurfaceType(int d3dType) {
377
switch (d3dType) {
378
case TEXTURE:
379
return D3DTexture;
380
case RT_TEXTURE:
381
return D3DSurfaceRTT;
382
default:
383
return D3DSurface;
384
}
385
}
386
387
private boolean initSurfaceNow() {
388
boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
389
switch (type) {
390
case RT_PLAIN:
391
return initRTSurface(getNativeOps(), isOpaque);
392
case TEXTURE:
393
return initTexture(getNativeOps(), false/*isRTT*/, isOpaque);
394
case RT_TEXTURE:
395
return initTexture(getNativeOps(), true/*isRTT*/, isOpaque);
396
// REMIND: we may want to pass the exact type to the native
397
// level here so that we could choose the right presentation
398
// interval for the frontbuffer (immediate vs v-synced)
399
case WINDOW:
400
case FLIP_BACKBUFFER:
401
return initFlipBackbuffer(getNativeOps(), peer.getData(),
402
backBuffersNum, swapEffect,
403
syncType.id());
404
default:
405
return false;
406
}
407
}
408
409
/**
410
* Initializes the appropriate D3D offscreen surface based on the value
411
* of the type parameter. If the surface creation fails for any reason,
412
* an OutOfMemoryError will be thrown.
413
*/
414
protected void initSurface() {
415
// any time we create or restore the surface, recreate the raster
416
synchronized (this) {
417
wrn = null;
418
}
419
// REMIND: somewhere a puppy died
420
class Status {
421
boolean success = false;
422
};
423
final Status status = new Status();
424
D3DRenderQueue rq = D3DRenderQueue.getInstance();
425
rq.lock();
426
try {
427
rq.flushAndInvokeNow(new Runnable() {
428
public void run() {
429
status.success = initSurfaceNow();
430
}
431
});
432
if (!status.success) {
433
throw new InvalidPipeException("Error creating D3DSurface");
434
}
435
} finally {
436
rq.unlock();
437
}
438
}
439
440
/**
441
* Returns the D3DContext for the GraphicsConfig associated with this
442
* surface.
443
*/
444
public final D3DContext getContext() {
445
return graphicsDevice.getContext();
446
}
447
448
/**
449
* Returns one of the surface type constants defined above.
450
*/
451
public final int getType() {
452
return type;
453
}
454
455
private static native int dbGetPixelNative(long pData, int x, int y);
456
private static native void dbSetPixelNative(long pData, int x, int y,
457
int pixel);
458
static class D3DDataBufferNative extends DataBufferNative {
459
int pixel;
460
protected D3DDataBufferNative(SurfaceData sData,
461
int type, int w, int h)
462
{
463
super(sData, type, w, h);
464
}
465
466
protected int getElem(final int x, final int y,
467
final SurfaceData sData)
468
{
469
if (sData.isSurfaceLost()) {
470
return 0;
471
}
472
473
int retPixel;
474
D3DRenderQueue rq = D3DRenderQueue.getInstance();
475
rq.lock();
476
try {
477
rq.flushAndInvokeNow(new Runnable() {
478
public void run() {
479
pixel = dbGetPixelNative(sData.getNativeOps(), x, y);
480
}
481
});
482
} finally {
483
retPixel = pixel;
484
rq.unlock();
485
}
486
return retPixel;
487
}
488
489
protected void setElem(final int x, final int y, final int pixel,
490
final SurfaceData sData)
491
{
492
if (sData.isSurfaceLost()) {
493
return;
494
}
495
496
D3DRenderQueue rq = D3DRenderQueue.getInstance();
497
rq.lock();
498
try {
499
rq.flushAndInvokeNow(new Runnable() {
500
public void run() {
501
dbSetPixelNative(sData.getNativeOps(), x, y, pixel);
502
}
503
});
504
sData.markDirty();
505
} finally {
506
rq.unlock();
507
}
508
}
509
}
510
511
public synchronized Raster getRaster(int x, int y, int w, int h) {
512
if (wrn == null) {
513
DirectColorModel dcm = (DirectColorModel)getColorModel();
514
SampleModel smHw;
515
int dataType = 0;
516
int scanStride = width;
517
518
if (dcm.getPixelSize() > 16) {
519
dataType = DataBuffer.TYPE_INT;
520
} else {
521
// 15, 16
522
dataType = DataBuffer.TYPE_USHORT;
523
}
524
525
// note that we have to use the surface width and height here,
526
// not the passed w,h
527
smHw = new SinglePixelPackedSampleModel(dataType, width, height,
528
scanStride, dcm.getMasks());
529
DataBuffer dbn = new D3DDataBufferNative(this, dataType,
530
width, height);
531
wrn = WritableRasterNative.createNativeRaster(smHw, dbn);
532
}
533
534
return wrn;
535
}
536
537
/**
538
* For now, we can only render LCD text if:
539
* - the pixel shaders are available, and
540
* - blending is disabled, and
541
* - the source color is opaque
542
* - and the destination is opaque
543
*/
544
public boolean canRenderLCDText(SunGraphics2D sg2d) {
545
return
546
graphicsDevice.isCapPresent(CAPS_LCD_SHADER) &&
547
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
548
sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
549
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
550
}
551
552
/**
553
* If acceleration should no longer be used for this surface.
554
* This implementation flags to the manager that it should no
555
* longer attempt to re-create a D3DSurface.
556
*/
557
void disableAccelerationForSurface() {
558
if (offscreenImage != null) {
559
SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
560
if (sm instanceof D3DVolatileSurfaceManager) {
561
setSurfaceLost(true);
562
((D3DVolatileSurfaceManager)sm).setAccelerationEnabled(false);
563
}
564
}
565
}
566
567
public void validatePipe(SunGraphics2D sg2d) {
568
TextPipe textpipe;
569
boolean validated = false;
570
571
// REMIND: the D3D pipeline doesn't support XOR!, more
572
// fixes will be needed below. For now we disable D3D rendering
573
// for the surface which had any XOR rendering done to.
574
if (sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
575
super.validatePipe(sg2d);
576
sg2d.imagepipe = d3dImagePipe;
577
disableAccelerationForSurface();
578
return;
579
}
580
581
// D3DTextRenderer handles both AA and non-AA text, but
582
// only works with the following modes:
583
// (Note: For LCD text we only enter this code path if
584
// canRenderLCDText() has already validated that the mode is
585
// CompositeType.SrcNoEa (opaque color), which will be subsumed
586
// by the CompositeType.SrcNoEa (any color) test below.)
587
588
if (/* CompositeType.SrcNoEa (any color) */
589
(sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
590
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) ||
591
592
/* CompositeType.SrcOver (any color) */
593
(sg2d.compositeState == SunGraphics2D.COMP_ALPHA &&
594
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
595
(((AlphaComposite)sg2d.composite).getRule() ==
596
AlphaComposite.SRC_OVER)) ||
597
598
/* CompositeType.Xor (any color) */
599
(sg2d.compositeState == SunGraphics2D.COMP_XOR &&
600
sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR))
601
{
602
textpipe = d3dTextPipe;
603
} else {
604
// do this to initialize textpipe correctly; we will attempt
605
// to override the non-text pipes below
606
super.validatePipe(sg2d);
607
textpipe = sg2d.textpipe;
608
validated = true;
609
}
610
611
PixelToParallelogramConverter txPipe = null;
612
D3DRenderer nonTxPipe = null;
613
614
if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
615
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
616
if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {
617
txPipe = d3dTxRenderPipe;
618
nonTxPipe = d3dRenderPipe;
619
}
620
} else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
621
if (D3DPaints.isValid(sg2d)) {
622
txPipe = d3dTxRenderPipe;
623
nonTxPipe = d3dRenderPipe;
624
}
625
// custom paints handled by super.validatePipe() below
626
}
627
} else {
628
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
629
if (graphicsDevice.isCapPresent(CAPS_AA_SHADER) &&
630
(sg2d.imageComp == CompositeType.SrcOverNoEa ||
631
sg2d.imageComp == CompositeType.SrcOver))
632
{
633
if (!validated) {
634
super.validatePipe(sg2d);
635
validated = true;
636
}
637
PixelToParallelogramConverter aaConverter =
638
new PixelToParallelogramConverter(sg2d.shapepipe,
639
d3dAAPgramPipe,
640
1.0/8.0, 0.499,
641
false);
642
sg2d.drawpipe = aaConverter;
643
sg2d.fillpipe = aaConverter;
644
sg2d.shapepipe = aaConverter;
645
} else if (sg2d.compositeState == SunGraphics2D.COMP_XOR) {
646
// install the solid pipes when AA and XOR are both enabled
647
txPipe = d3dTxRenderPipe;
648
nonTxPipe = d3dRenderPipe;
649
}
650
}
651
// other cases handled by super.validatePipe() below
652
}
653
654
if (txPipe != null) {
655
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
656
sg2d.drawpipe = txPipe;
657
sg2d.fillpipe = txPipe;
658
} else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
659
sg2d.drawpipe = txPipe;
660
sg2d.fillpipe = nonTxPipe;
661
} else {
662
sg2d.drawpipe = nonTxPipe;
663
sg2d.fillpipe = nonTxPipe;
664
}
665
// Note that we use the transforming pipe here because it
666
// will examine the shape and possibly perform an optimized
667
// operation if it can be simplified. The simplifications
668
// will be valid for all STROKE and TRANSFORM types.
669
sg2d.shapepipe = txPipe;
670
} else {
671
if (!validated) {
672
super.validatePipe(sg2d);
673
}
674
}
675
676
// install the text pipe based on our earlier decision
677
sg2d.textpipe = textpipe;
678
679
// always override the image pipe with the specialized D3D pipe
680
sg2d.imagepipe = d3dImagePipe;
681
}
682
683
@Override
684
protected MaskFill getMaskFill(SunGraphics2D sg2d) {
685
if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR) {
686
/*
687
* We can only accelerate non-Color MaskFill operations if
688
* all of the following conditions hold true:
689
* - there is an implementation for the given paintState
690
* - the current Paint can be accelerated for this destination
691
* - multitexturing is available (since we need to modulate
692
* the alpha mask texture with the paint texture)
693
*
694
* In all other cases, we return null, in which case the
695
* validation code will choose a more general software-based loop.
696
*/
697
if (!D3DPaints.isValid(sg2d) ||
698
!graphicsDevice.isCapPresent(CAPS_MULTITEXTURE))
699
{
700
return null;
701
}
702
}
703
return super.getMaskFill(sg2d);
704
}
705
706
@Override
707
public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
708
int dx, int dy) {
709
if (sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
710
return false;
711
}
712
d3dRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
713
return true;
714
}
715
716
@Override
717
public void flush() {
718
D3DRenderQueue rq = D3DRenderQueue.getInstance();
719
rq.lock();
720
try {
721
RenderBuffer buf = rq.getBuffer();
722
rq.ensureCapacityAndAlignment(12, 4);
723
buf.putInt(FLUSH_SURFACE);
724
buf.putLong(getNativeOps());
725
726
// this call is expected to complete synchronously, so flush now
727
rq.flushNow();
728
} finally {
729
rq.unlock();
730
}
731
}
732
733
/**
734
* Disposes the native resources associated with the given D3DSurfaceData
735
* (referenced by the pData parameter). This method is invoked from
736
* the native Dispose() method from the Disposer thread when the
737
* Java-level D3DSurfaceData object is about to go away.
738
*/
739
static void dispose(long pData) {
740
D3DRenderQueue rq = D3DRenderQueue.getInstance();
741
rq.lock();
742
try {
743
RenderBuffer buf = rq.getBuffer();
744
rq.ensureCapacityAndAlignment(12, 4);
745
buf.putInt(DISPOSE_SURFACE);
746
buf.putLong(pData);
747
748
// this call is expected to complete synchronously, so flush now
749
rq.flushNow();
750
} finally {
751
rq.unlock();
752
}
753
}
754
755
static void swapBuffers(D3DSurfaceData sd,
756
final int x1, final int y1,
757
final int x2, final int y2)
758
{
759
long pData = sd.getNativeOps();
760
D3DRenderQueue rq = D3DRenderQueue.getInstance();
761
// swapBuffers can be called from the toolkit thread by swing, we
762
// should detect this and prevent the deadlocks
763
if (D3DRenderQueue.isRenderQueueThread()) {
764
if (!rq.tryLock()) {
765
// if we could not obtain the lock, repaint the area
766
// that was supposed to be swapped, and no-op this swap
767
final Component target = (Component)sd.getPeer().getTarget();
768
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
769
public void run() {
770
double scaleX = sd.getDefaultScaleX();
771
double scaleY = sd.getDefaultScaleY();
772
if (scaleX > 1 || scaleY > 1) {
773
int sx1 = (int) Math.floor(x1 / scaleX);
774
int sy1 = (int) Math.floor(y1 / scaleY);
775
int sx2 = (int) Math.ceil(x2 / scaleX);
776
int sy2 = (int) Math.ceil(y2 / scaleY);
777
target.repaint(sx1, sy1, sx2 - sx1, sy2 - sy1);
778
} else {
779
target.repaint(x1, y1, x2 - x1, y2 - y1);
780
}
781
}
782
});
783
return;
784
}
785
} else {
786
rq.lock();
787
}
788
try {
789
RenderBuffer buf = rq.getBuffer();
790
rq.ensureCapacityAndAlignment(28, 4);
791
buf.putInt(SWAP_BUFFERS);
792
buf.putLong(pData);
793
buf.putInt(x1);
794
buf.putInt(y1);
795
buf.putInt(x2);
796
buf.putInt(y2);
797
rq.flushNow();
798
} finally {
799
rq.unlock();
800
}
801
}
802
803
/**
804
* Returns destination Image associated with this SurfaceData.
805
*/
806
public Object getDestination() {
807
return offscreenImage;
808
}
809
810
public Rectangle getBounds() {
811
if (type == FLIP_BACKBUFFER || type == WINDOW) {
812
double scaleX = getDefaultScaleX();
813
double scaleY = getDefaultScaleY();
814
Rectangle r = peer.getBounds();
815
r.x = r.y = 0;
816
r.width = Region.clipRound(r.width * scaleX);
817
r.height = Region.clipRound(r.height * scaleY);
818
return r;
819
} else {
820
return new Rectangle(width, height);
821
}
822
}
823
824
public Rectangle getNativeBounds() {
825
D3DRenderQueue rq = D3DRenderQueue.getInstance();
826
// need to lock to make sure nativeWidth and Height are consistent
827
// since they are set from the render thread from the native
828
// level
829
rq.lock();
830
try {
831
// REMIND: use xyoffsets?
832
return new Rectangle(nativeWidth, nativeHeight);
833
} finally {
834
rq.unlock();
835
}
836
}
837
838
839
public GraphicsConfiguration getDeviceConfiguration() {
840
return graphicsDevice.getDefaultConfiguration();
841
}
842
843
public SurfaceData getReplacement() {
844
return restoreContents(offscreenImage);
845
}
846
847
private static D3DGraphicsConfig getGC(WComponentPeer peer) {
848
GraphicsConfiguration gc;
849
if (peer != null) {
850
gc = peer.getGraphicsConfiguration();
851
} else {
852
GraphicsEnvironment env =
853
GraphicsEnvironment.getLocalGraphicsEnvironment();
854
GraphicsDevice gd = env.getDefaultScreenDevice();
855
gc = gd.getDefaultConfiguration();
856
}
857
return (gc instanceof D3DGraphicsConfig) ? (D3DGraphicsConfig)gc : null;
858
}
859
860
/**
861
* Attempts to restore the surface by initializing the native data
862
*/
863
void restoreSurface() {
864
initSurface();
865
}
866
867
WComponentPeer getPeer() {
868
return peer;
869
}
870
871
/**
872
* We need to let the surface manager know that the surface is lost so
873
* that for example BufferStrategy.contentsLost() returns correct result.
874
* Normally the status of contentsLost is set in validate(), but in some
875
* cases (like Swing's buffer per window) we intentionally don't call
876
* validate from the toolkit thread but only check for the BS status.
877
*/
878
@Override
879
public void setSurfaceLost(boolean lost) {
880
super.setSurfaceLost(lost);
881
if (lost && offscreenImage != null) {
882
SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
883
sm.acceleratedSurfaceLost();
884
}
885
}
886
887
private static native long getNativeResourceNative(long sdops, int resType);
888
/**
889
* Returns a pointer to the native resource of specified {@code resType}
890
* associated with this surface.
891
*
892
* Specifically, for {@code D3DSurfaceData} this method returns pointers of
893
* the following:
894
* <pre>
895
* TEXTURE - (IDirect3DTexture9*)
896
* RT_TEXTURE, RT_PLAIN - (IDirect3DSurface9*)
897
* FLIP_BACKBUFFER - (IDirect3DSwapChain9*)
898
* D3D_DEVICE_RESOURCE - (IDirect3DDevice9*)
899
* </pre>
900
*
901
* Multiple resources may be available for some types (i.e. for render to
902
* texture one could retrieve both a destination surface by specifying
903
* RT_TEXTURE, and a texture by using TEXTURE).
904
*
905
* Note: the pointer returned by this method is only valid on the rendering
906
* thread.
907
*
908
* @return pointer to the native resource of specified type or 0L if
909
* such resource doesn't exist or can not be retrieved.
910
* @see sun.java2d.pipe.hw.AccelSurface#getNativeResource
911
*/
912
public long getNativeResource(int resType) {
913
return getNativeResourceNative(getNativeOps(), resType);
914
}
915
916
/**
917
* Class representing an on-screen d3d surface. Since d3d can't
918
* render to the screen directly, it is implemented as a swap chain,
919
* controlled by D3DScreenUpdateManager.
920
*
921
* @see D3DScreenUpdateManager
922
*/
923
public static class D3DWindowSurfaceData extends D3DSurfaceData {
924
StateTracker dirtyTracker;
925
926
public D3DWindowSurfaceData(WComponentPeer peer,
927
D3DGraphicsConfig gc)
928
{
929
super(peer, gc,
930
peer.getBounds().width, peer.getBounds().height,
931
null, peer.getColorModel(), 1, SWAP_COPY, VSYNC_DEFAULT,
932
WINDOW);
933
dirtyTracker = getStateTracker();
934
}
935
936
/**
937
* {@inheritDoc}
938
*
939
* Overridden to use ScreenUpdateManager to obtain the replacement
940
* surface.
941
*
942
* @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface
943
*/
944
@Override
945
public SurfaceData getReplacement() {
946
ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
947
return mgr.getReplacementScreenSurface(peer, this);
948
}
949
950
/**
951
* Returns destination Component associated with this SurfaceData.
952
*/
953
@Override
954
public Object getDestination() {
955
return peer.getTarget();
956
}
957
958
@Override
959
void disableAccelerationForSurface() {
960
// for on-screen surfaces we need to make sure a backup GDI surface is
961
// is used until a new one is set (which may happen during a resize). We
962
// don't want the screen update maanger to replace the surface right way
963
// because it causes repainting issues in Swing, so we invalidate it,
964
// this will prevent SUM from issuing a replaceSurfaceData call.
965
setSurfaceLost(true);
966
invalidate();
967
flush();
968
peer.disableAcceleration();
969
ScreenUpdateManager.getInstance().dropScreenSurface(this);
970
}
971
972
@Override
973
void restoreSurface() {
974
if (!peer.isAccelCapable()) {
975
throw new InvalidPipeException("Onscreen acceleration " +
976
"disabled for this surface");
977
}
978
Window fsw = graphicsDevice.getFullScreenWindow();
979
if (fsw != null && fsw != peer.getTarget()) {
980
throw new InvalidPipeException("Can't restore onscreen surface"+
981
" when in full-screen mode");
982
}
983
super.restoreSurface();
984
// if initialization was unsuccessful, an IPE will be thrown
985
// and the surface will remain lost
986
setSurfaceLost(false);
987
988
// This is to make sure the render target is reset after this
989
// surface is restored. The reason for this is that sometimes this
990
// surface can be restored from multiple threads (the screen update
991
// manager's thread and app's rendering thread) at the same time,
992
// and when that happens the second restoration will create the
993
// native resource which will not be set as render target because
994
// the BufferedContext's validate method will think that since the
995
// surface data object didn't change then the current render target
996
// is correct and no rendering will appear on the screen.
997
D3DRenderQueue rq = D3DRenderQueue.getInstance();
998
rq.lock();
999
try {
1000
getContext().invalidateContext();
1001
} finally {
1002
rq.unlock();
1003
}
1004
}
1005
1006
public boolean isDirty() {
1007
return !dirtyTracker.isCurrent();
1008
}
1009
1010
public void markClean() {
1011
dirtyTracker = getStateTracker();
1012
}
1013
}
1014
1015
/**
1016
* Updates the layered window with the contents of the surface.
1017
*
1018
* @param pd3dsd pointer to the D3DSDOps structure
1019
* @param pData pointer to the AwtWindow peer data
1020
* @param w width of the window
1021
* @param h height of the window
1022
* @see sun.awt.windows.TranslucentWindowPainter
1023
*/
1024
public static native boolean updateWindowAccelImpl(long pd3dsd, long pData,
1025
int w, int h);
1026
}
1027
1028