1 /*
2 * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.java2d.d3d;
27
28 import java.awt.AWTException;
29 import java.awt.BufferCapabilities;
30 import java.awt.BufferCapabilities.FlipContents;
31 import java.awt.Component;
32 import java.awt.Graphics;
33 import java.awt.ImageCapabilities;
34 import java.awt.Transparency;
35 import java.awt.color.ColorSpace;
36 import java.awt.image.ColorModel;
37 import java.awt.image.DataBuffer;
38 import java.awt.image.DirectColorModel;
39 import java.awt.image.VolatileImage;
40 import sun.awt.Win32GraphicsConfig;
41 import sun.awt.image.SunVolatileImage;
42 import sun.awt.image.SurfaceManager;
43 import sun.awt.windows.WComponentPeer;
44 import sun.java2d.Surface;
45 import sun.java2d.SurfaceData;
46 import sun.java2d.pipe.hw.AccelDeviceEventNotifier;
47 import sun.java2d.pipe.hw.AccelTypedVolatileImage;
48 import sun.java2d.pipe.hw.AccelGraphicsConfig;
49 import sun.java2d.pipe.hw.AccelSurface;
50 import sun.java2d.pipe.hw.ContextCapabilities;
51 import static sun.java2d.pipe.hw.AccelSurface.*;
52 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
53 import sun.java2d.pipe.hw.AccelDeviceEventListener;
54
55 public class D3DGraphicsConfig
56 extends Win32GraphicsConfig
57 implements AccelGraphicsConfig
58 {
59 private static ImageCapabilities imageCaps = new D3DImageCaps();
60
61 private BufferCapabilities bufferCaps;
62 private D3DGraphicsDevice device;
63
64 protected D3DGraphicsConfig(D3DGraphicsDevice device) {
65 super(device, 0);
66 this.device = device;
67 }
68
69 public SurfaceData createManagedSurface(int w, int h, int transparency) {
70 return D3DSurfaceData.createData(this, w, h,
71 getColorModel(transparency),
72 null,
73 D3DSurfaceData.TEXTURE);
74 }
75
76 @Override
77 public synchronized void displayChanged() {
78 super.displayChanged();
79 // the context could hold a reference to a D3DSurfaceData, which in
80 // turn has a reference back to this D3DGraphicsConfig, so in order
81 // for this instance to be disposed we need to break the connection
82 D3DRenderQueue rq = D3DRenderQueue.getInstance();
83 rq.lock();
84 try {
85 D3DContext.invalidateCurrentContext();
86 } finally {
87 rq.unlock();
88 }
89 }
90
91 @Override
92 public ColorModel getColorModel(int transparency) {
93 switch (transparency) {
94 case Transparency.OPAQUE:
95 // REMIND: once the ColorModel spec is changed, this should be
96 // an opaque premultiplied DCM...
97 return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
98 case Transparency.BITMASK:
99 return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
100 case Transparency.TRANSLUCENT:
101 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
102 return new DirectColorModel(cs, 32,
103 0xff0000, 0xff00, 0xff, 0xff000000,
104 true, DataBuffer.TYPE_INT);
105 default:
106 return null;
107 }
108 }
109
110 @Override
111 public String toString() {
112 return ("D3DGraphicsConfig[dev="+screen+",pixfmt="+visual+"]");
113 }
114
115 /**
116 * The following methods are invoked from WComponentPeer.java rather
117 * than having the Win32-dependent implementations hardcoded in that
118 * class. This way the appropriate actions are taken based on the peer's
119 * GraphicsConfig, whether it is a Win32GraphicsConfig or a
120 * D3DGraphicsConfig.
121 */
122
123 /**
124 * Creates a new SurfaceData that will be associated with the given
125 * WComponentPeer. D3D9 doesn't allow rendering to the screen,
126 * so a GDI surface will be returned.
127 */
128 @Override
129 public SurfaceData createSurfaceData(WComponentPeer peer,
130 int numBackBuffers)
131 {
132 return super.createSurfaceData(peer, numBackBuffers);
133 }
134
135 /**
136 * The following methods correspond to the multibuffering methods in
137 * WComponentPeer.java...
138 */
139
140 /**
141 * Checks that the requested configuration is natively supported; if not,
142 * an AWTException is thrown.
143 */
144 @Override
145 public void assertOperationSupported(Component target,
146 int numBuffers,
147 BufferCapabilities caps)
148 throws AWTException
149 {
150 if (numBuffers < 2 || numBuffers > 4) {
151 throw new AWTException("Only 2-4 buffers supported");
152 }
153 if (caps.getFlipContents() == BufferCapabilities.FlipContents.COPIED &&
154 numBuffers != 2)
155 {
156 throw new AWTException("FlipContents.COPIED is only" +
157 "supported for 2 buffers");
158 }
159 }
160
161 /**
162 * Creates a D3D-based backbuffer for the given peer and returns the
163 * image wrapper.
164 */
165 @Override
166 public VolatileImage createBackBuffer(WComponentPeer peer) {
167 Component target = (Component)peer.getTarget();
168 // it is possible for the component to have size 0x0, adjust it to
169 // be at least 1x1 to avoid IAE
170 int w = Math.max(1, target.getWidth());
171 int h = Math.max(1, target.getHeight());
172 return new SunVolatileImage(target, w, h, Boolean.TRUE);
173 }
174
175 /**
176 * Performs the native D3D flip operation for the given target Component.
177 */
178 @Override
179 public void flip(WComponentPeer peer,
180 Component target, VolatileImage backBuffer,
181 int x1, int y1, int x2, int y2,
182 BufferCapabilities.FlipContents flipAction)
183 {
184 // REMIND: we should actually get a surface data for the
185 // backBuffer's VI
186 SurfaceManager d3dvsm =
187 SurfaceManager.getManager(backBuffer);
188 SurfaceData sd = d3dvsm.getPrimarySurfaceData();
189 if (sd instanceof D3DSurfaceData) {
190 D3DSurfaceData d3dsd = (D3DSurfaceData)sd;
191 D3DSurfaceData.swapBuffers(d3dsd, x1, y1, x2, y2);
192 } else {
193 // the surface was likely lost could not have been restored
194 Graphics g = peer.getGraphics();
195 try {
196 g.drawImage(backBuffer,
197 x1, y1, x2, y2,
198 x1, y1, x2, y2,
199 null);
200 } finally {
201 g.dispose();
202 }
203 }
204
205 if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
206 Graphics g = backBuffer.getGraphics();
207 try {
208 g.setColor(target.getBackground());
209 g.fillRect(0, 0,
210 backBuffer.getWidth(),
211 backBuffer.getHeight());
212 } finally {
213 g.dispose();
214 }
215 }
216 }
217
218 private static class D3DBufferCaps extends BufferCapabilities {
219 public D3DBufferCaps() {
220 // REMIND: should we indicate that the front-buffer
221 // (the on-screen rendering) is not accelerated?
222 super(imageCaps, imageCaps, FlipContents.UNDEFINED);
223 }
224 @Override
225 public boolean isMultiBufferAvailable() {
226 return true;
227 }
228
229 }
230
231 @Override
232 public BufferCapabilities getBufferCapabilities() {
233 if (bufferCaps == null) {
234 bufferCaps = new D3DBufferCaps();
235 }
236 return bufferCaps;
237 }
238
239 private static class D3DImageCaps extends ImageCapabilities {
240 private D3DImageCaps() {
241 super(true);
242 }
243 @Override
244 public boolean isTrueVolatile() {
245 return true;
246 }
247 }
248
249 @Override
250 public ImageCapabilities getImageCapabilities() {
251 return imageCaps;
252 }
253
254 D3DGraphicsDevice getD3DDevice() {
255 return device;
256 }
257
258 /**
259 * {@inheritDoc}
260 *
261 * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
262 */
263 @Override
264 public D3DContext getContext() {
265 return device.getContext();
266 }
267
268 /**
269 * {@inheritDoc}
270 *
271 * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
272 */
273 @Override
274 public VolatileImage
275 createCompatibleVolatileImage(int width, int height,
276 int transparency, int type)
277 {
278 if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
279 transparency == Transparency.BITMASK)
280 {
281 return null;
282 }
283 boolean isOpaque = transparency == Transparency.OPAQUE;
284 if (type == RT_TEXTURE) {
285 int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
286 if (!device.isCapPresent(cap)) {
287 return null;
288 }
289 } else if (type == RT_PLAIN) {
290 if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) {
291 return null;
292 }
293 }
294
295 SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
296 transparency, type);
297 Surface sd = vi.getDestSurface();
298 if (!(sd instanceof AccelSurface) ||
299 ((AccelSurface)sd).getType() != type)
300 {
301 vi.flush();
302 vi = null;
303 }
304
305 return vi;
306 }
307
308 /**
309 * {@inheritDoc}
310 *
311 * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
312 */
313 @Override
314 public ContextCapabilities getContextCapabilities() {
315 return device.getContextCapabilities();
316 }
317
318 @Override
319 public void addDeviceEventListener(AccelDeviceEventListener l) {
320 AccelDeviceEventNotifier.addListener(l, device.getScreen());
321 }
322
323 @Override
324 public void removeDeviceEventListener(AccelDeviceEventListener l) {
325 AccelDeviceEventNotifier.removeListener(l);
326 }
327 }
--- EOF ---