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
26package sun.java2d.opengl;
27
28import sun.lwawt.macosx.CFRetainedResource;
29import sun.lwawt.LWWindowPeer;
30
31import sun.java2d.SurfaceData;
32import sun.java2d.NullSurfaceData;
33
34import sun.awt.CGraphicsConfig;
35
36import java.awt.Rectangle;
37import java.awt.GraphicsConfiguration;
38import java.awt.Transparency;
39
40public class CGLLayer extends CFRetainedResource {
41
42    private native long nativeCreateLayer();
43    private static native void nativeSetScale(long layerPtr, double scale);
44    private static native void validate(long layerPtr, CGLSurfaceData cglsd);
45    private static native void blitTexture(long layerPtr);
46
47    private LWWindowPeer peer;
48    private int scale = 1;
49
50    private SurfaceData surfaceData; // represents intermediate buffer (texture)
51
52    public CGLLayer(LWWindowPeer peer) {
53        super(0, true);
54
55        setPtr(nativeCreateLayer());
56        this.peer = peer;
57    }
58
59    public long getPointer() {
60        return ptr;
61    }
62
63    public Rectangle getBounds() {
64        return peer.getBounds();
65    }
66
67    public GraphicsConfiguration getGraphicsConfiguration() {
68        return peer.getGraphicsConfiguration();
69    }
70
71    public boolean isOpaque() {
72        return !peer.isTranslucent();
73    }
74
75    public int getTransparency() {
76        return isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT;
77    }
78
79    public Object getDestination() {
80        return peer.getTarget();
81    }
82
83    public SurfaceData replaceSurfaceData() {
84        if (getBounds().isEmpty()) {
85            surfaceData = NullSurfaceData.theInstance;
86            return surfaceData;
87        }
88
89        // the layer redirects all painting to the buffer's graphics
90        // and blits the buffer to the layer surface (in drawInCGLContext callback)
91        CGraphicsConfig gc = (CGraphicsConfig)getGraphicsConfiguration();
92        surfaceData = gc.createSurfaceData(this);
93        setScale(gc.getDevice().getScaleFactor());
94        // the layer holds a reference to the buffer, which in
95        // turn has a reference back to this layer
96        if (surfaceData instanceof CGLSurfaceData) {
97            validate((CGLSurfaceData)surfaceData);
98        }
99
100        return surfaceData;
101    }
102
103    public SurfaceData getSurfaceData() {
104        return surfaceData;
105    }
106
107    public void validate(final CGLSurfaceData cglsd) {
108        OGLRenderQueue rq = OGLRenderQueue.getInstance();
109        rq.lock();
110        try {
111            execute(ptr -> validate(ptr, cglsd));
112        } finally {
113            rq.unlock();
114        }
115    }
116
117    @Override
118    public void dispose() {
119        // break the connection between the layer and the buffer
120        validate(null);
121        super.dispose();
122    }
123
124    private void setScale(final int _scale) {
125        if (scale != _scale) {
126            scale = _scale;
127            execute(ptr -> nativeSetScale(ptr, scale));
128        }
129    }
130
131    // ----------------------------------------------------------------------
132    // NATIVE CALLBACKS
133    // ----------------------------------------------------------------------
134
135    private void drawInCGLContext() {
136        // tell the flusher thread not to update the intermediate buffer
137        // until we are done blitting from it
138        OGLRenderQueue rq = OGLRenderQueue.getInstance();
139        rq.lock();
140        try {
141            execute(ptr -> blitTexture(ptr));
142        } finally {
143            rq.unlock();
144        }
145    }
146}
147