f32c2aff97cb787a06727547e20bfb0369724152
[WebKit-https.git] / Source / WebCore / platform / graphics / surfaces / glx / GLXConfigSelector.h
1 /*
2  * Copyright (C) 2012 Intel Corporation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef GLXConfigSelector_h
27 #define GLXConfigSelector_h
28
29 #if USE(ACCELERATED_COMPOSITING) && USE(GLX)
30
31 #include "X11Helper.h"
32 #include <opengl/GLDefs.h>
33 #include <opengl/GLPlatformSurface.h>
34
35 namespace WebCore {
36
37 static int clientAttributes[] = {
38     // The specification is a set key value pairs stored in a simple array.
39     GLX_LEVEL,                          0,
40     static_cast<int>(GLX_VISUAL_ID),    0,
41     GLX_DRAWABLE_TYPE,                  GLX_PIXMAP_BIT,
42     GLX_BIND_TO_TEXTURE_TARGETS_EXT,    GLX_TEXTURE_2D_BIT_EXT,
43     GLX_BIND_TO_TEXTURE_RGBA_EXT,       TRUE,
44     0
45 };
46
47 static int glxSurfaceAttributes[] = {
48     GLX_LEVEL, 0,
49     GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
50     GLX_RENDER_TYPE,   0,
51     GLX_RED_SIZE,      1,
52     GLX_GREEN_SIZE,    1,
53     GLX_BLUE_SIZE,     1,
54     GLX_ALPHA_SIZE,    0,
55     GLX_DOUBLEBUFFER,  GL_FALSE,
56     None
57 };
58
59 class GLXConfigSelector {
60     WTF_MAKE_NONCOPYABLE(GLXConfigSelector);
61
62 public:
63     GLXConfigSelector(GLPlatformSurface::SurfaceAttributes attr = GLPlatformSurface::Default)
64         : m_surfaceContextFBConfig(0)
65         , m_pixmapContextFBConfig(0)
66         , m_attributes(attr)
67     {
68     }
69
70     virtual ~GLXConfigSelector()
71     {
72     }
73
74     XVisualInfo* visualInfo(const GLXFBConfig& config)
75     {
76         return glXGetVisualFromFBConfig(X11Helper::nativeDisplay(), config);
77     }
78
79     GLXFBConfig pixmapContextConfig()
80     {
81         if (!m_pixmapContextFBConfig) {
82             validateAttributes();
83             m_pixmapContextFBConfig = findMatchingConfig(glxSurfaceAttributes, m_attributes & GLPlatformSurface::SupportAlpha ? 32 : 24);
84         }
85
86         return m_pixmapContextFBConfig;
87     }
88
89
90     GLXFBConfig surfaceContextConfig()
91     {
92         if (!m_surfaceContextFBConfig) {
93             glxSurfaceAttributes[3] = GLX_WINDOW_BIT;
94             glxSurfaceAttributes[7] = 8;
95             glxSurfaceAttributes[9] = 8;
96             glxSurfaceAttributes[11] = 8;
97             validateAttributes();
98             m_surfaceContextFBConfig = findMatchingConfig(glxSurfaceAttributes, m_attributes & GLPlatformSurface::SupportAlpha ? 32 : 24);
99         }
100
101         return m_surfaceContextFBConfig;
102     }
103
104     GLXFBConfig surfaceClientConfig(int depth, VisualID id)
105     {
106         clientAttributes[3] = static_cast<int>(id);
107         clientAttributes[8] = depth == 32 ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT;
108         // Prefer to match with Visual Id.
109         GLXFBConfig config = findMatchingConfigWithVisualId(clientAttributes, depth, id);
110
111         if (!config)
112             config = findMatchingConfig(clientAttributes, depth);
113
114         return config;
115     }
116
117     void reset()
118     {
119         m_surfaceContextFBConfig = 0;
120         m_pixmapContextFBConfig = 0;
121     }
122
123     GLPlatformSurface::SurfaceAttributes attributes() const
124     {
125         return m_attributes;
126     }
127
128 private:
129     void validateAttributes()
130     {
131         if (m_attributes & GLPlatformSurface::SupportAlpha) {
132             glxSurfaceAttributes[13] = 8;
133             glxSurfaceAttributes[5] = GLX_RGBA_BIT;
134         }
135
136         if (m_attributes & GLPlatformSurface::DoubleBuffered)
137             glxSurfaceAttributes[15] = GL_TRUE;
138     }
139
140     GLXFBConfig findMatchingConfig(const int attributes[], int depth = 32)
141     {
142         int numAvailableConfigs;
143         OwnPtrX11<GLXFBConfig> temp(glXChooseFBConfig(X11Helper::nativeDisplay(), DefaultScreen(X11Helper::nativeDisplay()), attributes, &numAvailableConfigs));
144
145         if (!numAvailableConfigs || !temp.get())
146             return 0;
147
148         OwnPtrX11<XVisualInfo> scopedVisualInfo;
149         for (int i = 0; i < numAvailableConfigs; ++i) {
150             scopedVisualInfo = glXGetVisualFromFBConfig(X11Helper::nativeDisplay(), temp[i]);
151             if (!scopedVisualInfo.get())
152                 continue;
153
154 #if USE(GRAPHICS_SURFACE)
155             if (X11Helper::isXRenderExtensionSupported()) {
156                 XRenderPictFormat* format = XRenderFindVisualFormat(X11Helper::nativeDisplay(), scopedVisualInfo->visual);
157
158                 if (format) {
159                     if (m_attributes & GLPlatformSurface::SupportAlpha) {
160                         if (scopedVisualInfo->depth == depth && format->direct.alphaMask > 0)
161                             return temp[i];
162                     } else if (!format->direct.alphaMask)
163                         return temp[i];
164                 }
165             }
166 #endif
167             if (scopedVisualInfo->depth == depth)
168                 return temp[i];
169         }
170
171         // Did not find any visual supporting alpha, select the first available config.
172         scopedVisualInfo = glXGetVisualFromFBConfig(X11Helper::nativeDisplay(), temp[0]);
173
174         if ((m_attributes & GLPlatformSurface::SupportAlpha) && (scopedVisualInfo->depth != 32))
175             m_attributes &= ~GLPlatformSurface::SupportAlpha;
176
177         return temp[0];
178     }
179
180     GLXFBConfig findMatchingConfigWithVisualId(const int attributes[], int depth, VisualID id)
181     {
182         int numAvailableConfigs;
183         OwnPtrX11<GLXFBConfig> temp(glXChooseFBConfig(X11Helper::nativeDisplay(), DefaultScreen(X11Helper::nativeDisplay()), attributes, &numAvailableConfigs));
184
185         if (!numAvailableConfigs || !temp.get())
186             return 0;
187
188         OwnPtrX11<XVisualInfo> scopedVisualInfo;
189         for (int i = 0; i < numAvailableConfigs; ++i) {
190             scopedVisualInfo = glXGetVisualFromFBConfig(X11Helper::nativeDisplay(), temp[i]);
191             if (!scopedVisualInfo.get())
192                 continue;
193
194             if (id && scopedVisualInfo->depth == depth && scopedVisualInfo->visualid == id)
195                 return temp[i];
196         }
197
198         return 0;
199     }
200
201     GLXFBConfig m_surfaceContextFBConfig;
202     GLXFBConfig m_pixmapContextFBConfig;
203     GLPlatformSurface::SurfaceAttributes m_attributes : 3;
204 };
205
206 }
207
208 #endif
209
210 #endif