88 // a pipeline isn't enabled
89 if (gcName.startsWith("D3D")) {
90 return new VIOptD3DWindowPainter(peer);
91 } else if (forceOpt && gcName.startsWith("WGL")) {
92 // on some boards (namely, ATI, even on pcix bus) ogl is
93 // very slow reading pixels back so for now it is disabled
94 // unless forced
95 return new VIOptWGLWindowPainter(peer);
96 }
97 }
98 }
99 return new BIWindowPainter(peer);
100 }
101
102 protected TranslucentWindowPainter(WWindowPeer peer) {
103 this.peer = peer;
104 this.window = (Window)peer.getTarget();
105 }
106
107 /**
108 * Creates (if needed), clears and returns the buffer for this painter.
109 */
110 protected abstract Image getBackBuffer();
111
112 /**
113 * Updates the the window associated with this painter with the contents
114 * of the passed image.
115 * The image can not be null, and NPE will be thrown if it is.
116 */
117 protected abstract boolean update(Image bb);
118
119 /**
120 * Flushes the resources associated with the painter. They will be
121 * recreated as needed.
122 */
123 public abstract void flush();
124
125 /**
126 * Updates the window associated with the painter given the passed image.
127 * If the passed image is null the painter will use its own buffer for
128 * rendering the contents of the window into it and updating the window.
129 *
130 * If the passed buffer has dimensions different from the window, it is
131 * copied into the internal buffer first and the latter is used to update
132 * the window.
133 *
134 * @param bb the image to update the non opaque window with, or null.
135 * If not null, the image must be of ARGB_PRE type.
136 */
137 public void updateWindow(Image bb) {
138 boolean done = false;
139 if (bb != null && (window.getWidth() != bb.getWidth(null) ||
140 window.getHeight() != bb.getHeight(null)))
141 {
142 Image ourBB = getBackBuffer();
143 Graphics2D g = (Graphics2D)ourBB.getGraphics();
144 g.drawImage(bb, 0, 0, null);
145 g.dispose();
146 bb = ourBB;
147 }
148 do {
149 if (bb == null) {
150 bb = getBackBuffer();
151 Graphics2D g = (Graphics2D)bb.getGraphics();
152 try {
153 window.paintAll(g);
154 } finally {
155 g.dispose();
156 }
157 }
158
159 peer.paintAppletWarning((Graphics2D)bb.getGraphics(),
160 bb.getWidth(null), bb.getHeight(null));
161
162 done = update(bb);
163 // in case they passed us a lost VI, next time around we'll use our
164 // own bb because we can not validate and restore the contents of
165 // their VI
166 if (!done) {
167 bb = null;
168 }
169 } while (!done);
170 }
171
172 private static final Image clearImage(Image bb) {
173 Graphics2D g = (Graphics2D)bb.getGraphics();
174 int w = bb.getWidth(null);
175 int h = bb.getHeight(null);
176
177 g.setComposite(AlphaComposite.Src);
178 g.setColor(new Color(0, 0, 0, 0));
179 g.fillRect(0, 0, w, h);
180
181 return bb;
182 }
183
184 /**
185 * A painter which uses BufferedImage as the internal buffer. The window
186 * is painted into this buffer, and the contents then are uploaded
187 * into the layered window.
188 *
189 * This painter handles all types of images passed to its paint(Image)
190 * method (VI, BI, regular Images).
191 */
192 private static class BIWindowPainter extends TranslucentWindowPainter {
193 private WeakReference<BufferedImage> biRef;
194
195 protected BIWindowPainter(WWindowPeer peer) {
196 super(peer);
197 }
198
199 private BufferedImage getBIBackBuffer() {
200 int w = window.getWidth();
201 int h = window.getHeight();
202 BufferedImage bb = biRef == null ? null : biRef.get();
203 if (bb == null || bb.getWidth() != w || bb.getHeight() != h) {
204 if (bb != null) {
205 bb.flush();
206 bb = null;
207 }
208 bb = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
209 biRef = new WeakReference<BufferedImage>(bb);
210 }
211 return (BufferedImage)clearImage(bb);
212 }
213
214 @Override
215 protected Image getBackBuffer() {
216 return getBIBackBuffer();
217 }
218
219 @Override
220 protected boolean update(Image bb) {
221 VolatileImage viBB = null;
222
223 if (bb instanceof BufferedImage) {
224 BufferedImage bi = (BufferedImage)bb;
225 int data[] =
226 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
227 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
228 return true;
229 } else if (bb instanceof VolatileImage) {
230 viBB = (VolatileImage)bb;
231 if (bb instanceof DestSurfaceProvider) {
232 Surface s = ((DestSurfaceProvider)bb).getDestSurface();
233 if (s instanceof BufImgSurfaceData) {
234 // the image is probably lost, upload the data from the
235 // backup surface to avoid creating another heap-based
236 // image (the parent's buffer)
237 int w = viBB.getWidth();
238 int h = viBB.getHeight();
239 BufImgSurfaceData bisd = (BufImgSurfaceData)s;
240 int data[] = ((DataBufferInt)bisd.getRaster(0,0,w,h).
241 getDataBuffer()).getData();
242 peer.updateWindowImpl(data, w, h);
243 return true;
244 }
245 }
246 }
247
248 // copy the passed image into our own buffer, then upload
249 BufferedImage bi = getBIBackBuffer();
250 Graphics2D g = (Graphics2D)bi.getGraphics();
251 g.setComposite(AlphaComposite.Src);
252 g.drawImage(bb, 0, 0, null);
253
254 int data[] =
255 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
256 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
257
258 return (viBB != null ? !viBB.contentsLost() : true);
259 }
260
261 public void flush() {
262 if (biRef != null) {
263 biRef.clear();
264 }
265 }
266 }
267
268 /**
269 * A version of the painter which uses VolatileImage as the internal buffer.
270 * The window is painted into this VI and then copied into the parent's
271 * Java heap-based buffer (which is then uploaded to the layered window)
272 */
273 private static class VIWindowPainter extends BIWindowPainter {
274 private WeakReference<VolatileImage> viRef;
275
276 protected VIWindowPainter(WWindowPeer peer) {
277 super(peer);
278 }
279
280 @Override
281 protected Image getBackBuffer() {
282 int w = window.getWidth();
283 int h = window.getHeight();
284 GraphicsConfiguration gc = peer.getGraphicsConfiguration();
285
286 VolatileImage viBB = viRef == null ? null : viRef.get();
287
288 if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h ||
289 viBB.validate(gc) == IMAGE_INCOMPATIBLE)
290 {
291 if (viBB != null) {
292 viBB.flush();
293 viBB = null;
294 }
295
296 if (gc instanceof AccelGraphicsConfig) {
297 AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc);
298 viBB = agc.createCompatibleVolatileImage(w, h,
299 TRANSLUCENT,
300 RT_PLAIN);
301 }
302 if (viBB == null) {
303 viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT);
304 }
305 viBB.validate(gc);
306 viRef = new WeakReference<VolatileImage>(viBB);
307 }
308
309 return clearImage(viBB);
310 }
311
312 @Override
313 public void flush() {
314 if (viRef != null) {
315 VolatileImage viBB = viRef.get();
316 if (viBB != null) {
317 viBB.flush();
318 viBB = null;
319 }
320 viRef.clear();
321 }
322 }
323 }
324
325 /**
326 * Optimized version of hw painter. Uses VolatileImages for the
327 * buffer, and uses an optimized path to pull the data from those into
328 * the layered window, bypassing Java heap-based image.
329 */
330 private abstract static class VIOptWindowPainter extends VIWindowPainter {
331
332 protected VIOptWindowPainter(WWindowPeer peer) {
333 super(peer);
334 }
335
336 protected abstract boolean updateWindowAccel(long psdops, int w, int h);
337
338 @Override
339 protected boolean update(Image bb) {
340 if (bb instanceof DestSurfaceProvider) {
|
88 // a pipeline isn't enabled
89 if (gcName.startsWith("D3D")) {
90 return new VIOptD3DWindowPainter(peer);
91 } else if (forceOpt && gcName.startsWith("WGL")) {
92 // on some boards (namely, ATI, even on pcix bus) ogl is
93 // very slow reading pixels back so for now it is disabled
94 // unless forced
95 return new VIOptWGLWindowPainter(peer);
96 }
97 }
98 }
99 return new BIWindowPainter(peer);
100 }
101
102 protected TranslucentWindowPainter(WWindowPeer peer) {
103 this.peer = peer;
104 this.window = (Window)peer.getTarget();
105 }
106
107 /**
108 * Creates (if needed), clears (if requested) and returns the buffer
109 * for this painter.
110 */
111 protected abstract Image getBackBuffer(boolean clear);
112
113 /**
114 * Updates the the window associated with this painter with the contents
115 * of the passed image.
116 * The image can not be null, and NPE will be thrown if it is.
117 */
118 protected abstract boolean update(Image bb);
119
120 /**
121 * Flushes the resources associated with the painter. They will be
122 * recreated as needed.
123 */
124 public abstract void flush();
125
126 /**
127 * Updates the window associated with the painter.
128 *
129 * @param repaint indicates if the window should be completely repainted
130 * to the back buffer using {@link java.awt.Window#paintAll} before update.
131 */
132 public void updateWindow(boolean repaint) {
133 boolean done = false;
134 Image bb = getBackBuffer(repaint);
135 while (!done) {
136 if (repaint) {
137 Graphics2D g = (Graphics2D)bb.getGraphics();
138 try {
139 window.paintAll(g);
140 } finally {
141 g.dispose();
142 }
143 }
144
145 done = update(bb);
146 if (!done) {
147 repaint = true;
148 bb = getBackBuffer(true);
149 }
150 }
151 }
152
153 private static final Image clearImage(Image bb) {
154 Graphics2D g = (Graphics2D)bb.getGraphics();
155 int w = bb.getWidth(null);
156 int h = bb.getHeight(null);
157
158 g.setComposite(AlphaComposite.Src);
159 g.setColor(new Color(0, 0, 0, 0));
160 g.fillRect(0, 0, w, h);
161
162 return bb;
163 }
164
165 /**
166 * A painter which uses BufferedImage as the internal buffer. The window
167 * is painted into this buffer, and the contents then are uploaded
168 * into the layered window.
169 *
170 * This painter handles all types of images passed to its paint(Image)
171 * method (VI, BI, regular Images).
172 */
173 private static class BIWindowPainter extends TranslucentWindowPainter {
174 private BufferedImage backBuffer;
175
176 protected BIWindowPainter(WWindowPeer peer) {
177 super(peer);
178 }
179
180 @Override
181 protected Image getBackBuffer(boolean clear) {
182 int w = window.getWidth();
183 int h = window.getHeight();
184 if (backBuffer == null ||
185 backBuffer.getWidth() != w ||
186 backBuffer.getHeight() != h)
187 {
188 flush();
189 backBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
190 }
191 return clear ? (BufferedImage)clearImage(backBuffer) : backBuffer;
192 }
193
194 @Override
195 protected boolean update(Image bb) {
196 VolatileImage viBB = null;
197
198 if (bb instanceof BufferedImage) {
199 BufferedImage bi = (BufferedImage)bb;
200 int data[] =
201 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
202 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
203 return true;
204 } else if (bb instanceof VolatileImage) {
205 viBB = (VolatileImage)bb;
206 if (bb instanceof DestSurfaceProvider) {
207 Surface s = ((DestSurfaceProvider)bb).getDestSurface();
208 if (s instanceof BufImgSurfaceData) {
209 // the image is probably lost, upload the data from the
210 // backup surface to avoid creating another heap-based
211 // image (the parent's buffer)
212 int w = viBB.getWidth();
213 int h = viBB.getHeight();
214 BufImgSurfaceData bisd = (BufImgSurfaceData)s;
215 int data[] = ((DataBufferInt)bisd.getRaster(0,0,w,h).
216 getDataBuffer()).getData();
217 peer.updateWindowImpl(data, w, h);
218 return true;
219 }
220 }
221 }
222
223 // copy the passed image into our own buffer, then upload
224 BufferedImage bi = (BufferedImage)clearImage(backBuffer);
225
226 int data[] =
227 ((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
228 peer.updateWindowImpl(data, bi.getWidth(), bi.getHeight());
229
230 return (viBB != null ? !viBB.contentsLost() : true);
231 }
232
233 public void flush() {
234 if (backBuffer != null) {
235 backBuffer.flush();
236 backBuffer = null;
237 }
238 }
239 }
240
241 /**
242 * A version of the painter which uses VolatileImage as the internal buffer.
243 * The window is painted into this VI and then copied into the parent's
244 * Java heap-based buffer (which is then uploaded to the layered window)
245 */
246 private static class VIWindowPainter extends BIWindowPainter {
247 private VolatileImage viBB;
248
249 protected VIWindowPainter(WWindowPeer peer) {
250 super(peer);
251 }
252
253 @Override
254 protected Image getBackBuffer(boolean clear) {
255 int w = window.getWidth();
256 int h = window.getHeight();
257 GraphicsConfiguration gc = peer.getGraphicsConfiguration();
258
259 if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h ||
260 viBB.validate(gc) == IMAGE_INCOMPATIBLE)
261 {
262 flush();
263
264 if (gc instanceof AccelGraphicsConfig) {
265 AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc);
266 viBB = agc.createCompatibleVolatileImage(w, h,
267 TRANSLUCENT,
268 RT_PLAIN);
269 }
270 if (viBB == null) {
271 viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT);
272 }
273 viBB.validate(gc);
274 }
275
276 return clear ? clearImage(viBB) : viBB;
277 }
278
279 @Override
280 public void flush() {
281 if (viBB != null) {
282 viBB.flush();
283 viBB = null;
284 }
285 }
286 }
287
288 /**
289 * Optimized version of hw painter. Uses VolatileImages for the
290 * buffer, and uses an optimized path to pull the data from those into
291 * the layered window, bypassing Java heap-based image.
292 */
293 private abstract static class VIOptWindowPainter extends VIWindowPainter {
294
295 protected VIOptWindowPainter(WWindowPeer peer) {
296 super(peer);
297 }
298
299 protected abstract boolean updateWindowAccel(long psdops, int w, int h);
300
301 @Override
302 protected boolean update(Image bb) {
303 if (bb instanceof DestSurfaceProvider) {
|