feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
888
jdkSrc/jdk8/sun/java2d/d3d/D3DBlitLoops.java
Normal file
888
jdkSrc/jdk8/sun/java2d/d3d/D3DBlitLoops.java
Normal file
@@ -0,0 +1,888 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.annotation.Native;
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.ScaledBlit;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.TransformBlit;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import sun.java2d.windows.GDIWindowSurfaceData;
|
||||
|
||||
final class D3DBlitLoops {
|
||||
|
||||
static void register() {
|
||||
Blit blitIntArgbPreToSurface =
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE);
|
||||
Blit blitIntArgbPreToTexture =
|
||||
new D3DSwToTextureBlit(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE);
|
||||
TransformBlit transformBlitIntArgbPreToSurface =
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE);
|
||||
GraphicsPrimitive[] primitives = {
|
||||
// prevent D3DSurface -> Screen blits
|
||||
new D3DSurfaceToGDIWindowSurfaceBlit(),
|
||||
new D3DSurfaceToGDIWindowSurfaceScale(),
|
||||
new D3DSurfaceToGDIWindowSurfaceTransform(),
|
||||
|
||||
// surface->surface ops
|
||||
new D3DSurfaceToSurfaceBlit(),
|
||||
new D3DSurfaceToSurfaceScale(),
|
||||
new D3DSurfaceToSurfaceTransform(),
|
||||
|
||||
// render-to-texture surface->surface ops
|
||||
new D3DRTTSurfaceToSurfaceBlit(),
|
||||
new D3DRTTSurfaceToSurfaceScale(),
|
||||
new D3DRTTSurfaceToSurfaceTransform(),
|
||||
|
||||
// surface->sw ops
|
||||
new D3DSurfaceToSwBlit(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
|
||||
// sw->surface ops
|
||||
blitIntArgbPreToSurface,
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToSurfaceBlit(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToSurfaceBlit(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
new D3DGeneralBlit(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
blitIntArgbPreToSurface),
|
||||
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntArgbPre,
|
||||
D3DSurfaceData.ST_INT_ARGB_PRE),
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToSurfaceScale(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToSurfaceScale(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToSurfaceScale(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToSurfaceScale(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToSurfaceTransform(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToSurfaceTransform(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
transformBlitIntArgbPreToSurface,
|
||||
|
||||
new D3DGeneralTransformedBlit(transformBlitIntArgbPreToSurface),
|
||||
|
||||
// texture->surface ops
|
||||
new D3DTextureToSurfaceBlit(),
|
||||
new D3DTextureToSurfaceScale(),
|
||||
new D3DTextureToSurfaceTransform(),
|
||||
|
||||
// sw->texture ops
|
||||
blitIntArgbPreToTexture,
|
||||
new D3DSwToTextureBlit(SurfaceType.IntRgb,
|
||||
D3DSurfaceData.ST_INT_RGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.IntArgb,
|
||||
D3DSurfaceData.ST_INT_ARGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.IntBgr,
|
||||
D3DSurfaceData.ST_INT_BGR),
|
||||
new D3DSwToTextureBlit(SurfaceType.ThreeByteBgr,
|
||||
D3DSurfaceData.ST_3BYTE_BGR),
|
||||
new D3DSwToTextureBlit(SurfaceType.Ushort565Rgb,
|
||||
D3DSurfaceData.ST_USHORT_565_RGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.Ushort555Rgb,
|
||||
D3DSurfaceData.ST_USHORT_555_RGB),
|
||||
new D3DSwToTextureBlit(SurfaceType.ByteIndexed,
|
||||
D3DSurfaceData.ST_BYTE_INDEXED),
|
||||
// REMIND: we don't have a native sw loop to back this loop up
|
||||
// new D3DSwToTextureBlit(SurfaceType.ByteIndexedBm,
|
||||
// D3DSurfaceData.ST_BYTE_INDEXED_BM),
|
||||
new D3DGeneralBlit(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.SrcNoEa,
|
||||
blitIntArgbPreToTexture),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following offsets are used to pack the parameters in
|
||||
* createPackedParams(). (They are also used at the native level when
|
||||
* unpacking the params.)
|
||||
*/
|
||||
@Native private static final int OFFSET_SRCTYPE = 16;
|
||||
@Native private static final int OFFSET_HINT = 8;
|
||||
@Native private static final int OFFSET_TEXTURE = 3;
|
||||
@Native private static final int OFFSET_RTT = 2;
|
||||
@Native private static final int OFFSET_XFORM = 1;
|
||||
@Native private static final int OFFSET_ISOBLIT = 0;
|
||||
|
||||
/**
|
||||
* Packs the given parameters into a single int value in order to save
|
||||
* space on the rendering queue.
|
||||
*/
|
||||
private static int createPackedParams(boolean isoblit, boolean texture,
|
||||
boolean rtt, boolean xform,
|
||||
int hint, int srctype)
|
||||
{
|
||||
return
|
||||
((srctype << OFFSET_SRCTYPE) |
|
||||
(hint << OFFSET_HINT ) |
|
||||
((texture ? 1 : 0) << OFFSET_TEXTURE) |
|
||||
((rtt ? 1 : 0) << OFFSET_RTT ) |
|
||||
((xform ? 1 : 0) << OFFSET_XFORM ) |
|
||||
((isoblit ? 1 : 0) << OFFSET_ISOBLIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues a BLIT operation with the given parameters. Note that the
|
||||
* RenderQueue lock must be held before calling this method.
|
||||
*/
|
||||
private static void enqueueBlit(RenderQueue rq,
|
||||
SurfaceData src, SurfaceData dst,
|
||||
int packedParams,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(72, 24);
|
||||
buf.putInt(BLIT);
|
||||
buf.putInt(packedParams);
|
||||
buf.putInt(sx1).putInt(sy1);
|
||||
buf.putInt(sx2).putInt(sy2);
|
||||
buf.putDouble(dx1).putDouble(dy1);
|
||||
buf.putDouble(dx2).putDouble(dy2);
|
||||
buf.putLong(src.getNativeOps());
|
||||
buf.putLong(dst.getNativeOps());
|
||||
}
|
||||
|
||||
static void Blit(SurfaceData srcData, SurfaceData dstData,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform xform, int hint,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
int srctype, boolean texture)
|
||||
{
|
||||
int ctxflags = 0;
|
||||
if (srcData.getTransparency() == Transparency.OPAQUE) {
|
||||
ctxflags |= D3DContext.SRC_IS_OPAQUE;
|
||||
}
|
||||
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure the RenderQueue keeps a hard reference to the
|
||||
// source (sysmem) SurfaceData to prevent it from being
|
||||
// disposed while the operation is processed on the QFT
|
||||
rq.addReference(srcData);
|
||||
|
||||
if (texture) {
|
||||
// make sure we have a current context before uploading
|
||||
// the sysmem data to the texture object
|
||||
D3DContext.setScratchSurface(d3dDst.getContext());
|
||||
} else {
|
||||
D3DContext.validateContext(d3dDst, d3dDst,
|
||||
clip, comp, xform, null, null,
|
||||
ctxflags);
|
||||
}
|
||||
|
||||
int packedParams = createPackedParams(false, texture,
|
||||
false, xform != null,
|
||||
hint, srctype);
|
||||
enqueueBlit(rq, srcData, dstData,
|
||||
packedParams,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
|
||||
// always flush immediately, since we (currently) have no means
|
||||
// of tracking changes to the system memory surface
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
|
||||
if (d3dDst.getType() == D3DSurfaceData.WINDOW) {
|
||||
// flush immediately when copying to the screen to improve
|
||||
// responsiveness of applications using VI or BI backbuffers
|
||||
D3DScreenUpdateManager mgr =
|
||||
(D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
|
||||
mgr.runUpdateNow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The srcImg and biop parameters are only used when invoked
|
||||
* from the D3DBufImgOps.renderImageWithOp() method; in all other cases,
|
||||
* this method can be called with null values for those two parameters,
|
||||
* and they will be effectively ignored.
|
||||
*/
|
||||
static void IsoBlit(SurfaceData srcData, SurfaceData dstData,
|
||||
BufferedImage srcImg, BufferedImageOp biop,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform xform, int hint,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
boolean texture)
|
||||
{
|
||||
int ctxflags = 0;
|
||||
if (srcData.getTransparency() == Transparency.OPAQUE) {
|
||||
ctxflags |= D3DContext.SRC_IS_OPAQUE;
|
||||
}
|
||||
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
boolean rtt = false;
|
||||
rq.lock();
|
||||
try {
|
||||
D3DSurfaceData d3dSrc = (D3DSurfaceData)srcData;
|
||||
int srctype = d3dSrc.getType();
|
||||
D3DSurfaceData srcCtxData = d3dSrc;
|
||||
if (srctype == D3DSurfaceData.TEXTURE) {
|
||||
rtt = false;
|
||||
} else {
|
||||
// the source is a backbuffer, or render-to-texture
|
||||
// surface; we set rtt to true to differentiate this kind
|
||||
// of surface from a regular texture object
|
||||
rtt = true;
|
||||
}
|
||||
|
||||
D3DContext.validateContext(srcCtxData, d3dDst,
|
||||
clip, comp, xform, null, null,
|
||||
ctxflags);
|
||||
|
||||
if (biop != null) {
|
||||
D3DBufImgOps.enableBufImgOp(rq, d3dSrc, srcImg, biop);
|
||||
}
|
||||
|
||||
int packedParams = createPackedParams(true, texture,
|
||||
rtt, xform != null,
|
||||
hint, 0 /*unused*/);
|
||||
enqueueBlit(rq, srcData, dstData,
|
||||
packedParams,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2);
|
||||
|
||||
if (biop != null) {
|
||||
D3DBufImgOps.disableBufImgOp(rq, biop);
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
|
||||
if (rtt && (d3dDst.getType() == D3DSurfaceData.WINDOW)) {
|
||||
// we only have to flush immediately when copying from a
|
||||
// (non-texture) surface to the screen; otherwise Swing apps
|
||||
// might appear unresponsive until the auto-flush completes
|
||||
D3DScreenUpdateManager mgr =
|
||||
(D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
|
||||
mgr.runUpdateNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSurfaceBlit extends Blit {
|
||||
|
||||
D3DSurfaceToSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DSurfaceToSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DSurfaceToSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DRTTSurfaceToSurfaceBlit extends Blit {
|
||||
|
||||
D3DRTTSurfaceToSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DRTTSurfaceToSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DRTTSurfaceToSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DRTTSurfaceToSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DRTTSurfaceToSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DSurfaceRTT,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToSwBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
// REMIND: destination will actually be opaque/premultiplied...
|
||||
D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.SrcNoEa,
|
||||
dstType);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
// make sure the RenderQueue keeps a hard reference to the
|
||||
// destination (sysmem) SurfaceData to prevent it from being
|
||||
// disposed while the operation is processed on the QFT
|
||||
rq.addReference(dst);
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
D3DContext.setScratchSurface(((D3DSurfaceData)src).getContext());
|
||||
|
||||
rq.ensureCapacityAndAlignment(48, 32);
|
||||
buf.putInt(SURFACE_TO_SW_BLIT);
|
||||
buf.putInt(sx).putInt(sy);
|
||||
buf.putInt(dx).putInt(dy);
|
||||
buf.putInt(w).putInt(h);
|
||||
buf.putInt(typeval);
|
||||
buf.putLong(src.getNativeOps());
|
||||
buf.putLong(dst.getNativeOps());
|
||||
|
||||
// always flush immediately
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToSurfaceBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToSurfaceBlit(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToSurfaceScale extends ScaledBlit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToSurfaceScale(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToSurfaceTransform extends TransformBlit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToSurfaceTransform(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, false);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSwToTextureBlit extends Blit {
|
||||
|
||||
private int typeval;
|
||||
|
||||
D3DSwToTextureBlit(SurfaceType srcType, int typeval) {
|
||||
super(srcType,
|
||||
CompositeType.SrcNoEa,
|
||||
D3DSurfaceData.D3DTexture);
|
||||
this.typeval = typeval;
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.Blit(src, dst,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
typeval, true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DTextureToSurfaceBlit extends Blit {
|
||||
|
||||
D3DTextureToSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DTextureToSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DTextureToSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, null,
|
||||
AffineTransformOp.TYPE_NEAREST_NEIGHBOR,
|
||||
sx1, sy1, sx2, sy2,
|
||||
dx1, dy1, dx2, dy2,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DTextureToSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DTextureToSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DTexture,
|
||||
CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
D3DBlitLoops.IsoBlit(src, dst,
|
||||
null, null,
|
||||
comp, clip, at, hint,
|
||||
sx, sy, sx+w, sy+h,
|
||||
dx, dy, dx+w, dy+h,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general Blit implementation converts any source surface to an
|
||||
* intermediate IntArgbPre surface, and then uses the more specific
|
||||
* IntArgbPre->D3DSurface/Texture loop to get the intermediate
|
||||
* (premultiplied) surface down to D3D using simple blit.
|
||||
*/
|
||||
class D3DGeneralBlit extends Blit {
|
||||
|
||||
private final Blit performop;
|
||||
private WeakReference srcTmp;
|
||||
|
||||
D3DGeneralBlit(SurfaceType dstType,
|
||||
CompositeType compType,
|
||||
Blit performop)
|
||||
{
|
||||
super(SurfaceType.Any, compType, dstType);
|
||||
this.performop = performop;
|
||||
}
|
||||
|
||||
public synchronized void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
|
||||
SurfaceData cachedSrc = null;
|
||||
if (srcTmp != null) {
|
||||
// use cached intermediate surface, if available
|
||||
cachedSrc = (SurfaceData)srcTmp.get();
|
||||
}
|
||||
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, sx, sy, w, h,
|
||||
cachedSrc, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
// copy IntArgbPre intermediate surface to D3D surface
|
||||
performop.Blit(src, dst, comp, clip,
|
||||
0, 0, dx, dy, w, h);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This general TransformedBlit implementation converts any source surface to an
|
||||
* intermediate IntArgbPre surface, and then uses the more specific
|
||||
* IntArgbPre->D3DSurface/Texture loop to get the intermediate
|
||||
* (premultiplied) surface down to D3D using simple transformBlit.
|
||||
*/
|
||||
final class D3DGeneralTransformedBlit extends TransformBlit {
|
||||
|
||||
private final TransformBlit performop;
|
||||
private WeakReference<SurfaceData> srcTmp;
|
||||
|
||||
D3DGeneralTransformedBlit(final TransformBlit performop) {
|
||||
super(SurfaceType.Any, CompositeType.AnyAlpha,
|
||||
D3DSurfaceData.D3DSurface);
|
||||
this.performop = performop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint, int srcx,
|
||||
int srcy, int dstx, int dsty, int width,
|
||||
int height){
|
||||
Blit convertsrc = Blit.getFromCache(src.getSurfaceType(),
|
||||
CompositeType.SrcNoEa,
|
||||
SurfaceType.IntArgbPre);
|
||||
// use cached intermediate surface, if available
|
||||
final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null;
|
||||
// convert source to IntArgbPre
|
||||
src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc,
|
||||
BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
|
||||
// transform IntArgbPre intermediate surface to D3D surface
|
||||
performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty,
|
||||
width, height);
|
||||
|
||||
if (src != cachedSrc) {
|
||||
// cache the intermediate surface
|
||||
srcTmp = new WeakReference<>(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following classes prohibit copying D3DSurfaces to the screen
|
||||
* (the D3D->sysmem->GDI path is known to be very very slow).
|
||||
*
|
||||
* Note: we used to disable hw acceleration for the surafce manager associated
|
||||
* with the source surface in these loops but it proved to be too cautious.
|
||||
*
|
||||
* In most cases d3d->screen copy happens only during some transitional
|
||||
* period where the accelerated destination surface is being recreated or
|
||||
* restored (for example, when Swing's backbuffer VI is copied to the screen
|
||||
* but the D3DScreenSurfaceManager couldn't restore its surface).
|
||||
*
|
||||
* An exception is if for some reason we could not enable accelerated on-screen
|
||||
* rendering for this window for some permanent reason (like window being too
|
||||
* small, or a present BufferStrategy).
|
||||
*
|
||||
* This meant that we'd disable hw acceleration after the first failure
|
||||
* completely (at least until the src image is recreated which in case of
|
||||
* Swing back-buffer happens only after resize).
|
||||
*
|
||||
* Now we delegate to the VISM to figure out if the acceleration needs to
|
||||
* be disabled or if we can wait for a while until the onscreen accelerated
|
||||
* can resume (by marking the source surface lost and making sure the
|
||||
* VISM has a chance to use the backup surface).
|
||||
*
|
||||
*/
|
||||
|
||||
class D3DSurfaceToGDIWindowSurfaceBlit extends Blit {
|
||||
|
||||
D3DSurfaceToGDIWindowSurfaceBlit() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
GDIWindowSurfaceData.AnyGdi);
|
||||
}
|
||||
@Override
|
||||
public void Blit(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx, int sy, int dx, int dy, int w, int h)
|
||||
{
|
||||
// see comment above
|
||||
D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class D3DSurfaceToGDIWindowSurfaceScale extends ScaledBlit {
|
||||
|
||||
D3DSurfaceToGDIWindowSurfaceScale() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
GDIWindowSurfaceData.AnyGdi);
|
||||
}
|
||||
@Override
|
||||
public void Scale(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
int sx1, int sy1,
|
||||
int sx2, int sy2,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
// see comment above
|
||||
D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
class D3DSurfaceToGDIWindowSurfaceTransform extends TransformBlit {
|
||||
|
||||
D3DSurfaceToGDIWindowSurfaceTransform() {
|
||||
super(D3DSurfaceData.D3DSurface,
|
||||
CompositeType.AnyAlpha,
|
||||
GDIWindowSurfaceData.AnyGdi);
|
||||
}
|
||||
@Override
|
||||
public void Transform(SurfaceData src, SurfaceData dst,
|
||||
Composite comp, Region clip,
|
||||
AffineTransform at, int hint,
|
||||
int sx, int sy, int dx, int dy,
|
||||
int w, int h)
|
||||
{
|
||||
// see comment above
|
||||
D3DVolatileSurfaceManager.handleVItoScreenOp(src, dst);
|
||||
}
|
||||
}
|
||||
116
jdkSrc/jdk8/sun/java2d/d3d/D3DBufImgOps.java
Normal file
116
jdkSrc/jdk8/sun/java2d/d3d/D3DBufImgOps.java
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.LookupOp;
|
||||
import java.awt.image.RescaleOp;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.pipe.BufferedBufImgOps;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
|
||||
class D3DBufImgOps extends BufferedBufImgOps {
|
||||
|
||||
/**
|
||||
* This method is called from D3DDrawImage.transformImage() only. It
|
||||
* validates the provided BufferedImageOp to determine whether the op
|
||||
* is one that can be accelerated by the D3D pipeline. If the operation
|
||||
* cannot be completed for any reason, this method returns false;
|
||||
* otherwise, the given BufferedImage is rendered to the destination
|
||||
* using the provided BufferedImageOp and this method returns true.
|
||||
*/
|
||||
static boolean renderImageWithOp(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp biop, int x, int y)
|
||||
{
|
||||
// Validate the provided BufferedImage (make sure it is one that
|
||||
// is supported, and that its properties are acceleratable)
|
||||
if (biop instanceof ConvolveOp) {
|
||||
if (!isConvolveOpValid((ConvolveOp)biop)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof RescaleOp) {
|
||||
if (!isRescaleOpValid((RescaleOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof LookupOp) {
|
||||
if (!isLookupOpValid((LookupOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// No acceleration for other BufferedImageOps (yet)
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
if (!(dstData instanceof D3DSurfaceData) ||
|
||||
(sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) ||
|
||||
(sg.compositeState > SunGraphics2D.COMP_ALPHA))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img, sg.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
// REMIND: this hack tries to ensure that we have a cached texture
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(img, sg.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the source surface is actually a texture and that
|
||||
// shaders are supported
|
||||
D3DSurfaceData d3dSrc = (D3DSurfaceData)srcData;
|
||||
D3DGraphicsDevice gd =
|
||||
(D3DGraphicsDevice)d3dSrc.getDeviceConfiguration().getDevice();
|
||||
if (d3dSrc.getType() != D3DSurfaceData.TEXTURE ||
|
||||
!gd.isCapPresent(CAPS_LCD_SHADER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int sw = img.getWidth();
|
||||
int sh = img.getHeight();
|
||||
D3DBlitLoops.IsoBlit(srcData, dstData,
|
||||
img, biop,
|
||||
sg.composite, sg.getCompClip(),
|
||||
sg.transform, sg.interpolationType,
|
||||
0, 0, sw, sh,
|
||||
x, y, x+sw, y+sh,
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
190
jdkSrc/jdk8/sun/java2d/d3d/D3DContext.java
Normal file
190
jdkSrc/jdk8/sun/java2d/d3d/D3DContext.java
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.lang.annotation.Native;
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.pipe.hw.ContextCapabilities.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
|
||||
/**
|
||||
* Note that the RenderQueue lock must be acquired before calling any of
|
||||
* the methods in this class.
|
||||
*/
|
||||
class D3DContext extends BufferedContext {
|
||||
|
||||
private final D3DGraphicsDevice device;
|
||||
|
||||
D3DContext(RenderQueue rq, D3DGraphicsDevice device) {
|
||||
super(rq);
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the currentContext field to ensure that we properly
|
||||
* revalidate the D3DContext (make it current, etc.) next time through
|
||||
* the validate() method. This is typically invoked from methods
|
||||
* that affect the current context state (e.g. disposing a context or
|
||||
* surface).
|
||||
*/
|
||||
static void invalidateCurrentContext() {
|
||||
// assert D3DRenderQueue.getInstance().lock.isHeldByCurrentThread();
|
||||
|
||||
// invalidate the current Java-level context so that we
|
||||
// revalidate everything the next time around
|
||||
if (currentContext != null) {
|
||||
currentContext.invalidateContext();
|
||||
currentContext = null;
|
||||
}
|
||||
|
||||
// invalidate the context reference at the native level, and
|
||||
// then flush the queue so that we have no pending operations
|
||||
// dependent on the current context
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.ensureCapacity(4);
|
||||
rq.getBuffer().putInt(INVALIDATE_CONTEXT);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current context on the native level to be the one passed as
|
||||
* the argument.
|
||||
* If the context is not the same as the defaultContext the latter
|
||||
* will be reset to null.
|
||||
*
|
||||
* This call is needed when copying from a SW surface to a Texture
|
||||
* (the upload test) or copying from d3d to SW surface to make sure we
|
||||
* have the correct current context.
|
||||
*
|
||||
* @param d3dc the context to be made current on the native level
|
||||
*/
|
||||
static void setScratchSurface(D3DContext d3dc) {
|
||||
// assert D3DRenderQueue.getInstance().lock.isHeldByCurrentThread();
|
||||
|
||||
// invalidate the current context
|
||||
if (d3dc != currentContext) {
|
||||
currentContext = null;
|
||||
}
|
||||
|
||||
// set the scratch context
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacity(8);
|
||||
buf.putInt(SET_SCRATCH_SURFACE);
|
||||
buf.putInt(d3dc.getDevice().getScreen());
|
||||
}
|
||||
|
||||
public RenderQueue getRenderQueue() {
|
||||
return D3DRenderQueue.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveState() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
|
||||
// reset all attributes of this and current contexts
|
||||
invalidateContext();
|
||||
invalidateCurrentContext();
|
||||
|
||||
setScratchSurface(this);
|
||||
|
||||
// save the state on the native level
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(SAVE_STATE);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreState() {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
|
||||
// reset all attributes of this and current contexts
|
||||
invalidateContext();
|
||||
invalidateCurrentContext();
|
||||
|
||||
setScratchSurface(this);
|
||||
|
||||
// restore the state on the native level
|
||||
rq.ensureCapacity(4);
|
||||
buf.putInt(RESTORE_STATE);
|
||||
rq.flushNow();
|
||||
}
|
||||
|
||||
D3DGraphicsDevice getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
static class D3DContextCaps extends ContextCapabilities {
|
||||
/**
|
||||
* Indicates the presence of pixel shaders (v2.0 or greater).
|
||||
* This cap will only be set if the hardware supports the minimum number
|
||||
* of texture units.
|
||||
*/
|
||||
@Native static final int CAPS_LCD_SHADER = (FIRST_PRIVATE_CAP << 0);
|
||||
/**
|
||||
* Indicates the presence of pixel shaders (v2.0 or greater).
|
||||
* This cap will only be set if the hardware meets our
|
||||
* minimum requirements.
|
||||
*/
|
||||
@Native static final int CAPS_BIOP_SHADER = (FIRST_PRIVATE_CAP << 1);
|
||||
/**
|
||||
* Indicates that the device was successfully initialized and can
|
||||
* be safely used.
|
||||
*/
|
||||
@Native static final int CAPS_DEVICE_OK = (FIRST_PRIVATE_CAP << 2);
|
||||
/**
|
||||
* Indicates that the device has all of the necessary capabilities
|
||||
* to support the Antialiasing Pixel Shader program.
|
||||
*/
|
||||
@Native static final int CAPS_AA_SHADER = (FIRST_PRIVATE_CAP << 3);
|
||||
|
||||
D3DContextCaps(int caps, String adapterId) {
|
||||
super(caps, adapterId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuffer buf = new StringBuffer(super.toString());
|
||||
if ((caps & CAPS_LCD_SHADER) != 0) {
|
||||
buf.append("CAPS_LCD_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_BIOP_SHADER) != 0) {
|
||||
buf.append("CAPS_BIOP_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_AA_SHADER) != 0) {
|
||||
buf.append("CAPS_AA_SHADER|");
|
||||
}
|
||||
if ((caps & CAPS_DEVICE_OK) != 0) {
|
||||
buf.append("CAPS_DEVICE_OK|");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
101
jdkSrc/jdk8/sun/java2d/d3d/D3DDrawImage.java
Normal file
101
jdkSrc/jdk8/sun/java2d/d3d/D3DDrawImage.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Image;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.TransformBlit;
|
||||
import sun.java2d.pipe.DrawImage;
|
||||
|
||||
public class D3DDrawImage extends DrawImage {
|
||||
|
||||
@Override
|
||||
protected void renderImageXform(SunGraphics2D sg, Image img,
|
||||
AffineTransform tx, int interpType,
|
||||
int sx1, int sy1, int sx2, int sy2,
|
||||
Color bgColor)
|
||||
{
|
||||
// punt to the MediaLib-based transformImage() in the superclass if:
|
||||
// - bicubic interpolation is specified
|
||||
// - a background color is specified and will be used
|
||||
// - an appropriate TransformBlit primitive could not be found
|
||||
if (interpType != AffineTransformOp.TYPE_BICUBIC) {
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img,
|
||||
sg.TRANSFORM_GENERIC,
|
||||
sg.imageComp,
|
||||
bgColor);
|
||||
|
||||
if (srcData != null && !isBgOperation(srcData, bgColor)) {
|
||||
SurfaceType srcType = srcData.getSurfaceType();
|
||||
SurfaceType dstType = dstData.getSurfaceType();
|
||||
TransformBlit blit = TransformBlit.getFromCache(srcType,
|
||||
sg.imageComp,
|
||||
dstType);
|
||||
|
||||
if (blit != null) {
|
||||
blit.Transform(srcData, dstData,
|
||||
sg.composite, sg.getCompClip(),
|
||||
tx, interpType,
|
||||
sx1, sy1, 0, 0, sx2-sx1, sy2-sy1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.renderImageXform(sg, img, tx, interpType,
|
||||
sx1, sy1, sx2, sy2, bgColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformImage(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp op, int x, int y)
|
||||
{
|
||||
if (op != null) {
|
||||
if (op instanceof AffineTransformOp) {
|
||||
AffineTransformOp atop = (AffineTransformOp) op;
|
||||
transformImage(sg, img, x, y,
|
||||
atop.getTransform(),
|
||||
atop.getInterpolationType());
|
||||
return;
|
||||
} else {
|
||||
if (D3DBufImgOps.renderImageWithOp(sg, img, op, x, y)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
img = op.filter(img, null);
|
||||
}
|
||||
copyImage(sg, img, x, y, null);
|
||||
}
|
||||
}
|
||||
327
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsConfig.java
Normal file
327
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsConfig.java
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.BufferCapabilities.FlipContents;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.Surface;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.hw.AccelDeviceEventNotifier;
|
||||
import sun.java2d.pipe.hw.AccelTypedVolatileImage;
|
||||
import sun.java2d.pipe.hw.AccelGraphicsConfig;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import sun.java2d.pipe.hw.AccelDeviceEventListener;
|
||||
|
||||
public class D3DGraphicsConfig
|
||||
extends Win32GraphicsConfig
|
||||
implements AccelGraphicsConfig
|
||||
{
|
||||
private static ImageCapabilities imageCaps = new D3DImageCaps();
|
||||
|
||||
private BufferCapabilities bufferCaps;
|
||||
private D3DGraphicsDevice device;
|
||||
|
||||
protected D3DGraphicsConfig(D3DGraphicsDevice device) {
|
||||
super(device, 0);
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
public SurfaceData createManagedSurface(int w, int h, int transparency) {
|
||||
return D3DSurfaceData.createData(this, w, h,
|
||||
getColorModel(transparency),
|
||||
null,
|
||||
D3DSurfaceData.TEXTURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void displayChanged() {
|
||||
super.displayChanged();
|
||||
// the context could hold a reference to a D3DSurfaceData, which in
|
||||
// turn has a reference back to this D3DGraphicsConfig, so in order
|
||||
// for this instance to be disposed we need to break the connection
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
D3DContext.invalidateCurrentContext();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
switch (transparency) {
|
||||
case Transparency.OPAQUE:
|
||||
// REMIND: once the ColorModel spec is changed, this should be
|
||||
// an opaque premultiplied DCM...
|
||||
return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
|
||||
case Transparency.BITMASK:
|
||||
return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
|
||||
case Transparency.TRANSLUCENT:
|
||||
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
||||
return new DirectColorModel(cs, 32,
|
||||
0xff0000, 0xff00, 0xff, 0xff000000,
|
||||
true, DataBuffer.TYPE_INT);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ("D3DGraphicsConfig[dev="+screen+",pixfmt="+visual+"]");
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods are invoked from WComponentPeer.java rather
|
||||
* than having the Win32-dependent implementations hardcoded in that
|
||||
* class. This way the appropriate actions are taken based on the peer's
|
||||
* GraphicsConfig, whether it is a Win32GraphicsConfig or a
|
||||
* D3DGraphicsConfig.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new SurfaceData that will be associated with the given
|
||||
* WComponentPeer. D3D9 doesn't allow rendering to the screen,
|
||||
* so a GDI surface will be returned.
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData createSurfaceData(WComponentPeer peer,
|
||||
int numBackBuffers)
|
||||
{
|
||||
return super.createSurfaceData(peer, numBackBuffers);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following methods correspond to the multibuffering methods in
|
||||
* WComponentPeer.java...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks that the requested configuration is natively supported; if not,
|
||||
* an AWTException is thrown.
|
||||
*/
|
||||
@Override
|
||||
public void assertOperationSupported(Component target,
|
||||
int numBuffers,
|
||||
BufferCapabilities caps)
|
||||
throws AWTException
|
||||
{
|
||||
if (numBuffers < 2 || numBuffers > 4) {
|
||||
throw new AWTException("Only 2-4 buffers supported");
|
||||
}
|
||||
if (caps.getFlipContents() == BufferCapabilities.FlipContents.COPIED &&
|
||||
numBuffers != 2)
|
||||
{
|
||||
throw new AWTException("FlipContents.COPIED is only" +
|
||||
"supported for 2 buffers");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a D3D-based backbuffer for the given peer and returns the
|
||||
* image wrapper.
|
||||
*/
|
||||
@Override
|
||||
public VolatileImage createBackBuffer(WComponentPeer peer) {
|
||||
Component target = (Component)peer.getTarget();
|
||||
// it is possible for the component to have size 0x0, adjust it to
|
||||
// be at least 1x1 to avoid IAE
|
||||
int w = Math.max(1, target.getWidth());
|
||||
int h = Math.max(1, target.getHeight());
|
||||
return new SunVolatileImage(target, w, h, Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the native D3D flip operation for the given target Component.
|
||||
*/
|
||||
@Override
|
||||
public void flip(WComponentPeer peer,
|
||||
Component target, VolatileImage backBuffer,
|
||||
int x1, int y1, int x2, int y2,
|
||||
BufferCapabilities.FlipContents flipAction)
|
||||
{
|
||||
// REMIND: we should actually get a surface data for the
|
||||
// backBuffer's VI
|
||||
SurfaceManager d3dvsm =
|
||||
SurfaceManager.getManager(backBuffer);
|
||||
SurfaceData sd = d3dvsm.getPrimarySurfaceData();
|
||||
if (sd instanceof D3DSurfaceData) {
|
||||
D3DSurfaceData d3dsd = (D3DSurfaceData)sd;
|
||||
D3DSurfaceData.swapBuffers(d3dsd, x1, y1, x2, y2);
|
||||
} else {
|
||||
// the surface was likely lost could not have been restored
|
||||
Graphics g = peer.getGraphics();
|
||||
try {
|
||||
g.drawImage(backBuffer,
|
||||
x1, y1, x2, y2,
|
||||
x1, y1, x2, y2,
|
||||
null);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
|
||||
Graphics g = backBuffer.getGraphics();
|
||||
try {
|
||||
g.setColor(target.getBackground());
|
||||
g.fillRect(0, 0,
|
||||
backBuffer.getWidth(),
|
||||
backBuffer.getHeight());
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class D3DBufferCaps extends BufferCapabilities {
|
||||
public D3DBufferCaps() {
|
||||
// REMIND: should we indicate that the front-buffer
|
||||
// (the on-screen rendering) is not accelerated?
|
||||
super(imageCaps, imageCaps, FlipContents.UNDEFINED);
|
||||
}
|
||||
@Override
|
||||
public boolean isMultiBufferAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferCapabilities getBufferCapabilities() {
|
||||
if (bufferCaps == null) {
|
||||
bufferCaps = new D3DBufferCaps();
|
||||
}
|
||||
return bufferCaps;
|
||||
}
|
||||
|
||||
private static class D3DImageCaps extends ImageCapabilities {
|
||||
private D3DImageCaps() {
|
||||
super(true);
|
||||
}
|
||||
@Override
|
||||
public boolean isTrueVolatile() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCapabilities getImageCapabilities() {
|
||||
return imageCaps;
|
||||
}
|
||||
|
||||
D3DGraphicsDevice getD3DDevice() {
|
||||
return device;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
|
||||
*/
|
||||
@Override
|
||||
public D3DContext getContext() {
|
||||
return device.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
|
||||
*/
|
||||
@Override
|
||||
public VolatileImage
|
||||
createCompatibleVolatileImage(int width, int height,
|
||||
int transparency, int type)
|
||||
{
|
||||
if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
|
||||
transparency == Transparency.BITMASK)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
boolean isOpaque = transparency == Transparency.OPAQUE;
|
||||
if (type == RT_TEXTURE) {
|
||||
int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
|
||||
if (!device.isCapPresent(cap)) {
|
||||
return null;
|
||||
}
|
||||
} else if (type == RT_PLAIN) {
|
||||
if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
|
||||
transparency, type);
|
||||
Surface sd = vi.getDestSurface();
|
||||
if (!(sd instanceof AccelSurface) ||
|
||||
((AccelSurface)sd).getType() != type)
|
||||
{
|
||||
vi.flush();
|
||||
vi = null;
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
|
||||
*/
|
||||
@Override
|
||||
public ContextCapabilities getContextCapabilities() {
|
||||
return device.getContextCapabilities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDeviceEventListener(AccelDeviceEventListener l) {
|
||||
AccelDeviceEventNotifier.addListener(l, device.getScreen());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeDeviceEventListener(AccelDeviceEventListener l) {
|
||||
AccelDeviceEventNotifier.removeListener(l);
|
||||
}
|
||||
}
|
||||
503
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsDevice.java
Normal file
503
jdkSrc/jdk8/sun/java2d/d3d/D3DGraphicsDevice.java
Normal file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Dialog;
|
||||
import java.awt.DisplayMode;
|
||||
import java.awt.Frame;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.util.ArrayList;
|
||||
import sun.awt.Win32GraphicsDevice;
|
||||
import sun.awt.windows.WWindowPeer;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import sun.java2d.windows.WindowsFlags;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import sun.java2d.d3d.D3DContext.D3DContextCaps;
|
||||
|
||||
/**
|
||||
* This class implements D3D-specific functionality, such as fullscreen
|
||||
* exclusive mode and display changes. It is kept separate from
|
||||
* Win32GraphicsDevice to help avoid overburdening the parent class.
|
||||
*/
|
||||
public class D3DGraphicsDevice extends Win32GraphicsDevice {
|
||||
private D3DContext context;
|
||||
|
||||
private static boolean d3dAvailable;
|
||||
|
||||
private ContextCapabilities d3dCaps;
|
||||
|
||||
private static native boolean initD3D();
|
||||
|
||||
static {
|
||||
// loading the library doesn't help because we need the
|
||||
// toolkit thread running, so we have to call getDefaultToolkit()
|
||||
Toolkit.getDefaultToolkit();
|
||||
d3dAvailable = initD3D();
|
||||
if (d3dAvailable) {
|
||||
// we don't use pixel formats for the d3d pipeline
|
||||
pfDisabled = true;
|
||||
sun.misc.PerfCounter.getD3DAvailable().set(1);
|
||||
} else {
|
||||
sun.misc.PerfCounter.getD3DAvailable().set(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to construct a Direct3D-enabled GraphicsDevice.
|
||||
*
|
||||
* @return a D3DGraphicsDevice if it could be created
|
||||
* successfully, null otherwise.
|
||||
*/
|
||||
public static D3DGraphicsDevice createDevice(int screen) {
|
||||
if (!d3dAvailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ContextCapabilities d3dCaps = getDeviceCaps(screen);
|
||||
// could not initialize the device successfully
|
||||
if ((d3dCaps.getCaps() & CAPS_DEVICE_OK) == 0) {
|
||||
if (WindowsFlags.isD3DVerbose()) {
|
||||
System.out.println("Could not enable Direct3D pipeline on " +
|
||||
"screen " + screen);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (WindowsFlags.isD3DVerbose()) {
|
||||
System.out.println("Direct3D pipeline enabled on screen " + screen);
|
||||
}
|
||||
|
||||
D3DGraphicsDevice gd = new D3DGraphicsDevice(screen, d3dCaps);
|
||||
return gd;
|
||||
}
|
||||
|
||||
private static native int getDeviceCapsNative(int screen);
|
||||
private static native String getDeviceIdNative(int screen);
|
||||
private static ContextCapabilities getDeviceCaps(final int screen) {
|
||||
ContextCapabilities d3dCaps = null;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
int caps;
|
||||
String id;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.caps = getDeviceCapsNative(screen);
|
||||
res.id = getDeviceIdNative(screen);
|
||||
}
|
||||
});
|
||||
d3dCaps = new D3DContextCaps(res.caps, res.id);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
|
||||
return d3dCaps != null ? d3dCaps : new D3DContextCaps(CAPS_EMPTY, null);
|
||||
}
|
||||
|
||||
public final boolean isCapPresent(int cap) {
|
||||
return ((d3dCaps.getCaps() & cap) != 0);
|
||||
}
|
||||
|
||||
private D3DGraphicsDevice(int screennum, ContextCapabilities d3dCaps) {
|
||||
super(screennum);
|
||||
descString = "D3DGraphicsDevice[screen="+screennum;
|
||||
this.d3dCaps = d3dCaps;
|
||||
context = new D3DContext(D3DRenderQueue.getInstance(), this);
|
||||
}
|
||||
|
||||
public boolean isD3DEnabledOnDevice() {
|
||||
return isValid() && isCapPresent(CAPS_DEVICE_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if d3d pipeline has been successfully initialized.
|
||||
* @return true if d3d pipeline is initialized, false otherwise
|
||||
*/
|
||||
public static boolean isD3DAvailable() {
|
||||
return d3dAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the owning Frame for a given Window. Used in setFSWindow below
|
||||
* to set the properties of the owning Frame when a Window goes
|
||||
* into fullscreen mode.
|
||||
*/
|
||||
private Frame getToplevelOwner(Window w) {
|
||||
Window owner = w;
|
||||
while (owner != null) {
|
||||
owner = owner.getOwner();
|
||||
if (owner instanceof Frame) {
|
||||
return (Frame) owner;
|
||||
}
|
||||
}
|
||||
// could get here if passed Window is an owner-less Dialog
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean fsStatus;
|
||||
private Rectangle ownerOrigBounds = null;
|
||||
private boolean ownerWasVisible;
|
||||
private Window realFSWindow;
|
||||
private WindowListener fsWindowListener;
|
||||
private boolean fsWindowWasAlwaysOnTop;
|
||||
private static native boolean enterFullScreenExclusiveNative(int screen,
|
||||
long hwnd);
|
||||
|
||||
@Override
|
||||
protected void enterFullScreenExclusive(final int screen, WindowPeer wp)
|
||||
{
|
||||
final WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
|
||||
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
long hwnd = wpeer.getHWnd();
|
||||
if (hwnd == 0l) {
|
||||
// window is disposed
|
||||
fsStatus = false;
|
||||
return;
|
||||
}
|
||||
fsStatus = enterFullScreenExclusiveNative(screen, hwnd);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
if (!fsStatus) {
|
||||
super.enterFullScreenExclusive(screen, wp);
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean exitFullScreenExclusiveNative(int screen);
|
||||
@Override
|
||||
protected void exitFullScreenExclusive(final int screen, WindowPeer w) {
|
||||
if (fsStatus) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
exitFullScreenExclusiveNative(screen);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
} else {
|
||||
super.exitFullScreenExclusive(screen, w);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WindowAdapter class for the full-screen frame, responsible for
|
||||
* restoring the devices. This is important to do because unless the device
|
||||
* is restored it will not go back into the FS mode once alt+tabbed out.
|
||||
* This is a problem for windows for which we do not do any d3d-related
|
||||
* operations (like when we disabled on-screen rendering).
|
||||
*
|
||||
* REMIND: we create an instance per each full-screen device while a single
|
||||
* instance would suffice (but requires more management).
|
||||
*/
|
||||
private static class D3DFSWindowAdapter extends WindowAdapter {
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
D3DRenderQueue.getInstance().restoreDevices();
|
||||
}
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
D3DRenderQueue.getInstance().restoreDevices();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addFSWindowListener(Window w) {
|
||||
// if the window is not a toplevel (has an owner) we have to use the
|
||||
// real toplevel to enter the full-screen mode with (4933099).
|
||||
if (!(w instanceof Frame) && !(w instanceof Dialog) &&
|
||||
(realFSWindow = getToplevelOwner(w)) != null)
|
||||
{
|
||||
ownerOrigBounds = realFSWindow.getBounds();
|
||||
WWindowPeer fp = (WWindowPeer)realFSWindow.getPeer();
|
||||
|
||||
ownerWasVisible = realFSWindow.isVisible();
|
||||
Rectangle r = w.getBounds();
|
||||
// we use operations on peer instead of component because calling
|
||||
// them on component will take the tree lock
|
||||
fp.reshape(r.x, r.y, r.width, r.height);
|
||||
fp.setVisible(true);
|
||||
} else {
|
||||
realFSWindow = w;
|
||||
}
|
||||
|
||||
fsWindowWasAlwaysOnTop = realFSWindow.isAlwaysOnTop();
|
||||
((WWindowPeer)realFSWindow.getPeer()).setAlwaysOnTop(true);
|
||||
|
||||
fsWindowListener = new D3DFSWindowAdapter();
|
||||
realFSWindow.addWindowListener(fsWindowListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFSWindowListener(Window w) {
|
||||
realFSWindow.removeWindowListener(fsWindowListener);
|
||||
fsWindowListener = null;
|
||||
|
||||
/**
|
||||
* Bug 4933099: There is some funny-business to deal with when this
|
||||
* method is called with a Window instead of a Frame. See 4836744
|
||||
* for more information on this. One side-effect of our workaround
|
||||
* for the problem is that the owning Frame of a Window may end
|
||||
* up getting resized during the fullscreen process. When we
|
||||
* return from fullscreen mode, we should resize the Frame to
|
||||
* its original size (just like the Window is being resized
|
||||
* to its original size in GraphicsDevice).
|
||||
*/
|
||||
WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
|
||||
if (wpeer != null) {
|
||||
if (ownerOrigBounds != null) {
|
||||
// if the window went into fs mode before it was realized it
|
||||
// could have (0,0) dimensions
|
||||
if (ownerOrigBounds.width == 0) ownerOrigBounds.width = 1;
|
||||
if (ownerOrigBounds.height == 0) ownerOrigBounds.height = 1;
|
||||
wpeer.reshape(ownerOrigBounds.x, ownerOrigBounds.y,
|
||||
ownerOrigBounds.width, ownerOrigBounds.height);
|
||||
if (!ownerWasVisible) {
|
||||
wpeer.setVisible(false);
|
||||
}
|
||||
ownerOrigBounds = null;
|
||||
}
|
||||
if (!fsWindowWasAlwaysOnTop) {
|
||||
wpeer.setAlwaysOnTop(false);
|
||||
}
|
||||
}
|
||||
|
||||
realFSWindow = null;
|
||||
}
|
||||
|
||||
private static native DisplayMode getCurrentDisplayModeNative(int screen);
|
||||
@Override
|
||||
protected DisplayMode getCurrentDisplayMode(final int screen) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
DisplayMode dm = null;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.dm = getCurrentDisplayModeNative(screen);
|
||||
}
|
||||
});
|
||||
if (res.dm == null) {
|
||||
return super.getCurrentDisplayMode(screen);
|
||||
}
|
||||
return res.dm;
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
private static native void configDisplayModeNative(int screen, long hwnd,
|
||||
int width, int height,
|
||||
int bitDepth,
|
||||
int refreshRate);
|
||||
@Override
|
||||
protected void configDisplayMode(final int screen, final WindowPeer w,
|
||||
final int width, final int height,
|
||||
final int bitDepth, final int refreshRate)
|
||||
{
|
||||
// we entered fs mode via gdi
|
||||
if (!fsStatus) {
|
||||
super.configDisplayMode(screen, w, width, height, bitDepth,
|
||||
refreshRate);
|
||||
return;
|
||||
}
|
||||
|
||||
final WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
|
||||
|
||||
// REMIND: we do this before we switch the display mode, so
|
||||
// the dimensions may be exceeding the dimensions of the screen,
|
||||
// is this a problem?
|
||||
|
||||
// update the bounds of the owner frame
|
||||
if (getFullScreenWindow() != realFSWindow) {
|
||||
Rectangle screenBounds = getDefaultConfiguration().getBounds();
|
||||
wpeer.reshape(screenBounds.x, screenBounds.y, width, height);
|
||||
}
|
||||
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
long hwnd = wpeer.getHWnd();
|
||||
if (hwnd == 0l) {
|
||||
// window is disposed
|
||||
return;
|
||||
}
|
||||
// REMIND: do we really need a window here?
|
||||
// we should probably just use the current one
|
||||
configDisplayModeNative(screen, hwnd, width, height,
|
||||
bitDepth, refreshRate);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static native void enumDisplayModesNative(int screen,
|
||||
ArrayList modes);
|
||||
@Override
|
||||
protected void enumDisplayModes(final int screen, final ArrayList modes) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
enumDisplayModesNative(screen, modes);
|
||||
}
|
||||
});
|
||||
if (modes.size() == 0) {
|
||||
modes.add(getCurrentDisplayModeNative(screen));
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static native long getAvailableAcceleratedMemoryNative(int screen);
|
||||
@Override
|
||||
public int getAvailableAcceleratedMemory() {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
long mem = 0L;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.mem = getAvailableAcceleratedMemoryNative(getScreen());
|
||||
}
|
||||
});
|
||||
return (int)res.mem;
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration[] getConfigurations() {
|
||||
if (configs == null) {
|
||||
if (isD3DEnabledOnDevice()) {
|
||||
defaultConfig = getDefaultConfiguration();
|
||||
if (defaultConfig != null) {
|
||||
configs = new GraphicsConfiguration[1];
|
||||
configs[0] = defaultConfig;
|
||||
return configs.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.getConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDefaultConfiguration() {
|
||||
if (defaultConfig == null) {
|
||||
if (isD3DEnabledOnDevice()) {
|
||||
defaultConfig = new D3DGraphicsConfig(this);
|
||||
} else {
|
||||
defaultConfig = super.getDefaultConfiguration();
|
||||
}
|
||||
}
|
||||
return defaultConfig;
|
||||
}
|
||||
|
||||
private static native boolean isD3DAvailableOnDeviceNative(int screen);
|
||||
// REMIND: this method is not used now, we use caps instead
|
||||
public static boolean isD3DAvailableOnDevice(final int screen) {
|
||||
if (!d3dAvailable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// REMIND: should we cache the result per device somehow,
|
||||
// and then reset and retry it on display change?
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
class Result {
|
||||
boolean avail = false;
|
||||
};
|
||||
final Result res = new Result();
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
res.avail = isD3DAvailableOnDeviceNative(screen);
|
||||
}
|
||||
});
|
||||
return res.avail;
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
D3DContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
ContextCapabilities getContextCapabilities() {
|
||||
return d3dCaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayChanged() {
|
||||
super.displayChanged();
|
||||
// REMIND: make sure this works when the device is lost and we don't
|
||||
// disable d3d too eagerly
|
||||
if (d3dAvailable) {
|
||||
d3dCaps = getDeviceCaps(getScreen());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidate(int defaultScreen) {
|
||||
super.invalidate(defaultScreen);
|
||||
// REMIND: this is a bit excessive, isD3DEnabledOnDevice will return
|
||||
// false anyway because the device is invalid
|
||||
d3dCaps = new D3DContextCaps(CAPS_EMPTY, null);
|
||||
}
|
||||
}
|
||||
69
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskBlit.java
Normal file
69
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskBlit.java
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.BufferedMaskBlit;
|
||||
import static sun.java2d.loops.CompositeType.*;
|
||||
import static sun.java2d.loops.SurfaceType.*;
|
||||
|
||||
class D3DMaskBlit extends BufferedMaskBlit {
|
||||
|
||||
static void register() {
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new D3DMaskBlit(IntArgb, SrcOver),
|
||||
new D3DMaskBlit(IntArgbPre, SrcOver),
|
||||
new D3DMaskBlit(IntRgb, SrcOver),
|
||||
new D3DMaskBlit(IntRgb, SrcNoEa),
|
||||
new D3DMaskBlit(IntBgr, SrcOver),
|
||||
new D3DMaskBlit(IntBgr, SrcNoEa),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
private D3DMaskBlit(SurfaceType srcType,
|
||||
CompositeType compType)
|
||||
{
|
||||
super(D3DRenderQueue.getInstance(),
|
||||
srcType, compType, D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContext(SurfaceData dstData,
|
||||
Composite comp, Region clip)
|
||||
{
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
|
||||
D3DContext.validateContext(d3dDst, d3dDst,
|
||||
clip, comp, null, null, null,
|
||||
D3DContext.NO_CONTEXT_FLAGS);
|
||||
}
|
||||
}
|
||||
82
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskFill.java
Normal file
82
jdkSrc/jdk8/sun/java2d/d3d/D3DMaskFill.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.pipe.BufferedMaskFill;
|
||||
import static sun.java2d.loops.CompositeType.*;
|
||||
import static sun.java2d.loops.SurfaceType.*;
|
||||
|
||||
class D3DMaskFill extends BufferedMaskFill {
|
||||
|
||||
static void register() {
|
||||
GraphicsPrimitive[] primitives = {
|
||||
new D3DMaskFill(AnyColor, SrcOver),
|
||||
new D3DMaskFill(OpaqueColor, SrcNoEa),
|
||||
new D3DMaskFill(GradientPaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueGradientPaint, SrcNoEa),
|
||||
new D3DMaskFill(LinearGradientPaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueLinearGradientPaint, SrcNoEa),
|
||||
new D3DMaskFill(RadialGradientPaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueRadialGradientPaint, SrcNoEa),
|
||||
new D3DMaskFill(TexturePaint, SrcOver),
|
||||
new D3DMaskFill(OpaqueTexturePaint, SrcNoEa),
|
||||
};
|
||||
GraphicsPrimitiveMgr.register(primitives);
|
||||
}
|
||||
|
||||
protected D3DMaskFill(SurfaceType srcType, CompositeType compType) {
|
||||
super(D3DRenderQueue.getInstance(),
|
||||
srcType, compType, D3DSurfaceData.D3DSurface);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void maskFill(int x, int y, int w, int h,
|
||||
int maskoff, int maskscan, int masklen,
|
||||
byte[] mask);
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d,
|
||||
Composite comp, int ctxflags)
|
||||
{
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData) sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " +
|
||||
sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), comp,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
}
|
||||
234
jdkSrc/jdk8/sun/java2d/d3d/D3DPaints.java
Normal file
234
jdkSrc/jdk8/sun/java2d/d3d/D3DPaints.java
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.LinearGradientPaint;
|
||||
import java.awt.MultipleGradientPaint;
|
||||
import java.awt.MultipleGradientPaint.ColorSpaceType;
|
||||
import java.awt.MultipleGradientPaint.CycleMethod;
|
||||
import java.awt.TexturePaint;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.lang.annotation.Native;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
|
||||
abstract class D3DPaints {
|
||||
|
||||
/**
|
||||
* Holds all registered implementations, using the corresponding
|
||||
* SunGraphics2D.PAINT_* constant as the hash key.
|
||||
*/
|
||||
private static Map<Integer, D3DPaints> impls =
|
||||
new HashMap<Integer, D3DPaints>(4, 1.0f);
|
||||
|
||||
static {
|
||||
impls.put(SunGraphics2D.PAINT_GRADIENT, new Gradient());
|
||||
impls.put(SunGraphics2D.PAINT_LIN_GRADIENT, new LinearGradient());
|
||||
impls.put(SunGraphics2D.PAINT_RAD_GRADIENT, new RadialGradient());
|
||||
impls.put(SunGraphics2D.PAINT_TEXTURE, new Texture());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to locate an implementation corresponding to the paint state
|
||||
* of the provided SunGraphics2D object. If no implementation can be
|
||||
* found, or if the paint cannot be accelerated under the conditions
|
||||
* of the SunGraphics2D, this method returns false; otherwise, returns
|
||||
* true.
|
||||
*/
|
||||
static boolean isValid(SunGraphics2D sg2d) {
|
||||
D3DPaints impl = impls.get(sg2d.paintState);
|
||||
return (impl != null && impl.isPaintValid(sg2d));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this implementation is able to accelerate the
|
||||
* Paint object associated with, and under the conditions of, the
|
||||
* provided SunGraphics2D instance; otherwise returns false.
|
||||
*/
|
||||
abstract boolean isPaintValid(SunGraphics2D sg2d);
|
||||
|
||||
/************************* GradientPaint support ****************************/
|
||||
|
||||
private static class Gradient extends D3DPaints {
|
||||
private Gradient() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given GradientPaint instance can be
|
||||
* used by the accelerated D3DPaints.Gradient implementation.
|
||||
* A GradientPaint is considered valid only if the destination
|
||||
* has support for fragment shaders.
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
dstData.getDeviceConfiguration().getDevice();
|
||||
return gd.isCapPresent(CAPS_LCD_SHADER);
|
||||
}
|
||||
}
|
||||
|
||||
/************************** TexturePaint support ****************************/
|
||||
|
||||
private static class Texture extends D3DPaints {
|
||||
private Texture() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given TexturePaint instance can be used by the
|
||||
* accelerated BufferedPaints.Texture implementation.
|
||||
*
|
||||
* A TexturePaint is considered valid if the following conditions
|
||||
* are met:
|
||||
* - the texture image dimensions are power-of-two
|
||||
* - the texture image can be (or is already) cached in a D3D
|
||||
* texture object
|
||||
*/
|
||||
@Override
|
||||
public boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
TexturePaint paint = (TexturePaint)sg2d.paint;
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
BufferedImage bi = paint.getImage();
|
||||
|
||||
// verify that the texture image dimensions are pow2
|
||||
D3DGraphicsDevice gd =
|
||||
(D3DGraphicsDevice)dstData.getDeviceConfiguration().getDevice();
|
||||
int imgw = bi.getWidth();
|
||||
int imgh = bi.getHeight();
|
||||
if (!gd.isCapPresent(CAPS_TEXNONPOW2)) {
|
||||
if ((imgw & (imgw - 1)) != 0 || (imgh & (imgh - 1)) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// verify that the texture image is square if it has to be
|
||||
if (!gd.isCapPresent(CAPS_TEXNONSQUARE) && imgw != imgh)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
// REMIND: this is a hack that attempts to cache the system
|
||||
// memory image from the TexturePaint instance into a
|
||||
// D3D texture...
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(bi, sg2d.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof D3DSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// verify that the source surface is actually a texture
|
||||
D3DSurfaceData d3dData = (D3DSurfaceData)srcData;
|
||||
if (d3dData.getType() != D3DSurfaceData.TEXTURE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/****************** Shared MultipleGradientPaint support ********************/
|
||||
|
||||
private static abstract class MultiGradient extends D3DPaints {
|
||||
|
||||
/**
|
||||
* Note that this number is lower than the MULTI_MAX_FRACTIONS
|
||||
* defined in the superclass. The D3D pipeline now uses a
|
||||
* slightly more complicated shader (to avoid the gradient banding
|
||||
* issues), which has a higher instruction count. To ensure that
|
||||
* all versions of the shader can be compiled for PS 2.0 hardware,
|
||||
* we need to cap this maximum value at 8.
|
||||
*/
|
||||
@Native public static final int MULTI_MAX_FRACTIONS_D3D = 8;
|
||||
|
||||
protected MultiGradient() {}
|
||||
|
||||
/**
|
||||
* Returns true if the given MultipleGradientPaint instance can be
|
||||
* used by the accelerated D3DPaints.MultiGradient implementation.
|
||||
* A MultipleGradientPaint is considered valid if the following
|
||||
* conditions are met:
|
||||
* - the number of gradient "stops" is <= MAX_FRACTIONS
|
||||
* - the destination has support for fragment shaders
|
||||
*/
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
MultipleGradientPaint paint = (MultipleGradientPaint)sg2d.paint;
|
||||
// REMIND: ugh, this creates garbage; would be nicer if
|
||||
// we had a MultipleGradientPaint.getNumStops() method...
|
||||
if (paint.getFractions().length > MULTI_MAX_FRACTIONS_D3D) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
dstData.getDeviceConfiguration().getDevice();
|
||||
if (!gd.isCapPresent(CAPS_LCD_SHADER)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/********************** LinearGradientPaint support *************************/
|
||||
|
||||
private static class LinearGradient extends MultiGradient {
|
||||
private LinearGradient() {}
|
||||
|
||||
@Override
|
||||
boolean isPaintValid(SunGraphics2D sg2d) {
|
||||
LinearGradientPaint paint = (LinearGradientPaint)sg2d.paint;
|
||||
|
||||
if (paint.getFractions().length == 2 &&
|
||||
paint.getCycleMethod() != CycleMethod.REPEAT &&
|
||||
paint.getColorSpace() != ColorSpaceType.LINEAR_RGB)
|
||||
{
|
||||
D3DSurfaceData dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
dstData.getDeviceConfiguration().getDevice();
|
||||
if (gd.isCapPresent(CAPS_LCD_SHADER)) {
|
||||
// we can delegate to the optimized two-color gradient
|
||||
// codepath, which should be faster
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.isPaintValid(sg2d);
|
||||
}
|
||||
}
|
||||
|
||||
/********************** RadialGradientPaint support *************************/
|
||||
|
||||
private static class RadialGradient extends MultiGradient {
|
||||
private RadialGradient() {}
|
||||
}
|
||||
}
|
||||
159
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderQueue.java
Normal file
159
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderQueue.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
/**
|
||||
* D3D-specific implementation of RenderQueue.
|
||||
*/
|
||||
public class D3DRenderQueue extends RenderQueue {
|
||||
|
||||
private static D3DRenderQueue theInstance;
|
||||
private static Thread rqThread;
|
||||
|
||||
private D3DRenderQueue() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the single D3DRenderQueue instance. If it has not yet been
|
||||
* initialized, this method will first construct the single instance
|
||||
* before returning it.
|
||||
*/
|
||||
public static synchronized D3DRenderQueue getInstance() {
|
||||
if (theInstance == null) {
|
||||
theInstance = new D3DRenderQueue();
|
||||
// no need to lock, noone has reference to this instance yet
|
||||
theInstance.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
rqThread = Thread.currentThread();
|
||||
}
|
||||
});
|
||||
}
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the single D3DRenderQueue instance synchronously. If an
|
||||
* D3DRenderQueue has not yet been instantiated, this method is a no-op.
|
||||
* This method is useful in the case of Toolkit.sync(), in which we want
|
||||
* to flush the D3D pipeline, but only if the D3D pipeline is currently
|
||||
* enabled. Since this class has few external dependencies, callers need
|
||||
* not be concerned that calling this method will trigger initialization
|
||||
* of the D3D pipeline and related classes.
|
||||
*/
|
||||
public static void sync() {
|
||||
if (theInstance != null) {
|
||||
// need to make sure any/all screen surfaces are presented prior
|
||||
// to completing the sync operation
|
||||
D3DScreenUpdateManager mgr =
|
||||
(D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
|
||||
mgr.runUpdateNow();
|
||||
|
||||
theInstance.lock();
|
||||
try {
|
||||
theInstance.ensureCapacity(4);
|
||||
theInstance.getBuffer().putInt(SYNC);
|
||||
theInstance.flushNow();
|
||||
} finally {
|
||||
theInstance.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to restore the devices if they're in the lost state.
|
||||
* (used when a full-screen window is activated/deactivated)
|
||||
*/
|
||||
public static void restoreDevices() {
|
||||
D3DRenderQueue rq = getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.ensureCapacity(4);
|
||||
rq.getBuffer().putInt(RESTORE_DEVICES);
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if current thread is the render queue thread,
|
||||
* false otherwise
|
||||
*/
|
||||
public static boolean isRenderQueueThread() {
|
||||
return (Thread.currentThread() == rqThread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the native memory associated with the given native
|
||||
* graphics config info pointer on the single queue flushing thread.
|
||||
*/
|
||||
public static void disposeGraphicsConfig(long pConfigInfo) {
|
||||
D3DRenderQueue rq = getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_CONFIG);
|
||||
buf.putLong(pConfigInfo);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void flushNow() {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
flushBuffer(null);
|
||||
}
|
||||
|
||||
public void flushAndInvokeNow(Runnable r) {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
flushBuffer(r);
|
||||
}
|
||||
|
||||
private native void flushBuffer(long buf, int limit, Runnable task);
|
||||
|
||||
private void flushBuffer(Runnable task) {
|
||||
// assert lock.isHeldByCurrentThread();
|
||||
int limit = buf.position();
|
||||
if (limit > 0 || task != null) {
|
||||
// process the queue
|
||||
flushBuffer(buf.getAddress(), limit, task);
|
||||
}
|
||||
// reset the buffer position
|
||||
buf.clear();
|
||||
// clear the set of references, since we no longer need them
|
||||
refSet.clear();
|
||||
}
|
||||
}
|
||||
223
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderer.java
Normal file
223
jdkSrc/jdk8/sun/java2d/d3d/D3DRenderer.java
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.Path2D;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.BufferedPaints;
|
||||
import sun.java2d.pipe.BufferedRenderPipe;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
|
||||
class D3DRenderer extends BufferedRenderPipe {
|
||||
|
||||
D3DRenderer(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d) {
|
||||
int ctxflags =
|
||||
sg2d.paint.getTransparency() == Transparency.OPAQUE ?
|
||||
D3DContext.SRC_IS_OPAQUE : D3DContext.NO_CONTEXT_FLAGS;
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateContextAA(SunGraphics2D sg2d) {
|
||||
int ctxflags = D3DContext.NO_CONTEXT_FLAGS;
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, sg2d.paint, sg2d, ctxflags);
|
||||
}
|
||||
|
||||
void copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
rq.lock();
|
||||
try {
|
||||
int ctxflags =
|
||||
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE ?
|
||||
D3DContext.SRC_IS_OPAQUE : D3DContext.NO_CONTEXT_FLAGS;
|
||||
D3DSurfaceData dstData;
|
||||
try {
|
||||
dstData = (D3DSurfaceData)sg2d.surfaceData;
|
||||
} catch (ClassCastException e) {
|
||||
throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
|
||||
}
|
||||
D3DContext.validateContext(dstData, dstData,
|
||||
sg2d.getCompClip(), sg2d.composite,
|
||||
null, null, null, ctxflags);
|
||||
|
||||
rq.ensureCapacity(28);
|
||||
buf.putInt(COPY_AREA);
|
||||
buf.putInt(x).putInt(y).putInt(w).putInt(h);
|
||||
buf.putInt(dx).putInt(dy);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected native void drawPoly(int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed,
|
||||
int transX, int transY);
|
||||
|
||||
D3DRenderer traceWrap() {
|
||||
return new Tracer(this);
|
||||
}
|
||||
|
||||
private class Tracer extends D3DRenderer {
|
||||
private D3DRenderer d3dr;
|
||||
Tracer(D3DRenderer d3dr) {
|
||||
super(d3dr.rq);
|
||||
this.d3dr = d3dr;
|
||||
}
|
||||
public ParallelogramPipe getAAParallelogramPipe() {
|
||||
final ParallelogramPipe realpipe = d3dr.getAAParallelogramPipe();
|
||||
return new ParallelogramPipe() {
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillAAParallelogram");
|
||||
realpipe.fillParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawAAParallelogram");
|
||||
realpipe.drawParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2,
|
||||
lw1, lw2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void validateContext(SunGraphics2D sg2d) {
|
||||
d3dr.validateContext(sg2d);
|
||||
}
|
||||
public void drawLine(SunGraphics2D sg2d,
|
||||
int x1, int y1, int x2, int y2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawLine");
|
||||
d3dr.drawLine(sg2d, x1, y1, x2, y2);
|
||||
}
|
||||
public void drawRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawRect");
|
||||
d3dr.drawRect(sg2d, x, y, w, h);
|
||||
}
|
||||
protected void drawPoly(SunGraphics2D sg2d,
|
||||
int[] xPoints, int[] yPoints,
|
||||
int nPoints, boolean isClosed)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawPoly");
|
||||
d3dr.drawPoly(sg2d, xPoints, yPoints, nPoints, isClosed);
|
||||
}
|
||||
public void fillRect(SunGraphics2D sg2d, int x, int y, int w, int h) {
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillRect");
|
||||
d3dr.fillRect(sg2d, x, y, w, h);
|
||||
}
|
||||
protected void drawPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawPath");
|
||||
d3dr.drawPath(sg2d, p2df, transx, transy);
|
||||
}
|
||||
protected void fillPath(SunGraphics2D sg2d,
|
||||
Path2D.Float p2df, int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillPath");
|
||||
d3dr.fillPath(sg2d, p2df, transx, transy);
|
||||
}
|
||||
protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
|
||||
int transx, int transy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillSpans");
|
||||
d3dr.fillSpans(sg2d, si, transx, transy);
|
||||
}
|
||||
public void fillParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DFillParallelogram");
|
||||
d3dr.fillParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2);
|
||||
}
|
||||
public void drawParallelogram(SunGraphics2D sg2d,
|
||||
double ux1, double uy1,
|
||||
double ux2, double uy2,
|
||||
double x, double y,
|
||||
double dx1, double dy1,
|
||||
double dx2, double dy2,
|
||||
double lw1, double lw2)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawParallelogram");
|
||||
d3dr.drawParallelogram(sg2d,
|
||||
ux1, uy1, ux2, uy2,
|
||||
x, y, dx1, dy1, dx2, dy2, lw1, lw2);
|
||||
}
|
||||
public void copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
GraphicsPrimitive.tracePrimitive("D3DCopyArea");
|
||||
d3dr.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
536
jdkSrc/jdk8/sun/java2d/d3d/D3DScreenUpdateManager.java
Normal file
536
jdkSrc/jdk8/sun/java2d/d3d/D3DScreenUpdateManager.java
Normal file
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Window;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.misc.ThreadGroupUtils;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.windows.GDIWindowSurfaceData;
|
||||
import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData;
|
||||
import sun.java2d.windows.WindowsFlags;
|
||||
|
||||
/**
|
||||
* This class handles rendering to the screen with the D3D pipeline.
|
||||
*
|
||||
* Since it is not possible to render directly to the front buffer
|
||||
* with D3D9, we create a swap chain surface (with COPY effect) in place of the
|
||||
* GDIWindowSurfaceData. A background thread handles the swap chain flips.
|
||||
*
|
||||
* There are some restrictions to which windows we would use this for.
|
||||
* @see #createScreenSurface()
|
||||
*/
|
||||
public class D3DScreenUpdateManager extends ScreenUpdateManager
|
||||
implements Runnable
|
||||
{
|
||||
/**
|
||||
* A window must be at least MIN_WIN_SIZE in one or both dimensions
|
||||
* to be considered for the update manager.
|
||||
*/
|
||||
private static final int MIN_WIN_SIZE = 150;
|
||||
|
||||
private volatile boolean done;
|
||||
private volatile Thread screenUpdater;
|
||||
private boolean needsUpdateNow;
|
||||
|
||||
/**
|
||||
* Object used by the screen updater thread for waiting
|
||||
*/
|
||||
private Object runLock = new Object();
|
||||
/**
|
||||
* List of D3DWindowSurfaceData surfaces. Surfaces are added to the
|
||||
* list when a graphics object is created, and removed when the surface
|
||||
* is invalidated.
|
||||
*/
|
||||
private ArrayList<D3DWindowSurfaceData> d3dwSurfaces;
|
||||
/**
|
||||
* Cache of GDIWindowSurfaceData surfaces corresponding to the
|
||||
* D3DWindowSurfaceData surfaces. Surfaces are added to the list when
|
||||
* a d3dw surface is lost and could not be restored (due to lack of vram,
|
||||
* for example), and removed then the d3dw surface is invalidated.
|
||||
*/
|
||||
private HashMap<D3DWindowSurfaceData, GDIWindowSurfaceData> gdiSurfaces;
|
||||
|
||||
public D3DScreenUpdateManager() {
|
||||
done = false;
|
||||
AccessController.doPrivileged(
|
||||
(PrivilegedAction<Void>) () -> {
|
||||
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
|
||||
Thread shutdown = new Thread(rootTG, () -> {
|
||||
done = true;
|
||||
wakeUpUpdateThread();
|
||||
});
|
||||
shutdown.setContextClassLoader(null);
|
||||
try {
|
||||
Runtime.getRuntime().addShutdownHook(shutdown);
|
||||
} catch (Exception e) {
|
||||
done = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* If possible, creates a D3DWindowSurfaceData (which is actually
|
||||
* a back-buffer surface). If the creation fails, returns GDI
|
||||
* onscreen surface instead.
|
||||
*
|
||||
* Note that the created D3D surface does not initialize the native
|
||||
* resources (and is marked lost) to avoid wasting video memory. It is
|
||||
* restored when a graphics object is requested from the peer.
|
||||
*
|
||||
* Note that this method is called from a synchronized block in
|
||||
* WComponentPeer, so we don't need to synchronize
|
||||
*
|
||||
* Note that we only create a substibute d3dw surface if certain conditions
|
||||
* are met
|
||||
* <ul>
|
||||
* <li>the fake d3d rendering on screen is not disabled via flag
|
||||
* <li>d3d on the device is enabled
|
||||
* <li>surface is larger than MIN_WIN_SIZE (don't bother for smaller ones)
|
||||
* <li>it doesn't have a backBuffer for a BufferStrategy already
|
||||
* <li>the peer is either Canvas, Panel, Window, Frame,
|
||||
* Dialog or EmbeddedFrame
|
||||
* </ul>
|
||||
*
|
||||
* @param gc GraphicsConfiguration on associated with the surface
|
||||
* @param peer peer for which the surface is to be created
|
||||
* @param bbNum number of back-buffers requested. if this number is >0,
|
||||
* method returns GDI surface (we don't want to have two swap chains)
|
||||
* @param isResize whether this surface is being created in response to
|
||||
* a component resize event. This determines whether a repaint event will
|
||||
* be issued after a surface is created: it will be if <code>isResize</code>
|
||||
* is <code>true</code>.
|
||||
* @return surface data to be use for onscreen rendering
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData createScreenSurface(Win32GraphicsConfig gc,
|
||||
WComponentPeer peer,
|
||||
int bbNum, boolean isResize)
|
||||
{
|
||||
if (done || !(gc instanceof D3DGraphicsConfig)) {
|
||||
return super.createScreenSurface(gc, peer, bbNum, isResize);
|
||||
}
|
||||
|
||||
SurfaceData sd = null;
|
||||
|
||||
if (canUseD3DOnScreen(peer, gc, bbNum)) {
|
||||
try {
|
||||
// note that the created surface will be in the "lost"
|
||||
// state, it will be restored prior to rendering to it
|
||||
// for the first time. This is done so that vram is not
|
||||
// wasted for surfaces never rendered to
|
||||
sd = D3DSurfaceData.createData(peer);
|
||||
} catch (InvalidPipeException ipe) {
|
||||
sd = null;
|
||||
}
|
||||
}
|
||||
if (sd == null) {
|
||||
sd = GDIWindowSurfaceData.createData(peer);
|
||||
// note that we do not add this surface to the list of cached gdi
|
||||
// surfaces as there's no d3dw surface to associate it with;
|
||||
// this peer will have a gdi surface until next time a surface
|
||||
// will need to be replaced
|
||||
}
|
||||
|
||||
if (isResize) {
|
||||
// since we'd potentially replaced the back-buffer surface
|
||||
// (either with another bb, or a gdi one), the
|
||||
// component will need to be completely repainted;
|
||||
// this only need to be done when the surface is created in
|
||||
// response to a resize event since when a component is created it
|
||||
// will be repainted anyway
|
||||
repaintPeerTarget(peer);
|
||||
}
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if we can use a d3d surface for onscreen rendering for this
|
||||
* peer.
|
||||
* We only create onscreen d3d surfaces if the following conditions are met:
|
||||
* - d3d is enabled on this device and onscreen emulation is enabled
|
||||
* - window is big enough to bother (either dimension > MIN_WIN_SIZE)
|
||||
* - this heavyweight doesn't have a BufferStrategy
|
||||
* - if we are in full-screen mode then it must be the peer of the
|
||||
* full-screen window (since there could be only one SwapChain in fs)
|
||||
* and it must not have any heavyweight children
|
||||
* (as Present() doesn't respect component clipping in fullscreen mode)
|
||||
* - it's one of the classes likely to have custom rendering worth
|
||||
* accelerating
|
||||
*
|
||||
* @returns true if we can use a d3d surface for this peer's onscreen
|
||||
* rendering
|
||||
*/
|
||||
public static boolean canUseD3DOnScreen(final WComponentPeer peer,
|
||||
final Win32GraphicsConfig gc,
|
||||
final int bbNum)
|
||||
{
|
||||
if (!(gc instanceof D3DGraphicsConfig)) {
|
||||
return false;
|
||||
}
|
||||
D3DGraphicsConfig d3dgc = (D3DGraphicsConfig)gc;
|
||||
D3DGraphicsDevice d3dgd = d3dgc.getD3DDevice();
|
||||
String peerName = peer.getClass().getName();
|
||||
Rectangle r = peer.getBounds();
|
||||
Component target = (Component)peer.getTarget();
|
||||
Window fsw = d3dgd.getFullScreenWindow();
|
||||
|
||||
return
|
||||
WindowsFlags.isD3DOnScreenEnabled() &&
|
||||
d3dgd.isD3DEnabledOnDevice() &&
|
||||
peer.isAccelCapable() &&
|
||||
(r.width > MIN_WIN_SIZE || r.height > MIN_WIN_SIZE) &&
|
||||
bbNum == 0 &&
|
||||
(fsw == null || (fsw == target && !hasHWChildren(target))) &&
|
||||
(peerName.equals("sun.awt.windows.WCanvasPeer") ||
|
||||
peerName.equals("sun.awt.windows.WDialogPeer") ||
|
||||
peerName.equals("sun.awt.windows.WPanelPeer") ||
|
||||
peerName.equals("sun.awt.windows.WWindowPeer") ||
|
||||
peerName.equals("sun.awt.windows.WFramePeer") ||
|
||||
peerName.equals("sun.awt.windows.WEmbeddedFramePeer"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a graphics object for the passed in surface data. If
|
||||
* the surface is lost, it is restored.
|
||||
* If the surface wasn't lost or the restoration was successful
|
||||
* the surface is added to the list of maintained surfaces
|
||||
* (if it hasn't been already).
|
||||
*
|
||||
* If the updater thread hasn't been created yet , it will be created and
|
||||
* started.
|
||||
*
|
||||
* @param sd surface data for which to create SunGraphics2D
|
||||
* @param peer peer associated with the surface data
|
||||
* @param fgColor fg color to be used in graphics
|
||||
* @param bgColor bg color to be used in graphics
|
||||
* @param font font to be used in graphics
|
||||
* @return a SunGraphics2D object for the surface (or for temp GDI
|
||||
* surface data)
|
||||
*/
|
||||
@Override
|
||||
public Graphics2D createGraphics(SurfaceData sd,
|
||||
WComponentPeer peer, Color fgColor, Color bgColor, Font font)
|
||||
{
|
||||
if (!done && sd instanceof D3DWindowSurfaceData) {
|
||||
D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd;
|
||||
if (!d3dw.isSurfaceLost() || validate(d3dw)) {
|
||||
trackScreenSurface(d3dw);
|
||||
return new SunGraphics2D(sd, fgColor, bgColor, font);
|
||||
}
|
||||
// could not restore the d3dw surface, use the cached gdi surface
|
||||
// instead for this graphics object; note that we do not track
|
||||
// this new gdi surface, it is only used for this graphics
|
||||
// object
|
||||
sd = getGdiSurface(d3dw);
|
||||
}
|
||||
return super.createGraphics(sd, peer, fgColor, bgColor, font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts a repaint event for the peer's target to the EDT
|
||||
* @param peer for which target's the repaint should be issued
|
||||
*/
|
||||
private void repaintPeerTarget(WComponentPeer peer) {
|
||||
Component target = (Component)peer.getTarget();
|
||||
Rectangle bounds = AWTAccessor.getComponentAccessor().getBounds(target);
|
||||
// the system-level painting operations should call the handlePaint()
|
||||
// method of the WComponentPeer class to repaint the component;
|
||||
// calling repaint() forces AWT to make call to update()
|
||||
peer.handlePaint(0, 0, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a surface to the list of tracked surfaces.
|
||||
*
|
||||
* @param d3dw the surface to be added
|
||||
*/
|
||||
private void trackScreenSurface(SurfaceData sd) {
|
||||
if (!done && sd instanceof D3DWindowSurfaceData) {
|
||||
synchronized (this) {
|
||||
if (d3dwSurfaces == null) {
|
||||
d3dwSurfaces = new ArrayList<D3DWindowSurfaceData>();
|
||||
}
|
||||
D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd;
|
||||
if (!d3dwSurfaces.contains(d3dw)) {
|
||||
d3dwSurfaces.add(d3dw);
|
||||
}
|
||||
}
|
||||
startUpdateThread();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void dropScreenSurface(SurfaceData sd) {
|
||||
if (d3dwSurfaces != null && sd instanceof D3DWindowSurfaceData) {
|
||||
D3DWindowSurfaceData d3dw = (D3DWindowSurfaceData)sd;
|
||||
removeGdiSurface(d3dw);
|
||||
d3dwSurfaces.remove(d3dw);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData getReplacementScreenSurface(WComponentPeer peer,
|
||||
SurfaceData sd)
|
||||
{
|
||||
SurfaceData newSurface = super.getReplacementScreenSurface(peer, sd);
|
||||
// if some outstanding graphics context wants to get a replacement we
|
||||
// need to make sure that the new surface (if it is accelerated) is
|
||||
// being tracked
|
||||
trackScreenSurface(newSurface);
|
||||
return newSurface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the gdi surface corresponding to the passed d3dw surface
|
||||
* from list of the cached gdi surfaces.
|
||||
*
|
||||
* @param d3dw surface for which associated gdi surface is to be removed
|
||||
*/
|
||||
private void removeGdiSurface(final D3DWindowSurfaceData d3dw) {
|
||||
if (gdiSurfaces != null) {
|
||||
GDIWindowSurfaceData gdisd = gdiSurfaces.get(d3dw);
|
||||
if (gdisd != null) {
|
||||
gdisd.invalidate();
|
||||
gdiSurfaces.remove(d3dw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the update thread hasn't yet been created, it will be;
|
||||
* otherwise it is awaken
|
||||
*/
|
||||
private synchronized void startUpdateThread() {
|
||||
if (screenUpdater == null) {
|
||||
screenUpdater = AccessController.doPrivileged(
|
||||
(PrivilegedAction<Thread>) () -> {
|
||||
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
|
||||
Thread t = new Thread(rootTG,
|
||||
D3DScreenUpdateManager.this,
|
||||
"D3D Screen Updater");
|
||||
// REMIND: should it be higher?
|
||||
t.setPriority(Thread.NORM_PRIORITY + 2);
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
screenUpdater.start();
|
||||
} else {
|
||||
wakeUpUpdateThread();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes up the screen updater thread.
|
||||
*
|
||||
* This method is not synchronous, it doesn't wait
|
||||
* for the updater thread to complete the updates.
|
||||
*
|
||||
* It should be used when it is not necessary to wait for the
|
||||
* completion, for example, when a new surface had been added
|
||||
* to the list of tracked surfaces (which means that it's about
|
||||
* to be rendered to).
|
||||
*/
|
||||
public void wakeUpUpdateThread() {
|
||||
synchronized (runLock) {
|
||||
runLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes up the screen updater thread and waits for the completion
|
||||
* of the update.
|
||||
*
|
||||
* This method is called from Toolkit.sync() or
|
||||
* when there was a copy from a VI to the screen
|
||||
* so that swing applications would not appear to be
|
||||
* sluggish.
|
||||
*/
|
||||
public void runUpdateNow() {
|
||||
synchronized (this) {
|
||||
// nothing to do if the updater thread hadn't been started or if
|
||||
// there are no tracked surfaces
|
||||
if (done || screenUpdater == null ||
|
||||
d3dwSurfaces == null || d3dwSurfaces.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
synchronized (runLock) {
|
||||
needsUpdateNow = true;
|
||||
runLock.notifyAll();
|
||||
while (needsUpdateNow) {
|
||||
try {
|
||||
runLock.wait();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
while (!done) {
|
||||
synchronized (runLock) {
|
||||
// If the list is empty, suspend the thread until a
|
||||
// new surface is added. Note that we have to check before
|
||||
// wait() (and inside the runLock), otherwise we could miss a
|
||||
// notify() when a new surface is added and sleep forever.
|
||||
long timeout = d3dwSurfaces.size() > 0 ? 100 : 0;
|
||||
|
||||
// don't go to sleep if there's a thread waiting for an update
|
||||
if (!needsUpdateNow) {
|
||||
try { runLock.wait(timeout); }
|
||||
catch (InterruptedException e) {}
|
||||
}
|
||||
// if we were woken up, there are probably surfaces in the list,
|
||||
// no need to check if the list is empty
|
||||
}
|
||||
|
||||
// make a copy to avoid synchronization during the loop
|
||||
D3DWindowSurfaceData surfaces[] = new D3DWindowSurfaceData[] {};
|
||||
synchronized (this) {
|
||||
surfaces = d3dwSurfaces.toArray(surfaces);
|
||||
}
|
||||
for (D3DWindowSurfaceData sd : surfaces) {
|
||||
// skip invalid surfaces (they could have become invalid
|
||||
// after we made a copy of the list) - just a precaution
|
||||
if (sd.isValid() && (sd.isDirty() || sd.isSurfaceLost())) {
|
||||
if (!sd.isSurfaceLost()) {
|
||||
// the flip and the clearing of the dirty state
|
||||
// must be done under the lock, otherwise it's
|
||||
// possible to miss an update to the surface
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
Rectangle r = sd.getBounds();
|
||||
D3DSurfaceData.swapBuffers(sd, 0, 0,
|
||||
r.width, r.height);
|
||||
sd.markClean();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
} else if (!validate(sd)) {
|
||||
// it is possible that the validation may never
|
||||
// succeed, we need to detect this and replace
|
||||
// the d3dw surface with gdi; the replacement of
|
||||
// the surface will also trigger a repaint
|
||||
sd.getPeer().replaceSurfaceDataLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (runLock) {
|
||||
needsUpdateNow = false;
|
||||
runLock.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the passed surface if it was lost, resets the lost status.
|
||||
* @param sd surface to be validated
|
||||
* @return true if surface wasn't lost or if restoration was successful,
|
||||
* false otherwise
|
||||
*/
|
||||
private boolean validate(D3DWindowSurfaceData sd) {
|
||||
if (sd.isSurfaceLost()) {
|
||||
try {
|
||||
sd.restoreSurface();
|
||||
// if succeeded, first fill the surface with bg color
|
||||
// note: use the non-synch method to avoid incorrect lock order
|
||||
Color bg = sd.getPeer().getBackgroundNoSync();
|
||||
SunGraphics2D sg2d = new SunGraphics2D(sd, bg, bg, null);
|
||||
sg2d.fillRect(0, 0, sd.getBounds().width, sd.getBounds().height);
|
||||
sg2d.dispose();
|
||||
// now clean the dirty status so that we don't flip it
|
||||
// next time before it gets repainted; it is safe
|
||||
// to do without the lock because we will issue a
|
||||
// repaint anyway so we will not lose any rendering
|
||||
sd.markClean();
|
||||
// since the surface was successfully restored we need to
|
||||
// repaint whole window to repopulate the back-buffer
|
||||
repaintPeerTarget(sd.getPeer());
|
||||
} catch (InvalidPipeException ipe) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates (or returns a cached one) gdi surface for the same peer as
|
||||
* the passed d3dw surface has.
|
||||
*
|
||||
* @param d3dw surface used as key into the cache
|
||||
* @return gdi window surface associated with the d3d window surfaces' peer
|
||||
*/
|
||||
private synchronized SurfaceData getGdiSurface(D3DWindowSurfaceData d3dw) {
|
||||
if (gdiSurfaces == null) {
|
||||
gdiSurfaces =
|
||||
new HashMap<D3DWindowSurfaceData, GDIWindowSurfaceData>();
|
||||
}
|
||||
GDIWindowSurfaceData gdisd = gdiSurfaces.get(d3dw);
|
||||
if (gdisd == null) {
|
||||
gdisd = GDIWindowSurfaceData.createData(d3dw.getPeer());
|
||||
gdiSurfaces.put(d3dw, gdisd);
|
||||
}
|
||||
return gdisd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component has heavyweight children.
|
||||
*
|
||||
* @param comp component to check for hw children
|
||||
* @return true if Component has heavyweight children
|
||||
*/
|
||||
private static boolean hasHWChildren(Component comp) {
|
||||
if (comp instanceof Container) {
|
||||
for (Component c : ((Container)comp).getComponents()) {
|
||||
if (c.getPeer() instanceof WComponentPeer || hasHWChildren(c)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
990
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceData.java
Normal file
990
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceData.java
Normal file
@@ -0,0 +1,990 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import sun.awt.SunHints;
|
||||
import sun.awt.image.DataBufferNative;
|
||||
import sun.awt.image.PixelConverter;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.image.WritableRasterNative;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.MaskFill;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import sun.java2d.pipe.PixelToParallelogramConverter;
|
||||
import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.TextPipe;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import static sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType.*;
|
||||
import sun.java2d.pipe.hw.ExtendedBufferCapabilities.VSyncType;
|
||||
import java.awt.BufferCapabilities.FlipContents;
|
||||
import java.awt.Window;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.java2d.ScreenUpdateManager;
|
||||
import sun.java2d.StateTracker;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
|
||||
|
||||
/**
|
||||
* This class describes a D3D "surface", that is, a region of pixels
|
||||
* managed via D3D. An D3DSurfaceData can be tagged with one of three
|
||||
* different SurfaceType objects for the purpose of registering loops, etc.
|
||||
* This diagram shows the hierarchy of D3D SurfaceTypes:
|
||||
*
|
||||
* Any
|
||||
* / \
|
||||
* D3DSurface D3DTexture
|
||||
* |
|
||||
* D3DSurfaceRTT
|
||||
*
|
||||
* D3DSurface
|
||||
* This kind of surface can be rendered to using D3D APIs. It is also
|
||||
* possible to copy a D3DSurface to another D3DSurface (or to itself).
|
||||
*
|
||||
* D3DTexture
|
||||
* This kind of surface cannot be rendered to using D3D (in the same sense
|
||||
* as in D3DSurface). However, it is possible to upload a region of pixels
|
||||
* to a D3DTexture object via Lock/UnlockRect(). One can also copy a
|
||||
* surface of type D3DTexture to a D3DSurface by binding the texture
|
||||
* to a quad and then rendering it to the destination surface (this process
|
||||
* is known as "texture mapping").
|
||||
*
|
||||
* D3DSurfaceRTT
|
||||
* This kind of surface can be thought of as a sort of hybrid between
|
||||
* D3DSurface and D3DTexture, in that one can render to this kind of
|
||||
* surface as if it were of type D3DSurface, but the process of copying
|
||||
* this kind of surface to another is more like a D3DTexture. (Note that
|
||||
* "RTT" stands for "render-to-texture".)
|
||||
*
|
||||
* In addition to these SurfaceType variants, we have also defined some
|
||||
* constants that describe in more detail the type of underlying D3D
|
||||
* surface. This table helps explain the relationships between those
|
||||
* "type" constants and their corresponding SurfaceType:
|
||||
*
|
||||
* D3D Type Corresponding SurfaceType
|
||||
* -------- -------------------------
|
||||
* RT_PLAIN D3DSurface
|
||||
* TEXTURE D3DTexture
|
||||
* FLIP_BACKBUFFER D3DSurface
|
||||
* RT_TEXTURE D3DSurfaceRTT
|
||||
*/
|
||||
public class D3DSurfaceData extends SurfaceData implements AccelSurface {
|
||||
|
||||
/**
|
||||
* To be used with getNativeResource() only.
|
||||
* @see #getNativeResource()
|
||||
*/
|
||||
public static final int D3D_DEVICE_RESOURCE= 100;
|
||||
/*
|
||||
* Surface types.
|
||||
* We use these surface types when copying from a sw surface
|
||||
* to a surface or texture.
|
||||
*/
|
||||
public static final int ST_INT_ARGB = 0;
|
||||
public static final int ST_INT_ARGB_PRE = 1;
|
||||
public static final int ST_INT_ARGB_BM = 2;
|
||||
public static final int ST_INT_RGB = 3;
|
||||
public static final int ST_INT_BGR = 4;
|
||||
public static final int ST_USHORT_565_RGB = 5;
|
||||
public static final int ST_USHORT_555_RGB = 6;
|
||||
public static final int ST_BYTE_INDEXED = 7;
|
||||
public static final int ST_BYTE_INDEXED_BM = 8;
|
||||
public static final int ST_3BYTE_BGR = 9;
|
||||
|
||||
/** Equals to D3DSWAPEFFECT_DISCARD */
|
||||
public static final int SWAP_DISCARD = 1;
|
||||
/** Equals to D3DSWAPEFFECT_FLIP */
|
||||
public static final int SWAP_FLIP = 2;
|
||||
/** Equals to D3DSWAPEFFECT_COPY */
|
||||
public static final int SWAP_COPY = 3;
|
||||
/*
|
||||
* SurfaceTypes
|
||||
*/
|
||||
private static final String DESC_D3D_SURFACE = "D3D Surface";
|
||||
private static final String DESC_D3D_SURFACE_RTT =
|
||||
"D3D Surface (render-to-texture)";
|
||||
private static final String DESC_D3D_TEXTURE = "D3D Texture";
|
||||
|
||||
// REMIND: regarding ArgbPre??
|
||||
static final SurfaceType D3DSurface =
|
||||
SurfaceType.Any.deriveSubType(DESC_D3D_SURFACE,
|
||||
PixelConverter.ArgbPre.instance);
|
||||
static final SurfaceType D3DSurfaceRTT =
|
||||
D3DSurface.deriveSubType(DESC_D3D_SURFACE_RTT);
|
||||
static final SurfaceType D3DTexture =
|
||||
SurfaceType.Any.deriveSubType(DESC_D3D_TEXTURE);
|
||||
|
||||
private int type;
|
||||
private int width, height;
|
||||
// these fields are set from the native code when the surface is
|
||||
// initialized
|
||||
private int nativeWidth, nativeHeight;
|
||||
protected WComponentPeer peer;
|
||||
private Image offscreenImage;
|
||||
protected D3DGraphicsDevice graphicsDevice;
|
||||
|
||||
private int swapEffect;
|
||||
private VSyncType syncType;
|
||||
private int backBuffersNum;
|
||||
|
||||
private WritableRasterNative wrn;
|
||||
|
||||
protected static D3DRenderer d3dRenderPipe;
|
||||
protected static PixelToParallelogramConverter d3dTxRenderPipe;
|
||||
protected static ParallelogramPipe d3dAAPgramPipe;
|
||||
protected static D3DTextRenderer d3dTextPipe;
|
||||
protected static D3DDrawImage d3dImagePipe;
|
||||
|
||||
private native boolean initTexture(long pData, boolean isRTT,
|
||||
boolean isOpaque);
|
||||
private native boolean initFlipBackbuffer(long pData, long pPeerData,
|
||||
int numbuffers,
|
||||
int swapEffect, int syncType);
|
||||
private native boolean initRTSurface(long pData, boolean isOpaque);
|
||||
private native void initOps(int screen, int width, int height);
|
||||
|
||||
static {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
d3dImagePipe = new D3DDrawImage();
|
||||
d3dTextPipe = new D3DTextRenderer(rq);
|
||||
d3dRenderPipe = new D3DRenderer(rq);
|
||||
if (GraphicsPrimitive.tracingEnabled()) {
|
||||
d3dTextPipe = d3dTextPipe.traceWrap();
|
||||
d3dRenderPipe = d3dRenderPipe.traceWrap();
|
||||
//The wrapped d3dRenderPipe will wrap the AA pipe as well...
|
||||
//d3dAAPgramPipe = d3dRenderPipe.traceWrap();
|
||||
}
|
||||
d3dAAPgramPipe = d3dRenderPipe.getAAParallelogramPipe();
|
||||
d3dTxRenderPipe =
|
||||
new PixelToParallelogramConverter(d3dRenderPipe, d3dRenderPipe,
|
||||
1.0, 0.25, true);
|
||||
|
||||
D3DBlitLoops.register();
|
||||
D3DMaskFill.register();
|
||||
D3DMaskBlit.register();
|
||||
}
|
||||
|
||||
protected D3DSurfaceData(WComponentPeer peer, D3DGraphicsConfig gc,
|
||||
int width, int height, Image image,
|
||||
ColorModel cm, int numBackBuffers,
|
||||
int swapEffect, VSyncType vSyncType,
|
||||
int type)
|
||||
{
|
||||
super(getCustomSurfaceType(type), cm);
|
||||
this.graphicsDevice = gc.getD3DDevice();
|
||||
this.peer = peer;
|
||||
this.type = type;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.offscreenImage = image;
|
||||
this.backBuffersNum = numBackBuffers;
|
||||
this.swapEffect = swapEffect;
|
||||
this.syncType = vSyncType;
|
||||
|
||||
initOps(graphicsDevice.getScreen(), width, height);
|
||||
if (type == WINDOW) {
|
||||
// we put the surface into the "lost"
|
||||
// state; it will be restored by the D3DScreenUpdateManager
|
||||
// prior to rendering to it for the first time. This is done
|
||||
// so that vram is not wasted for surfaces never rendered to
|
||||
setSurfaceLost(true);
|
||||
} else {
|
||||
initSurface();
|
||||
}
|
||||
setBlitProxyKey(gc.getProxyKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
|
||||
return D3DSurfaceDataProxy.
|
||||
createProxy(srcData,
|
||||
(D3DGraphicsConfig)graphicsDevice.getDefaultConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SurfaceData object representing the back buffer of a
|
||||
* double-buffered on-screen Window.
|
||||
*/
|
||||
public static D3DSurfaceData createData(WComponentPeer peer, Image image) {
|
||||
D3DGraphicsConfig gc = getGC(peer);
|
||||
if (gc == null || !peer.isAccelCapable()) {
|
||||
return null;
|
||||
}
|
||||
BufferCapabilities caps = peer.getBackBufferCaps();
|
||||
VSyncType vSyncType = VSYNC_DEFAULT;
|
||||
if (caps instanceof ExtendedBufferCapabilities) {
|
||||
vSyncType = ((ExtendedBufferCapabilities)caps).getVSync();
|
||||
}
|
||||
Rectangle r = peer.getBounds();
|
||||
BufferCapabilities.FlipContents flip = caps.getFlipContents();
|
||||
int swapEffect;
|
||||
if (flip == FlipContents.COPIED) {
|
||||
swapEffect = SWAP_COPY;
|
||||
} else if (flip == FlipContents.PRIOR) {
|
||||
swapEffect = SWAP_FLIP;
|
||||
} else { // flip == FlipContents.UNDEFINED || .BACKGROUND
|
||||
swapEffect = SWAP_DISCARD;
|
||||
}
|
||||
return new D3DSurfaceData(peer, gc, r.width, r.height,
|
||||
image, peer.getColorModel(),
|
||||
peer.getBackBuffersNum(),
|
||||
swapEffect, vSyncType, FLIP_BACKBUFFER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a WINDOW type of surface - a
|
||||
* swap chain which serves as an on-screen surface,
|
||||
* handled by the D3DScreenUpdateManager.
|
||||
*
|
||||
* Note that the native surface is not initialized
|
||||
* when the surface is created to avoid using excessive
|
||||
* resources, and the surface is placed into the lost
|
||||
* state. It will be restored prior to any rendering
|
||||
* to it.
|
||||
*
|
||||
* @param peer peer for which the onscreen surface is to be created
|
||||
* @return a D3DWindowSurfaceData (flip chain) surface
|
||||
*/
|
||||
public static D3DSurfaceData createData(WComponentPeer peer) {
|
||||
D3DGraphicsConfig gc = getGC(peer);
|
||||
if (gc == null || !peer.isAccelCapable()) {
|
||||
return null;
|
||||
}
|
||||
return new D3DWindowSurfaceData(peer, gc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a SurfaceData object representing an off-screen buffer (either
|
||||
* a plain surface or Texture).
|
||||
*/
|
||||
public static D3DSurfaceData createData(D3DGraphicsConfig gc,
|
||||
int width, int height,
|
||||
ColorModel cm,
|
||||
Image image, int type)
|
||||
{
|
||||
if (type == RT_TEXTURE) {
|
||||
boolean isOpaque = cm.getTransparency() == Transparency.OPAQUE;
|
||||
int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
|
||||
if (!gc.getD3DDevice().isCapPresent(cap)) {
|
||||
type = RT_PLAIN;
|
||||
}
|
||||
}
|
||||
D3DSurfaceData ret = null;
|
||||
try {
|
||||
ret = new D3DSurfaceData(null, gc, width, height,
|
||||
image, cm, 0, SWAP_DISCARD, VSYNC_DEFAULT,
|
||||
type);
|
||||
} catch (InvalidPipeException ipe) {
|
||||
// try again - we might have ran out of vram, and rt textures
|
||||
// could take up more than a plain surface, so it might succeed
|
||||
if (type == RT_TEXTURE) {
|
||||
// If a RT_TEXTURE was requested do not attempt to create a
|
||||
// plain surface. (note that RT_TEXTURE can only be requested
|
||||
// from a VI so the cast is safe)
|
||||
if (((SunVolatileImage)image).getForcedAccelSurfaceType() !=
|
||||
RT_TEXTURE)
|
||||
{
|
||||
type = RT_PLAIN;
|
||||
ret = new D3DSurfaceData(null, gc, width, height,
|
||||
image, cm, 0, SWAP_DISCARD,
|
||||
VSYNC_DEFAULT, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate SurfaceType corresponding to the given D3D
|
||||
* surface type constant (e.g. TEXTURE -> D3DTexture).
|
||||
*/
|
||||
private static SurfaceType getCustomSurfaceType(int d3dType) {
|
||||
switch (d3dType) {
|
||||
case TEXTURE:
|
||||
return D3DTexture;
|
||||
case RT_TEXTURE:
|
||||
return D3DSurfaceRTT;
|
||||
default:
|
||||
return D3DSurface;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initSurfaceNow() {
|
||||
boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
|
||||
switch (type) {
|
||||
case RT_PLAIN:
|
||||
return initRTSurface(getNativeOps(), isOpaque);
|
||||
case TEXTURE:
|
||||
return initTexture(getNativeOps(), false/*isRTT*/, isOpaque);
|
||||
case RT_TEXTURE:
|
||||
return initTexture(getNativeOps(), true/*isRTT*/, isOpaque);
|
||||
// REMIND: we may want to pass the exact type to the native
|
||||
// level here so that we could choose the right presentation
|
||||
// interval for the frontbuffer (immediate vs v-synced)
|
||||
case WINDOW:
|
||||
case FLIP_BACKBUFFER:
|
||||
return initFlipBackbuffer(getNativeOps(), peer.getData(),
|
||||
backBuffersNum, swapEffect,
|
||||
syncType.id());
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the appropriate D3D offscreen surface based on the value
|
||||
* of the type parameter. If the surface creation fails for any reason,
|
||||
* an OutOfMemoryError will be thrown.
|
||||
*/
|
||||
protected void initSurface() {
|
||||
// any time we create or restore the surface, recreate the raster
|
||||
synchronized (this) {
|
||||
wrn = null;
|
||||
}
|
||||
// REMIND: somewhere a puppy died
|
||||
class Status {
|
||||
boolean success = false;
|
||||
};
|
||||
final Status status = new Status();
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
status.success = initSurfaceNow();
|
||||
}
|
||||
});
|
||||
if (!status.success) {
|
||||
throw new InvalidPipeException("Error creating D3DSurface");
|
||||
}
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the D3DContext for the GraphicsConfig associated with this
|
||||
* surface.
|
||||
*/
|
||||
public final D3DContext getContext() {
|
||||
return graphicsDevice.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one of the surface type constants defined above.
|
||||
*/
|
||||
public final int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static native int dbGetPixelNative(long pData, int x, int y);
|
||||
private static native void dbSetPixelNative(long pData, int x, int y,
|
||||
int pixel);
|
||||
static class D3DDataBufferNative extends DataBufferNative {
|
||||
int pixel;
|
||||
protected D3DDataBufferNative(SurfaceData sData,
|
||||
int type, int w, int h)
|
||||
{
|
||||
super(sData, type, w, h);
|
||||
}
|
||||
|
||||
protected int getElem(final int x, final int y,
|
||||
final SurfaceData sData)
|
||||
{
|
||||
if (sData.isSurfaceLost()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retPixel;
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
pixel = dbGetPixelNative(sData.getNativeOps(), x, y);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
retPixel = pixel;
|
||||
rq.unlock();
|
||||
}
|
||||
return retPixel;
|
||||
}
|
||||
|
||||
protected void setElem(final int x, final int y, final int pixel,
|
||||
final SurfaceData sData)
|
||||
{
|
||||
if (sData.isSurfaceLost()) {
|
||||
return;
|
||||
}
|
||||
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
rq.flushAndInvokeNow(new Runnable() {
|
||||
public void run() {
|
||||
dbSetPixelNative(sData.getNativeOps(), x, y, pixel);
|
||||
}
|
||||
});
|
||||
sData.markDirty();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Raster getRaster(int x, int y, int w, int h) {
|
||||
if (wrn == null) {
|
||||
DirectColorModel dcm = (DirectColorModel)getColorModel();
|
||||
SampleModel smHw;
|
||||
int dataType = 0;
|
||||
int scanStride = width;
|
||||
|
||||
if (dcm.getPixelSize() > 16) {
|
||||
dataType = DataBuffer.TYPE_INT;
|
||||
} else {
|
||||
// 15, 16
|
||||
dataType = DataBuffer.TYPE_USHORT;
|
||||
}
|
||||
|
||||
// note that we have to use the surface width and height here,
|
||||
// not the passed w,h
|
||||
smHw = new SinglePixelPackedSampleModel(dataType, width, height,
|
||||
scanStride, dcm.getMasks());
|
||||
DataBuffer dbn = new D3DDataBufferNative(this, dataType,
|
||||
width, height);
|
||||
wrn = WritableRasterNative.createNativeRaster(smHw, dbn);
|
||||
}
|
||||
|
||||
return wrn;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, we can only render LCD text if:
|
||||
* - the pixel shaders are available, and
|
||||
* - blending is disabled, and
|
||||
* - the source color is opaque
|
||||
* - and the destination is opaque
|
||||
*/
|
||||
public boolean canRenderLCDText(SunGraphics2D sg2d) {
|
||||
return
|
||||
graphicsDevice.isCapPresent(CAPS_LCD_SHADER) &&
|
||||
sg2d.compositeState <= SunGraphics2D.COMP_ISCOPY &&
|
||||
sg2d.paintState <= SunGraphics2D.PAINT_OPAQUECOLOR &&
|
||||
sg2d.surfaceData.getTransparency() == Transparency.OPAQUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* If acceleration should no longer be used for this surface.
|
||||
* This implementation flags to the manager that it should no
|
||||
* longer attempt to re-create a D3DSurface.
|
||||
*/
|
||||
void disableAccelerationForSurface() {
|
||||
if (offscreenImage != null) {
|
||||
SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
|
||||
if (sm instanceof D3DVolatileSurfaceManager) {
|
||||
setSurfaceLost(true);
|
||||
((D3DVolatileSurfaceManager)sm).setAccelerationEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validatePipe(SunGraphics2D sg2d) {
|
||||
TextPipe textpipe;
|
||||
boolean validated = false;
|
||||
|
||||
// REMIND: the D3D pipeline doesn't support XOR!, more
|
||||
// fixes will be needed below. For now we disable D3D rendering
|
||||
// for the surface which had any XOR rendering done to.
|
||||
if (sg2d.compositeState >= sg2d.COMP_XOR) {
|
||||
super.validatePipe(sg2d);
|
||||
sg2d.imagepipe = d3dImagePipe;
|
||||
disableAccelerationForSurface();
|
||||
return;
|
||||
}
|
||||
|
||||
// D3DTextRenderer handles both AA and non-AA text, but
|
||||
// only works with the following modes:
|
||||
// (Note: For LCD text we only enter this code path if
|
||||
// canRenderLCDText() has already validated that the mode is
|
||||
// CompositeType.SrcNoEa (opaque color), which will be subsumed
|
||||
// by the CompositeType.SrcNoEa (any color) test below.)
|
||||
|
||||
if (/* CompositeType.SrcNoEa (any color) */
|
||||
(sg2d.compositeState <= sg2d.COMP_ISCOPY &&
|
||||
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) ||
|
||||
|
||||
/* CompositeType.SrcOver (any color) */
|
||||
(sg2d.compositeState == sg2d.COMP_ALPHA &&
|
||||
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR &&
|
||||
(((AlphaComposite)sg2d.composite).getRule() ==
|
||||
AlphaComposite.SRC_OVER)) ||
|
||||
|
||||
/* CompositeType.Xor (any color) */
|
||||
(sg2d.compositeState == sg2d.COMP_XOR &&
|
||||
sg2d.paintState <= sg2d.PAINT_ALPHACOLOR))
|
||||
{
|
||||
textpipe = d3dTextPipe;
|
||||
} else {
|
||||
// do this to initialize textpipe correctly; we will attempt
|
||||
// to override the non-text pipes below
|
||||
super.validatePipe(sg2d);
|
||||
textpipe = sg2d.textpipe;
|
||||
validated = true;
|
||||
}
|
||||
|
||||
PixelToParallelogramConverter txPipe = null;
|
||||
D3DRenderer nonTxPipe = null;
|
||||
|
||||
if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
|
||||
if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {
|
||||
if (sg2d.compositeState <= sg2d.COMP_XOR) {
|
||||
txPipe = d3dTxRenderPipe;
|
||||
nonTxPipe = d3dRenderPipe;
|
||||
}
|
||||
} else if (sg2d.compositeState <= sg2d.COMP_ALPHA) {
|
||||
if (D3DPaints.isValid(sg2d)) {
|
||||
txPipe = d3dTxRenderPipe;
|
||||
nonTxPipe = d3dRenderPipe;
|
||||
}
|
||||
// custom paints handled by super.validatePipe() below
|
||||
}
|
||||
} else {
|
||||
if (sg2d.paintState <= sg2d.PAINT_ALPHACOLOR) {
|
||||
if (graphicsDevice.isCapPresent(CAPS_AA_SHADER) &&
|
||||
(sg2d.imageComp == CompositeType.SrcOverNoEa ||
|
||||
sg2d.imageComp == CompositeType.SrcOver))
|
||||
{
|
||||
if (!validated) {
|
||||
super.validatePipe(sg2d);
|
||||
validated = true;
|
||||
}
|
||||
PixelToParallelogramConverter aaConverter =
|
||||
new PixelToParallelogramConverter(sg2d.shapepipe,
|
||||
d3dAAPgramPipe,
|
||||
1.0/8.0, 0.499,
|
||||
false);
|
||||
sg2d.drawpipe = aaConverter;
|
||||
sg2d.fillpipe = aaConverter;
|
||||
sg2d.shapepipe = aaConverter;
|
||||
} else if (sg2d.compositeState == sg2d.COMP_XOR) {
|
||||
// install the solid pipes when AA and XOR are both enabled
|
||||
txPipe = d3dTxRenderPipe;
|
||||
nonTxPipe = d3dRenderPipe;
|
||||
}
|
||||
}
|
||||
// other cases handled by super.validatePipe() below
|
||||
}
|
||||
|
||||
if (txPipe != null) {
|
||||
if (sg2d.transformState >= sg2d.TRANSFORM_TRANSLATESCALE) {
|
||||
sg2d.drawpipe = txPipe;
|
||||
sg2d.fillpipe = txPipe;
|
||||
} else if (sg2d.strokeState != sg2d.STROKE_THIN) {
|
||||
sg2d.drawpipe = txPipe;
|
||||
sg2d.fillpipe = nonTxPipe;
|
||||
} else {
|
||||
sg2d.drawpipe = nonTxPipe;
|
||||
sg2d.fillpipe = nonTxPipe;
|
||||
}
|
||||
// Note that we use the transforming pipe here because it
|
||||
// will examine the shape and possibly perform an optimized
|
||||
// operation if it can be simplified. The simplifications
|
||||
// will be valid for all STROKE and TRANSFORM types.
|
||||
sg2d.shapepipe = txPipe;
|
||||
} else {
|
||||
if (!validated) {
|
||||
super.validatePipe(sg2d);
|
||||
}
|
||||
}
|
||||
|
||||
// install the text pipe based on our earlier decision
|
||||
sg2d.textpipe = textpipe;
|
||||
|
||||
// always override the image pipe with the specialized D3D pipe
|
||||
sg2d.imagepipe = d3dImagePipe;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MaskFill getMaskFill(SunGraphics2D sg2d) {
|
||||
if (sg2d.paintState > sg2d.PAINT_ALPHACOLOR) {
|
||||
/*
|
||||
* We can only accelerate non-Color MaskFill operations if
|
||||
* all of the following conditions hold true:
|
||||
* - there is an implementation for the given paintState
|
||||
* - the current Paint can be accelerated for this destination
|
||||
* - multitexturing is available (since we need to modulate
|
||||
* the alpha mask texture with the paint texture)
|
||||
*
|
||||
* In all other cases, we return null, in which case the
|
||||
* validation code will choose a more general software-based loop.
|
||||
*/
|
||||
if (!D3DPaints.isValid(sg2d) ||
|
||||
!graphicsDevice.isCapPresent(CAPS_MULTITEXTURE))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.getMaskFill(sg2d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyArea(SunGraphics2D sg2d,
|
||||
int x, int y, int w, int h, int dx, int dy)
|
||||
{
|
||||
if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE &&
|
||||
sg2d.compositeState < sg2d.COMP_XOR)
|
||||
{
|
||||
x += sg2d.transX;
|
||||
y += sg2d.transY;
|
||||
|
||||
d3dRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(FLUSH_SURFACE);
|
||||
buf.putLong(getNativeOps());
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the native resources associated with the given D3DSurfaceData
|
||||
* (referenced by the pData parameter). This method is invoked from
|
||||
* the native Dispose() method from the Disposer thread when the
|
||||
* Java-level D3DSurfaceData object is about to go away.
|
||||
*/
|
||||
static void dispose(long pData) {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_SURFACE);
|
||||
buf.putLong(pData);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static void swapBuffers(D3DSurfaceData sd,
|
||||
final int x1, final int y1,
|
||||
final int x2, final int y2)
|
||||
{
|
||||
long pData = sd.getNativeOps();
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
// swapBuffers can be called from the toolkit thread by swing, we
|
||||
// should detect this and prevent the deadlocks
|
||||
if (rq.isRenderQueueThread()) {
|
||||
if (!rq.tryLock()) {
|
||||
// if we could not obtain the lock, repaint the area
|
||||
// that was supposed to be swapped, and no-op this swap
|
||||
final Component target = (Component)sd.getPeer().getTarget();
|
||||
SunToolkit.executeOnEventHandlerThread(target, new Runnable() {
|
||||
public void run() {
|
||||
target.repaint(x1, y1, x2, y2);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
rq.lock();
|
||||
}
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(28, 4);
|
||||
buf.putInt(SWAP_BUFFERS);
|
||||
buf.putLong(pData);
|
||||
buf.putInt(x1);
|
||||
buf.putInt(y1);
|
||||
buf.putInt(x2);
|
||||
buf.putInt(y2);
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Image associated with this SurfaceData.
|
||||
*/
|
||||
public Object getDestination() {
|
||||
return offscreenImage;
|
||||
}
|
||||
|
||||
public Rectangle getBounds() {
|
||||
if (type == FLIP_BACKBUFFER || type == WINDOW) {
|
||||
Rectangle r = peer.getBounds();
|
||||
r.x = r.y = 0;
|
||||
return r;
|
||||
} else {
|
||||
return new Rectangle(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public Rectangle getNativeBounds() {
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
// need to lock to make sure nativeWidth and Height are consistent
|
||||
// since they are set from the render thread from the native
|
||||
// level
|
||||
rq.lock();
|
||||
try {
|
||||
// REMIND: use xyoffsets?
|
||||
return new Rectangle(nativeWidth, nativeHeight);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return graphicsDevice.getDefaultConfiguration();
|
||||
}
|
||||
|
||||
public SurfaceData getReplacement() {
|
||||
return restoreContents(offscreenImage);
|
||||
}
|
||||
|
||||
private static D3DGraphicsConfig getGC(WComponentPeer peer) {
|
||||
GraphicsConfiguration gc;
|
||||
if (peer != null) {
|
||||
gc = peer.getGraphicsConfiguration();
|
||||
} else {
|
||||
GraphicsEnvironment env =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice gd = env.getDefaultScreenDevice();
|
||||
gc = gd.getDefaultConfiguration();
|
||||
}
|
||||
return (gc instanceof D3DGraphicsConfig) ? (D3DGraphicsConfig)gc : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to restore the surface by initializing the native data
|
||||
*/
|
||||
void restoreSurface() {
|
||||
initSurface();
|
||||
}
|
||||
|
||||
WComponentPeer getPeer() {
|
||||
return peer;
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to let the surface manager know that the surface is lost so
|
||||
* that for example BufferStrategy.contentsLost() returns correct result.
|
||||
* Normally the status of contentsLost is set in validate(), but in some
|
||||
* cases (like Swing's buffer per window) we intentionally don't call
|
||||
* validate from the toolkit thread but only check for the BS status.
|
||||
*/
|
||||
@Override
|
||||
public void setSurfaceLost(boolean lost) {
|
||||
super.setSurfaceLost(lost);
|
||||
if (lost && offscreenImage != null) {
|
||||
SurfaceManager sm = SurfaceManager.getManager(offscreenImage);
|
||||
sm.acceleratedSurfaceLost();
|
||||
}
|
||||
}
|
||||
|
||||
private static native long getNativeResourceNative(long sdops, int resType);
|
||||
/**
|
||||
* Returns a pointer to the native resource of specified {@code resType}
|
||||
* associated with this surface.
|
||||
*
|
||||
* Specifically, for {@code D3DSurfaceData} this method returns pointers of
|
||||
* the following:
|
||||
* <pre>
|
||||
* TEXTURE - (IDirect3DTexture9*)
|
||||
* RT_TEXTURE, RT_PLAIN - (IDirect3DSurface9*)
|
||||
* FLIP_BACKBUFFER - (IDirect3DSwapChain9*)
|
||||
* D3D_DEVICE_RESOURCE - (IDirect3DDevice9*)
|
||||
* </pre>
|
||||
*
|
||||
* Multiple resources may be available for some types (i.e. for render to
|
||||
* texture one could retrieve both a destination surface by specifying
|
||||
* RT_TEXTURE, and a texture by using TEXTURE).
|
||||
*
|
||||
* Note: the pointer returned by this method is only valid on the rendering
|
||||
* thread.
|
||||
*
|
||||
* @return pointer to the native resource of specified type or 0L if
|
||||
* such resource doesn't exist or can not be retrieved.
|
||||
* @see sun.java2d.pipe.hw.AccelSurface#getNativeResource
|
||||
*/
|
||||
public long getNativeResource(int resType) {
|
||||
return getNativeResourceNative(getNativeOps(), resType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class representing an on-screen d3d surface. Since d3d can't
|
||||
* render to the screen directly, it is implemented as a swap chain,
|
||||
* controlled by D3DScreenUpdateManager.
|
||||
*
|
||||
* @see D3DScreenUpdateManager
|
||||
*/
|
||||
public static class D3DWindowSurfaceData extends D3DSurfaceData {
|
||||
StateTracker dirtyTracker;
|
||||
|
||||
public D3DWindowSurfaceData(WComponentPeer peer,
|
||||
D3DGraphicsConfig gc)
|
||||
{
|
||||
super(peer, gc,
|
||||
peer.getBounds().width, peer.getBounds().height,
|
||||
null, peer.getColorModel(), 1, SWAP_COPY, VSYNC_DEFAULT,
|
||||
WINDOW);
|
||||
dirtyTracker = getStateTracker();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* Overridden to use ScreenUpdateManager to obtain the replacement
|
||||
* surface.
|
||||
*
|
||||
* @see sun.java2d.ScreenUpdateManager#getReplacementScreenSurface
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData getReplacement() {
|
||||
ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
|
||||
return mgr.getReplacementScreenSurface(peer, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination Component associated with this SurfaceData.
|
||||
*/
|
||||
@Override
|
||||
public Object getDestination() {
|
||||
return peer.getTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
void disableAccelerationForSurface() {
|
||||
// for on-screen surfaces we need to make sure a backup GDI surface is
|
||||
// is used until a new one is set (which may happen during a resize). We
|
||||
// don't want the screen update maanger to replace the surface right way
|
||||
// because it causes repainting issues in Swing, so we invalidate it,
|
||||
// this will prevent SUM from issuing a replaceSurfaceData call.
|
||||
setSurfaceLost(true);
|
||||
invalidate();
|
||||
flush();
|
||||
peer.disableAcceleration();
|
||||
ScreenUpdateManager.getInstance().dropScreenSurface(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
void restoreSurface() {
|
||||
if (!peer.isAccelCapable()) {
|
||||
throw new InvalidPipeException("Onscreen acceleration " +
|
||||
"disabled for this surface");
|
||||
}
|
||||
Window fsw = graphicsDevice.getFullScreenWindow();
|
||||
if (fsw != null && fsw != peer.getTarget()) {
|
||||
throw new InvalidPipeException("Can't restore onscreen surface"+
|
||||
" when in full-screen mode");
|
||||
}
|
||||
super.restoreSurface();
|
||||
// if initialization was unsuccessful, an IPE will be thrown
|
||||
// and the surface will remain lost
|
||||
setSurfaceLost(false);
|
||||
|
||||
// This is to make sure the render target is reset after this
|
||||
// surface is restored. The reason for this is that sometimes this
|
||||
// surface can be restored from multiple threads (the screen update
|
||||
// manager's thread and app's rendering thread) at the same time,
|
||||
// and when that happens the second restoration will create the
|
||||
// native resource which will not be set as render target because
|
||||
// the BufferedContext's validate method will think that since the
|
||||
// surface data object didn't change then the current render target
|
||||
// is correct and no rendering will appear on the screen.
|
||||
D3DRenderQueue rq = D3DRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
getContext().invalidateContext();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return !dirtyTracker.isCurrent();
|
||||
}
|
||||
|
||||
public void markClean() {
|
||||
dirtyTracker = getStateTracker();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the layered window with the contents of the surface.
|
||||
*
|
||||
* @param pd3dsd pointer to the D3DSDOps structure
|
||||
* @param pData pointer to the AwtWindow peer data
|
||||
* @param w width of the window
|
||||
* @param h height of the window
|
||||
* @see sun.awt.windows.TranslucentWindowPainter
|
||||
*/
|
||||
public static native boolean updateWindowAccelImpl(long pd3dsd, long pData,
|
||||
int w, int h);
|
||||
}
|
||||
93
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceDataProxy.java
Normal file
93
jdkSrc/jdk8/sun/java2d/d3d/D3DSurfaceDataProxy.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Transparency;
|
||||
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.SurfaceDataProxy;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
|
||||
/**
|
||||
* The proxy class contains the logic for when to replace a
|
||||
* SurfaceData with a cached D3D Texture and the code to create
|
||||
* the accelerated surfaces.
|
||||
*/
|
||||
public class D3DSurfaceDataProxy extends SurfaceDataProxy {
|
||||
|
||||
public static SurfaceDataProxy createProxy(SurfaceData srcData,
|
||||
D3DGraphicsConfig dstConfig)
|
||||
{
|
||||
if (srcData instanceof D3DSurfaceData) {
|
||||
// srcData must be a VolatileImage which either matches
|
||||
// our pixel format or not - either way we do not cache it...
|
||||
return UNCACHED;
|
||||
}
|
||||
|
||||
return new D3DSurfaceDataProxy(dstConfig, srcData.getTransparency());
|
||||
}
|
||||
|
||||
D3DGraphicsConfig d3dgc;
|
||||
int transparency;
|
||||
|
||||
public D3DSurfaceDataProxy(D3DGraphicsConfig d3dgc, int transparency) {
|
||||
this.d3dgc = d3dgc;
|
||||
this.transparency = transparency;
|
||||
// REMIND: we may want to change this for the d3d pipeline, it's not
|
||||
// necessary to invalidate them all at once on display change
|
||||
activateDisplayListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceData validateSurfaceData(SurfaceData srcData,
|
||||
SurfaceData cachedData,
|
||||
int w, int h)
|
||||
{
|
||||
if (cachedData == null || cachedData.isSurfaceLost()) {
|
||||
try {
|
||||
cachedData = d3dgc.createManagedSurface(w, h, transparency);
|
||||
} catch (InvalidPipeException e) {
|
||||
if (!d3dgc.getD3DDevice().isD3DAvailable()) {
|
||||
invalidate();
|
||||
flush();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportedOperation(SurfaceData srcData,
|
||||
int txtype,
|
||||
CompositeType comp,
|
||||
Color bgColor)
|
||||
{
|
||||
return (bgColor == null || transparency == Transparency.OPAQUE);
|
||||
}
|
||||
}
|
||||
71
jdkSrc/jdk8/sun/java2d/d3d/D3DTextRenderer.java
Normal file
71
jdkSrc/jdk8/sun/java2d/d3d/D3DTextRenderer.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Composite;
|
||||
import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.pipe.BufferedTextPipe;
|
||||
import sun.java2d.pipe.RenderQueue;
|
||||
|
||||
class D3DTextRenderer extends BufferedTextPipe {
|
||||
|
||||
D3DTextRenderer(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected native void drawGlyphList(int numGlyphs, boolean usePositions,
|
||||
boolean subPixPos, boolean rgbOrder,
|
||||
int lcdContrast,
|
||||
float glOrigX, float glOrigY,
|
||||
long[] images, float[] positions);
|
||||
|
||||
@Override
|
||||
protected void validateContext(SunGraphics2D sg2d, Composite comp) {
|
||||
// assert rq.lock.isHeldByCurrentThread();
|
||||
D3DSurfaceData d3dDst = (D3DSurfaceData)sg2d.surfaceData;
|
||||
D3DContext.validateContext(d3dDst, d3dDst,
|
||||
sg2d.getCompClip(), comp,
|
||||
null, sg2d.paint, sg2d,
|
||||
D3DContext.NO_CONTEXT_FLAGS);
|
||||
}
|
||||
|
||||
D3DTextRenderer traceWrap() {
|
||||
return new Tracer(this);
|
||||
}
|
||||
|
||||
private static class Tracer extends D3DTextRenderer {
|
||||
Tracer(D3DTextRenderer d3dtr) {
|
||||
super(d3dtr.rq);
|
||||
}
|
||||
protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
|
||||
GraphicsPrimitive.tracePrimitive("D3DDrawGlyphs");
|
||||
super.drawGlyphList(sg2d, gl);
|
||||
}
|
||||
}
|
||||
}
|
||||
230
jdkSrc/jdk8/sun/java2d/d3d/D3DVolatileSurfaceManager.java
Normal file
230
jdkSrc/jdk8/sun/java2d/d3d/D3DVolatileSurfaceManager.java
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.d3d;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import sun.awt.Win32GraphicsConfig;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.awt.windows.WComponentPeer;
|
||||
import sun.java2d.InvalidPipeException;
|
||||
import sun.java2d.SurfaceData;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.*;
|
||||
import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
|
||||
import sun.java2d.windows.GDIWindowSurfaceData;
|
||||
|
||||
public class D3DVolatileSurfaceManager
|
||||
extends VolatileSurfaceManager
|
||||
{
|
||||
private boolean accelerationEnabled;
|
||||
private int restoreCountdown;
|
||||
|
||||
public D3DVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
super(vImg, context);
|
||||
|
||||
/*
|
||||
* We will attempt to accelerate this image only under the
|
||||
* following conditions:
|
||||
* - the image is opaque OR
|
||||
* - the image is translucent AND
|
||||
* - the GraphicsConfig supports the FBO extension OR
|
||||
* - the GraphicsConfig has a stored alpha channel
|
||||
*/
|
||||
int transparency = vImg.getTransparency();
|
||||
D3DGraphicsDevice gd = (D3DGraphicsDevice)
|
||||
vImg.getGraphicsConfig().getDevice();
|
||||
accelerationEnabled =
|
||||
(transparency == Transparency.OPAQUE) ||
|
||||
(transparency == Transparency.TRANSLUCENT &&
|
||||
(gd.isCapPresent(CAPS_RT_PLAIN_ALPHA) ||
|
||||
gd.isCapPresent(CAPS_RT_TEXTURE_ALPHA)));
|
||||
}
|
||||
|
||||
protected boolean isAccelerationEnabled() {
|
||||
return accelerationEnabled;
|
||||
}
|
||||
public void setAccelerationEnabled(boolean accelerationEnabled) {
|
||||
this.accelerationEnabled = accelerationEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a pbuffer-based SurfaceData object (or init the backbuffer
|
||||
* of an existing window if this is a double buffered GraphicsConfig).
|
||||
*/
|
||||
protected SurfaceData initAcceleratedSurface() {
|
||||
SurfaceData sData;
|
||||
Component comp = vImg.getComponent();
|
||||
WComponentPeer peer =
|
||||
(comp != null) ? (WComponentPeer)comp.getPeer() : null;
|
||||
|
||||
try {
|
||||
boolean forceback = false;
|
||||
if (context instanceof Boolean) {
|
||||
forceback = ((Boolean)context).booleanValue();
|
||||
}
|
||||
|
||||
if (forceback) {
|
||||
// peer must be non-null in this case
|
||||
sData = D3DSurfaceData.createData(peer, vImg);
|
||||
} else {
|
||||
D3DGraphicsConfig gc =
|
||||
(D3DGraphicsConfig)vImg.getGraphicsConfig();
|
||||
ColorModel cm = gc.getColorModel(vImg.getTransparency());
|
||||
int type = vImg.getForcedAccelSurfaceType();
|
||||
// if acceleration type is forced (type != UNDEFINED) then
|
||||
// use the forced type, otherwise use RT_TEXTURE
|
||||
if (type == UNDEFINED) {
|
||||
type = RT_TEXTURE;
|
||||
}
|
||||
sData = D3DSurfaceData.createData(gc,
|
||||
vImg.getWidth(),
|
||||
vImg.getHeight(),
|
||||
cm, vImg,
|
||||
type);
|
||||
}
|
||||
} catch (NullPointerException ex) {
|
||||
sData = null;
|
||||
} catch (OutOfMemoryError er) {
|
||||
sData = null;
|
||||
} catch (InvalidPipeException ipe) {
|
||||
sData = null;
|
||||
}
|
||||
|
||||
return sData;
|
||||
}
|
||||
|
||||
protected boolean isConfigValid(GraphicsConfiguration gc) {
|
||||
return ((gc == null) || (gc == vImg.getGraphicsConfig()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of iterations for restoreAcceleratedSurface to fail
|
||||
* before attempting to restore the accelerated surface.
|
||||
*
|
||||
* @see #restoreAcceleratedSurface
|
||||
* @see #handleVItoScreenOp
|
||||
*/
|
||||
private synchronized void setRestoreCountdown(int count) {
|
||||
restoreCountdown = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that we create a new surface instead of restoring
|
||||
* an old one. This will help with D3DContext revalidation.
|
||||
*/
|
||||
@Override
|
||||
protected void restoreAcceleratedSurface() {
|
||||
synchronized (this) {
|
||||
if (restoreCountdown > 0) {
|
||||
restoreCountdown--;
|
||||
throw new
|
||||
InvalidPipeException("Will attempt to restore surface " +
|
||||
" in " + restoreCountdown);
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceData sData = initAcceleratedSurface();
|
||||
if (sData != null) {
|
||||
sdAccel = sData;
|
||||
} else {
|
||||
throw new InvalidPipeException("could not restore surface");
|
||||
// REMIND: alternatively, we could try this:
|
||||
// ((D3DSurfaceData)sdAccel).restoreSurface();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We're asked to restore contents by the accelerated surface, which means
|
||||
* that it had been lost.
|
||||
*/
|
||||
@Override
|
||||
public SurfaceData restoreContents() {
|
||||
acceleratedSurfaceLost();
|
||||
return super.restoreContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the destination surface's peer can potentially handle accelerated
|
||||
* on-screen rendering then it is likely that the condition which resulted
|
||||
* in VI to Screen operation is temporary, so this method sets the
|
||||
* restore countdown in hope that the on-screen accelerated rendering will
|
||||
* resume. In the meantime the backup surface of the VISM will be used.
|
||||
*
|
||||
* The countdown is needed because otherwise we may never break out
|
||||
* of "do { vi.validate()..} while(vi.lost)" loop since validate() could
|
||||
* restore the source surface every time and it will get lost again on the
|
||||
* next copy attempt, and we would never get a chance to use the backup
|
||||
* surface. By using the countdown we allow the backup surface to be used
|
||||
* while the screen surface gets sorted out, or if it for some reason can
|
||||
* never be restored.
|
||||
*
|
||||
* If the destination surface's peer could never do accelerated onscreen
|
||||
* rendering then the acceleration for the SurfaceManager associated with
|
||||
* the source surface is disabled forever.
|
||||
*/
|
||||
static void handleVItoScreenOp(SurfaceData src, SurfaceData dst) {
|
||||
if (src instanceof D3DSurfaceData &&
|
||||
dst instanceof GDIWindowSurfaceData)
|
||||
{
|
||||
D3DSurfaceData d3dsd = (D3DSurfaceData)src;
|
||||
SurfaceManager mgr =
|
||||
SurfaceManager.getManager((Image)d3dsd.getDestination());
|
||||
if (mgr instanceof D3DVolatileSurfaceManager) {
|
||||
D3DVolatileSurfaceManager vsm = (D3DVolatileSurfaceManager)mgr;
|
||||
if (vsm != null) {
|
||||
d3dsd.setSurfaceLost(true);
|
||||
|
||||
GDIWindowSurfaceData wsd = (GDIWindowSurfaceData)dst;
|
||||
WComponentPeer p = wsd.getPeer();
|
||||
if (D3DScreenUpdateManager.canUseD3DOnScreen(p,
|
||||
(Win32GraphicsConfig)p.getGraphicsConfiguration(),
|
||||
p.getBackBuffersNum()))
|
||||
{
|
||||
// 10 is only chosen to be greater than the number of
|
||||
// times a sane person would call validate() inside
|
||||
// a validation loop, and to reduce thrashing between
|
||||
// accelerated and backup surfaces
|
||||
vsm.setRestoreCountdown(10);
|
||||
} else {
|
||||
vsm.setAccelerationEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initContents() {
|
||||
if (vImg.getForcedAccelSurfaceType() != TEXTURE) {
|
||||
super.initContents();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user