1 /*
2 * Copyright (c) 2011, 2015, 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.opengl;
27
28 import java.awt.Graphics;
29 import java.awt.GraphicsConfiguration;
30 import java.awt.GraphicsDevice;
31 import java.awt.GraphicsEnvironment;
32 import java.awt.Image;
33 import java.awt.Rectangle;
34 import java.awt.image.ColorModel;
35
36 import sun.java2d.SunGraphics2D;
37 import sun.java2d.SurfaceData;
38
39 import sun.lwawt.macosx.CPlatformView;
40
41 public abstract class CGLSurfaceData extends OGLSurfaceData {
42
43 protected final int scale;
44 protected final int width;
45 protected final int height;
46 protected CPlatformView pView;
47 private CGLGraphicsConfig graphicsConfig;
48
49 native void validate(int xoff, int yoff, int width, int height, boolean isOpaque);
50
51 private native void initOps(long pConfigInfo, long pPeerData, long layerPtr,
52 int xoff, int yoff, boolean isOpaque);
53
54 protected CGLSurfaceData(CGLGraphicsConfig gc, ColorModel cm, int type,
55 int width, int height) {
56 super(gc, cm, type);
57 // TEXTURE shouldn't be scaled, it is used for managed BufferedImages.
58 scale = type == TEXTURE ? 1 : gc.getDevice().getScaleFactor();
59 this.width = width * scale;
60 this.height = height * scale;
61 }
62
63 protected CGLSurfaceData(CPlatformView pView, CGLGraphicsConfig gc,
64 ColorModel cm, int type,int width, int height)
65 {
66 this(gc, cm, type, width, height);
67 this.pView = pView;
68 this.graphicsConfig = gc;
69
70 long pConfigInfo = gc.getNativeConfigInfo();
71 long pPeerData = 0L;
72 boolean isOpaque = true;
73 if (pView != null) {
74 pPeerData = pView.getAWTView();
75 isOpaque = pView.isOpaque();
76 }
77 initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque);
78 }
79
80 protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc,
81 ColorModel cm, int type,int width, int height)
82 {
83 this(gc, cm, type, width, height);
84 this.graphicsConfig = gc;
85
86 long pConfigInfo = gc.getNativeConfigInfo();
87 long layerPtr = 0L;
88 boolean isOpaque = true;
89 if (layer != null) {
90 layerPtr = layer.getPointer();
91 isOpaque = layer.isOpaque();
92 }
93 initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque);
94 }
95
96 @Override //SurfaceData
97 public GraphicsConfiguration getDeviceConfiguration() {
98 return graphicsConfig;
99 }
100
101 /**
102 * Creates a SurfaceData object representing the primary (front) buffer of
103 * an on-screen Window.
104 */
105 public static CGLWindowSurfaceData createData(CPlatformView pView) {
106 CGLGraphicsConfig gc = getGC(pView);
107 return new CGLWindowSurfaceData(pView, gc);
108 }
109
110 /**
111 * Creates a SurfaceData object representing the intermediate buffer
112 * between the Java2D flusher thread and the AppKit thread.
113 */
114 public static CGLLayerSurfaceData createData(CGLLayer layer) {
115 CGLGraphicsConfig gc = getGC(layer);
116 Rectangle r = layer.getBounds();
117 return new CGLLayerSurfaceData(layer, gc, r.width, r.height);
118 }
119
120 /**
121 * Creates a SurfaceData object representing the back buffer of a
122 * double-buffered on-screen Window.
123 */
124 public static CGLOffScreenSurfaceData createData(CPlatformView pView,
125 Image image, int type) {
126 CGLGraphicsConfig gc = getGC(pView);
127 Rectangle r = pView.getBounds();
128 if (type == FLIP_BACKBUFFER) {
129 return new CGLOffScreenSurfaceData(pView, gc, r.width, r.height,
130 image, gc.getColorModel(), FLIP_BACKBUFFER);
131 } else {
132 return new CGLVSyncOffScreenSurfaceData(pView, gc, r.width,
133 r.height, image, gc.getColorModel(), type);
134 }
135 }
136
137 /**
138 * Creates a SurfaceData object representing an off-screen buffer (either a
139 * FBO or Texture).
140 */
141 public static CGLOffScreenSurfaceData createData(CGLGraphicsConfig gc,
142 int width, int height, ColorModel cm, Image image, int type) {
143 return new CGLOffScreenSurfaceData(null, gc, width, height, image, cm,
144 type);
145 }
146
147 public static CGLGraphicsConfig getGC(CPlatformView pView) {
148 if (pView != null) {
149 return (CGLGraphicsConfig)pView.getGraphicsConfiguration();
150 } else {
151 // REMIND: this should rarely (never?) happen, but what if
152 // default config is not CGL?
153 GraphicsEnvironment env = GraphicsEnvironment
154 .getLocalGraphicsEnvironment();
155 GraphicsDevice gd = env.getDefaultScreenDevice();
156 return (CGLGraphicsConfig) gd.getDefaultConfiguration();
157 }
158 }
159
160 public static CGLGraphicsConfig getGC(CGLLayer layer) {
161 return (CGLGraphicsConfig)layer.getGraphicsConfiguration();
162 }
163
164 public void validate() {
165 // Overridden in CGLWindowSurfaceData below
166 }
167
168 @Override
169 public int getDefaultScale() {
170 return scale;
171 }
172
173 @Override
174 public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
175 int dx, int dy) {
176 final int state = sg2d.transformState;
177 if (state > SunGraphics2D.TRANSFORM_TRANSLATESCALE
178 || sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
179 return false;
180 }
181 if (state <= SunGraphics2D.TRANSFORM_ANY_TRANSLATE) {
182 x += sg2d.transX;
183 y += sg2d.transY;
184 } else if (state == SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
185 final double[] coords = {x, y, x + w, y + h, x + dx, y + dy};
186 sg2d.transform.transform(coords, 0, coords, 0, 3);
187 x = (int) Math.ceil(coords[0] - 0.5);
188 y = (int) Math.ceil(coords[1] - 0.5);
189 w = ((int) Math.ceil(coords[2] - 0.5)) - x;
190 h = ((int) Math.ceil(coords[3] - 0.5)) - y;
191 dx = ((int) Math.ceil(coords[4] - 0.5)) - x;
192 dy = ((int) Math.ceil(coords[5] - 0.5)) - y;
193 }
194 oglRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
195 return true;
196 }
197
198 protected native void clearWindow();
199
200 public static class CGLWindowSurfaceData extends CGLSurfaceData {
201
202 public CGLWindowSurfaceData(CPlatformView pView,
203 CGLGraphicsConfig gc) {
204 super(pView, gc, gc.getColorModel(), WINDOW, 0, 0);
205 }
206
207 @Override
208 public SurfaceData getReplacement() {
209 return pView.getSurfaceData();
210 }
211
212 @Override
213 public Rectangle getBounds() {
214 Rectangle r = pView.getBounds();
215 return new Rectangle(0, 0, r.width, r.height);
216 }
217
218 /**
219 * Returns destination Component associated with this SurfaceData.
220 */
221 @Override
222 public Object getDestination() {
223 return pView.getDestination();
224 }
225
226 public void validate() {
227 OGLRenderQueue rq = OGLRenderQueue.getInstance();
228 rq.lock();
229 try {
230 rq.flushAndInvokeNow(new Runnable() {
231 public void run() {
232 Rectangle peerBounds = pView.getBounds();
233 validate(0, 0, peerBounds.width, peerBounds.height, pView.isOpaque());
234 }
235 });
236 } finally {
237 rq.unlock();
238 }
239 }
240
241 @Override
242 public void invalidate() {
243 super.invalidate();
244 clearWindow();
245 }
246 }
247
248 /**
249 * A surface which implements an intermediate buffer between
250 * the Java2D flusher thread and the AppKit thread.
251 *
252 * This surface serves as a buffer attached to a CGLLayer and
253 * the layer redirects all painting to the buffer's graphics.
254 */
255 public static class CGLLayerSurfaceData extends CGLSurfaceData {
256
257 private CGLLayer layer;
258
259 public CGLLayerSurfaceData(CGLLayer layer, CGLGraphicsConfig gc,
260 int width, int height) {
261 super(layer, gc, gc.getColorModel(), FBOBJECT, width, height);
262 this.layer = layer;
263 initSurface(this.width, this.height);
264 }
265
266 @Override
267 public SurfaceData getReplacement() {
268 return layer.getSurfaceData();
269 }
270
271 @Override
272 boolean isOnScreen() {
273 return true;
274 }
275
276 @Override
277 public Rectangle getBounds() {
278 return new Rectangle(width, height);
279 }
280
281 @Override
282 public Object getDestination() {
283 return layer.getDestination();
284 }
285
286 @Override
287 public int getTransparency() {
288 return layer.getTransparency();
289 }
290
291 @Override
292 public void invalidate() {
293 super.invalidate();
294 clearWindow();
295 }
296 }
297
298 /**
299 * A surface which implements a v-synced flip back-buffer with COPIED
300 * FlipContents.
301 *
302 * This surface serves as a back-buffer to the outside world, while it is
303 * actually an offscreen surface. When the BufferStrategy this surface
304 * belongs to is showed, it is first copied to the real private
305 * FLIP_BACKBUFFER, which is then flipped.
306 */
307 public static class CGLVSyncOffScreenSurfaceData extends
308 CGLOffScreenSurfaceData {
309 private CGLOffScreenSurfaceData flipSurface;
310
311 public CGLVSyncOffScreenSurfaceData(CPlatformView pView,
312 CGLGraphicsConfig gc, int width, int height, Image image,
313 ColorModel cm, int type) {
314 super(pView, gc, width, height, image, cm, type);
315 flipSurface = CGLSurfaceData.createData(pView, image,
316 FLIP_BACKBUFFER);
317 }
318
319 public SurfaceData getFlipSurface() {
320 return flipSurface;
321 }
322
323 @Override
324 public void flush() {
325 flipSurface.flush();
326 super.flush();
327 }
328 }
329
330 public static class CGLOffScreenSurfaceData extends CGLSurfaceData {
331 private Image offscreenImage;
332
333 public CGLOffScreenSurfaceData(CPlatformView pView,
334 CGLGraphicsConfig gc, int width, int height, Image image,
335 ColorModel cm, int type) {
336 super(pView, gc, cm, type, width, height);
337 offscreenImage = image;
338 initSurface(this.width, this.height);
339 }
340
341 @Override
342 public SurfaceData getReplacement() {
343 return restoreContents(offscreenImage);
344 }
345
346 @Override
347 public Rectangle getBounds() {
348 if (type == FLIP_BACKBUFFER) {
349 Rectangle r = pView.getBounds();
350 return new Rectangle(0, 0, r.width, r.height);
351 } else {
352 return new Rectangle(width, height);
353 }
354 }
355
356 /**
357 * Returns destination Image associated with this SurfaceData.
358 */
359 @Override
360 public Object getDestination() {
361 return offscreenImage;
362 }
363 }
364
365 // Mac OS X specific APIs for JOGL/Java2D bridge...
366
367 // given a surface create and attach GL context, then return it
368 private native static long createCGLContextOnSurface(CGLSurfaceData sd,
369 long sharedContext);
370
371 public static long createOGLContextOnSurface(Graphics g, long sharedContext) {
372 SurfaceData sd = ((SunGraphics2D) g).surfaceData;
373 if ((sd instanceof CGLSurfaceData) == true) {
374 CGLSurfaceData cglsd = (CGLSurfaceData) sd;
375 return createCGLContextOnSurface(cglsd, sharedContext);
376 } else {
377 return 0L;
378 }
379 }
380
381 // returns whether or not the makeCurrent operation succeeded
382 native static boolean makeCGLContextCurrentOnSurface(CGLSurfaceData sd,
383 long ctx);
384
385 public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) {
386 SurfaceData sd = ((SunGraphics2D) g).surfaceData;
387 if ((ctx != 0L) && ((sd instanceof CGLSurfaceData) == true)) {
388 CGLSurfaceData cglsd = (CGLSurfaceData) sd;
389 return makeCGLContextCurrentOnSurface(cglsd, ctx);
390 } else {
391 return false;
392 }
393 }
394
395 // additional cleanup
396 private native static void destroyCGLContext(long ctx);
397
398 public static void destroyOGLContext(long ctx) {
399 if (ctx != 0L) {
400 destroyCGLContext(ctx);
401 }
402 }
403 }
--- EOF ---