feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View 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);
}
}

View 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;
}
}

View 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();
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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() {}
}
}

View 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();
}
}

View 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);
}
}
}

View 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;
}
}

View 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);
}

View 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);
}
}

View 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);
}
}
}

View 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();
}
}
}