1/*
2 * Copyright (c) 2004, 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
26package sun.java2d.opengl;
27
28import sun.java2d.pipe.BufferedContext;
29import sun.java2d.pipe.RenderBuffer;
30import sun.java2d.pipe.RenderQueue;
31import sun.java2d.pipe.hw.ContextCapabilities;
32import static sun.java2d.pipe.BufferedOpCodes.*;
33import static sun.java2d.pipe.hw.ContextCapabilities.*;
34
35import java.lang.annotation.Native;
36
37/**
38 * Note that the RenderQueue lock must be acquired before calling any of
39 * the methods in this class.
40 */
41public class OGLContext extends BufferedContext {
42
43    private final OGLGraphicsConfig config;
44
45    OGLContext(RenderQueue rq, OGLGraphicsConfig config) {
46        super(rq);
47        this.config = config;
48    }
49
50    /**
51     * Convenience method that delegates to setScratchSurface() below.
52     */
53    static void setScratchSurface(OGLGraphicsConfig gc) {
54        setScratchSurface(gc.getNativeConfigInfo());
55    }
56
57    /**
58     * Makes the given GraphicsConfig's context current to its associated
59     * "scratch surface".  Each GraphicsConfig maintains a native context
60     * (GLXContext on Unix, HGLRC on Windows) as well as a native pbuffer
61     * known as the "scratch surface".  By making the context current to the
62     * scratch surface, we are assured that we have a current context for
63     * the relevant GraphicsConfig, and can therefore perform operations
64     * depending on the capabilities of that GraphicsConfig.  For example,
65     * if the GraphicsConfig supports the GL_ARB_texture_non_power_of_two
66     * extension, then we should be able to make a non-pow2 texture for this
67     * GraphicsConfig once we make the context current to the scratch surface.
68     *
69     * This method should be used for operations with an OpenGL texture
70     * as the destination surface (e.g. a sw->texture blit loop), or in those
71     * situations where we may not otherwise have a current context (e.g.
72     * when disposing a texture-based surface).
73     */
74    static void setScratchSurface(long pConfigInfo) {
75        // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread();
76
77        // invalidate the current context
78        currentContext = null;
79
80        // set the scratch context
81        OGLRenderQueue rq = OGLRenderQueue.getInstance();
82        RenderBuffer buf = rq.getBuffer();
83        rq.ensureCapacityAndAlignment(12, 4);
84        buf.putInt(SET_SCRATCH_SURFACE);
85        buf.putLong(pConfigInfo);
86    }
87
88    /**
89     * Invalidates the currentContext field to ensure that we properly
90     * revalidate the OGLContext (make it current, etc.) next time through
91     * the validate() method.  This is typically invoked from methods
92     * that affect the current context state (e.g. disposing a context or
93     * surface).
94     */
95    static void invalidateCurrentContext() {
96        // assert OGLRenderQueue.getInstance().lock.isHeldByCurrentThread();
97
98        // invalidate the current Java-level context so that we
99        // revalidate everything the next time around
100        if (currentContext != null) {
101            currentContext.invalidateContext();
102            currentContext = null;
103        }
104
105        // invalidate the context reference at the native level, and
106        // then flush the queue so that we have no pending operations
107        // dependent on the current context
108        OGLRenderQueue rq = OGLRenderQueue.getInstance();
109        rq.ensureCapacity(4);
110        rq.getBuffer().putInt(INVALIDATE_CONTEXT);
111        rq.flushNow();
112    }
113
114    public RenderQueue getRenderQueue() {
115        return OGLRenderQueue.getInstance();
116    }
117
118    /**
119     * Returns a string representing adapter id (vendor, renderer, version).
120     * Must be called on the rendering thread.
121     *
122     * @return an id string for the adapter
123     */
124    static final native String getOGLIdString();
125
126    @Override
127    public void saveState() {
128        // assert rq.lock.isHeldByCurrentThread();
129
130        // reset all attributes of this and current contexts
131        invalidateContext();
132        invalidateCurrentContext();
133
134        setScratchSurface(config);
135
136        // save the state on the native level
137        rq.ensureCapacity(4);
138        buf.putInt(SAVE_STATE);
139        rq.flushNow();
140    }
141
142    @Override
143    public void restoreState() {
144        // assert rq.lock.isHeldByCurrentThread();
145
146        // reset all attributes of this and current contexts
147        invalidateContext();
148        invalidateCurrentContext();
149
150        setScratchSurface(config);
151
152        // restore the state on the native level
153        rq.ensureCapacity(4);
154        buf.putInt(RESTORE_STATE);
155        rq.flushNow();
156    }
157
158    static class OGLContextCaps extends ContextCapabilities {
159        /**
160         * Indicates the presence of the GL_EXT_framebuffer_object extension.
161         * This cap will only be set if the fbobject system property has been
162         * enabled and we are able to create an FBO with depth buffer.
163         */
164        @Native
165        static final int CAPS_EXT_FBOBJECT     =
166                (CAPS_RT_TEXTURE_ALPHA | CAPS_RT_TEXTURE_OPAQUE);
167        /** Indicates that the context is doublebuffered. */
168        @Native
169        static final int CAPS_DOUBLEBUFFERED   = (FIRST_PRIVATE_CAP << 0);
170        /**
171         * Indicates the presence of the GL_ARB_fragment_shader extension.
172         * This cap will only be set if the lcdshader system property has been
173         * enabled and the hardware supports the minimum number of texture units
174         */
175        @Native
176        static final int CAPS_EXT_LCD_SHADER   = (FIRST_PRIVATE_CAP << 1);
177        /**
178         * Indicates the presence of the GL_ARB_fragment_shader extension.
179         * This cap will only be set if the biopshader system property has been
180         * enabled and the hardware meets our minimum requirements.
181         */
182        @Native
183        static final int CAPS_EXT_BIOP_SHADER  = (FIRST_PRIVATE_CAP << 2);
184        /**
185         * Indicates the presence of the GL_ARB_fragment_shader extension.
186         * This cap will only be set if the gradshader system property has been
187         * enabled and the hardware meets our minimum requirements.
188         */
189        @Native
190        static final int CAPS_EXT_GRAD_SHADER  = (FIRST_PRIVATE_CAP << 3);
191        /** Indicates the presence of the GL_ARB_texture_rectangle extension. */
192        @Native
193        static final int CAPS_EXT_TEXRECT      = (FIRST_PRIVATE_CAP << 4);
194        /** Indicates the presence of the GL_NV_texture_barrier extension. */
195        @Native
196        static final int CAPS_EXT_TEXBARRIER = (FIRST_PRIVATE_CAP << 5);
197
198
199        OGLContextCaps(int caps, String adapterId) {
200            super(caps, adapterId);
201        }
202
203        @Override
204        public String toString() {
205            StringBuilder sb = new StringBuilder(super.toString());
206            if ((caps & CAPS_EXT_FBOBJECT) != 0) {
207                sb.append("CAPS_EXT_FBOBJECT|");
208            }
209            if ((caps & CAPS_DOUBLEBUFFERED) != 0) {
210                sb.append("CAPS_DOUBLEBUFFERED|");
211            }
212            if ((caps & CAPS_EXT_LCD_SHADER) != 0) {
213                sb.append("CAPS_EXT_LCD_SHADER|");
214            }
215            if ((caps & CAPS_EXT_BIOP_SHADER) != 0) {
216                sb.append("CAPS_BIOP_SHADER|");
217            }
218            if ((caps & CAPS_EXT_GRAD_SHADER) != 0) {
219                sb.append("CAPS_EXT_GRAD_SHADER|");
220            }
221            if ((caps & CAPS_EXT_TEXRECT) != 0) {
222                sb.append("CAPS_EXT_TEXRECT|");
223            }
224            if ((caps & CAPS_EXT_TEXBARRIER) != 0) {
225                sb.append("CAPS_EXT_TEXBARRIER|");
226            }
227            return sb.toString();
228        }
229    }
230}
231