1/*
2 * Copyright (c) 2003, 2017, 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
26package sun.java2d.opengl;
27
28import java.awt.GraphicsConfiguration;
29import java.awt.GraphicsDevice;
30import java.awt.GraphicsEnvironment;
31import java.awt.Image;
32import java.awt.Rectangle;
33import java.awt.image.ColorModel;
34
35import sun.awt.X11ComponentPeer;
36import sun.java2d.SurfaceData;
37
38public abstract class GLXSurfaceData extends OGLSurfaceData {
39
40    protected X11ComponentPeer peer;
41    private GLXGraphicsConfig graphicsConfig;
42
43    private native void initOps(X11ComponentPeer peer, long aData);
44
45    protected GLXSurfaceData(X11ComponentPeer peer, GLXGraphicsConfig gc,
46                             ColorModel cm, int type)
47    {
48        super(gc, cm, type);
49        this.peer = peer;
50        this.graphicsConfig = gc;
51        initOps(peer, graphicsConfig.getAData());
52    }
53
54    public GraphicsConfiguration getDeviceConfiguration() {
55        return graphicsConfig;
56    }
57
58    /**
59     * Creates a SurfaceData object representing the primary (front) buffer
60     * of an on-screen Window.
61     */
62    public static GLXWindowSurfaceData createData(X11ComponentPeer peer) {
63        GLXGraphicsConfig gc = getGC(peer);
64        return new GLXWindowSurfaceData(peer, gc);
65    }
66
67    /**
68     * Creates a SurfaceData object representing the back buffer of a
69     * double-buffered on-screen Window.
70     */
71    public static GLXOffScreenSurfaceData createData(X11ComponentPeer peer,
72                                                     Image image,
73                                                     int type)
74    {
75        GLXGraphicsConfig gc = getGC(peer);
76        Rectangle r = peer.getBounds();
77        if (type == FLIP_BACKBUFFER) {
78            return new GLXOffScreenSurfaceData(peer, gc, r.width, r.height,
79                                               image, peer.getColorModel(),
80                                               FLIP_BACKBUFFER);
81        } else {
82            return new GLXVSyncOffScreenSurfaceData(peer, gc, r.width, r.height,
83                                                    image, peer.getColorModel(),
84                                                    type);
85        }
86    }
87
88    /**
89     * Creates a SurfaceData object representing an off-screen buffer (either
90     * a FBO or Texture).
91     */
92    public static GLXOffScreenSurfaceData createData(GLXGraphicsConfig gc,
93                                                     int width, int height,
94                                                     ColorModel cm,
95                                                     Image image, int type)
96    {
97        return new GLXOffScreenSurfaceData(null, gc, width, height,
98                                           image, cm, type);
99    }
100
101    public static GLXGraphicsConfig getGC(X11ComponentPeer peer) {
102        if (peer != null) {
103            return (GLXGraphicsConfig)peer.getGraphicsConfiguration();
104        } else {
105            // REMIND: this should rarely (never?) happen, but what if
106            //         default config is not GLX?
107            GraphicsEnvironment env =
108                GraphicsEnvironment.getLocalGraphicsEnvironment();
109            GraphicsDevice gd = env.getDefaultScreenDevice();
110            return (GLXGraphicsConfig)gd.getDefaultConfiguration();
111        }
112    }
113
114    public static class GLXWindowSurfaceData extends GLXSurfaceData {
115        protected final int scale;
116
117        public GLXWindowSurfaceData(X11ComponentPeer peer,
118                                    GLXGraphicsConfig gc)
119        {
120            super(peer, gc, peer.getColorModel(), WINDOW);
121            scale = gc.getScale();
122        }
123
124        public SurfaceData getReplacement() {
125            return peer.getSurfaceData();
126        }
127
128        public Rectangle getBounds() {
129            Rectangle r = peer.getBounds();
130            r.x = r.y = 0;
131            r.width = (int) Math.ceil(r.width * scale);
132            r.height = (int) Math.ceil(r.height * scale);
133            return r;
134        }
135
136        /**
137         * Returns destination Component associated with this SurfaceData.
138         */
139        public Object getDestination() {
140            return peer.getTarget();
141        }
142
143        @Override
144        public double getDefaultScaleX() {
145            return scale;
146        }
147
148        @Override
149        public double getDefaultScaleY() {
150            return scale;
151        }
152    }
153
154    /**
155     * A surface which implements a v-synced flip back-buffer with COPIED
156     * FlipContents.
157     *
158     * This surface serves as a back-buffer to the outside world, while
159     * it is actually an offscreen surface. When the BufferStrategy this surface
160     * belongs to is showed, it is first copied to the real private
161     * FLIP_BACKBUFFER, which is then flipped.
162     */
163    public static class GLXVSyncOffScreenSurfaceData extends
164        GLXOffScreenSurfaceData
165    {
166        private GLXOffScreenSurfaceData flipSurface;
167
168        public GLXVSyncOffScreenSurfaceData(X11ComponentPeer peer,
169                                            GLXGraphicsConfig gc,
170                                            int width, int height,
171                                            Image image, ColorModel cm,
172                                            int type)
173        {
174            super(peer, gc, width, height, image, cm, type);
175            flipSurface = GLXSurfaceData.createData(peer, image, FLIP_BACKBUFFER);
176        }
177
178        public SurfaceData getFlipSurface() {
179            return flipSurface;
180        }
181
182        @Override
183        public void flush() {
184            flipSurface.flush();
185            super.flush();
186        }
187
188    }
189
190    public static class GLXOffScreenSurfaceData extends GLXSurfaceData {
191
192        private Image offscreenImage;
193        private int width, height;
194        private final int scale;
195
196        public GLXOffScreenSurfaceData(X11ComponentPeer peer,
197                                       GLXGraphicsConfig gc,
198                                       int width, int height,
199                                       Image image, ColorModel cm,
200                                       int type)
201        {
202            super(peer, gc, cm, type);
203
204            scale = gc.getDevice().getScaleFactor();
205            this.width = width * scale;
206            this.height = height * scale;
207            offscreenImage = image;
208
209            initSurface(this.width, this.height);
210        }
211
212        public SurfaceData getReplacement() {
213            return restoreContents(offscreenImage);
214        }
215
216        public Rectangle getBounds() {
217            if (type == FLIP_BACKBUFFER) {
218                Rectangle r = peer.getBounds();
219                r.x = r.y = 0;
220                r.width = (int) Math.ceil(r.width * scale);
221                r.height = (int) Math.ceil(r.height * scale);
222                return r;
223            } else {
224                return new Rectangle(width, height);
225            }
226        }
227
228        /**
229         * Returns destination Image associated with this SurfaceData.
230         */
231        public Object getDestination() {
232            return offscreenImage;
233        }
234
235        @Override
236        public double getDefaultScaleX() {
237            return scale;
238        }
239
240        @Override
241        public double getDefaultScaleY() {
242            return scale;
243        }
244    }
245}
246