1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // PixmapSurfaceGLX.cpp: GLX implementation of egl::Surface for Pixmaps
8
9 #include "common/debug.h"
10 #include "libANGLE/Display.h"
11 #include "libANGLE/Surface.h"
12
13 #include "libANGLE/renderer/gl/glx/DisplayGLX.h"
14
15 #include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
16 #include "libANGLE/renderer/gl/glx/PixmapSurfaceGLX.h"
17 #include "libANGLE/renderer/gl/glx/glx_utils.h"
18
19 #include <iostream>
20
21 namespace rx
22 {
23
24 namespace
25 {
26
EGLTextureFormatToGLXTextureFormat(EGLint textureFormat)27 int EGLTextureFormatToGLXTextureFormat(EGLint textureFormat)
28 {
29 switch (textureFormat)
30 {
31 case EGL_NO_TEXTURE:
32 return GLX_TEXTURE_FORMAT_NONE_EXT;
33 case EGL_TEXTURE_RGB:
34 return GLX_TEXTURE_FORMAT_RGB_EXT;
35 case EGL_TEXTURE_RGBA:
36 return GLX_TEXTURE_FORMAT_RGBA_EXT;
37 default:
38 UNREACHABLE();
39 return GLX_TEXTURE_FORMAT_NONE_EXT;
40 }
41 }
42
EGLTextureTargetToGLXTextureTarget(EGLint textureTarget)43 int EGLTextureTargetToGLXTextureTarget(EGLint textureTarget)
44 {
45 switch (textureTarget)
46 {
47 case EGL_NO_TEXTURE:
48 return 0;
49 case EGL_TEXTURE_2D:
50 return GLX_TEXTURE_2D_EXT;
51 default:
52 UNREACHABLE();
53 return 0;
54 }
55 }
56
EGLBufferToGLXBuffer(EGLint buffer)57 int EGLBufferToGLXBuffer(EGLint buffer)
58 {
59 switch (buffer)
60 {
61 case EGL_BACK_BUFFER:
62 return GLX_BACK_EXT;
63 default:
64 UNREACHABLE();
65 return 0;
66 }
67 }
68
69 } // namespace
70
PixmapSurfaceGLX(const egl::SurfaceState & state,Pixmap pixmap,Display * display,const FunctionsGLX & glx,glx::FBConfig fbConfig)71 PixmapSurfaceGLX::PixmapSurfaceGLX(const egl::SurfaceState &state,
72 Pixmap pixmap,
73 Display *display,
74 const FunctionsGLX &glx,
75 glx::FBConfig fbConfig)
76 : SurfaceGLX(state),
77 mWidth(0),
78 mHeight(0),
79 mGLX(glx),
80 mFBConfig(fbConfig),
81 mXPixmap(pixmap),
82 mGLXPixmap(0),
83 mDisplay(display)
84 {}
85
~PixmapSurfaceGLX()86 PixmapSurfaceGLX::~PixmapSurfaceGLX()
87 {
88 if (mGLXPixmap)
89 {
90 mGLX.destroyPixmap(mGLXPixmap);
91 }
92 }
93
initialize(const egl::Display * display)94 egl::Error PixmapSurfaceGLX::initialize(const egl::Display *display)
95 {
96 DisplayGLX *displayGLX = GetImplAs<DisplayGLX>(display);
97
98 {
99 Window rootWindow;
100 int x = 0;
101 int y = 0;
102 unsigned int borderWidth = 0;
103 unsigned int depth = 0;
104 int status = XGetGeometry(mDisplay, mXPixmap, &rootWindow, &x, &y, &mWidth, &mHeight,
105 &borderWidth, &depth);
106 if (!status)
107 {
108 return egl::EglBadSurface() << "XGetGeometry query failed on pixmap surface: "
109 << x11::XErrorToString(mDisplay, status);
110 }
111 }
112
113 std::vector<int> pixmapAttribs;
114 if (mState.attributes.contains(EGL_TEXTURE_FORMAT))
115 {
116 pixmapAttribs.push_back(GLX_TEXTURE_FORMAT_EXT);
117 pixmapAttribs.push_back(
118 EGLTextureFormatToGLXTextureFormat(mState.attributes.getAsInt(EGL_TEXTURE_FORMAT)));
119 }
120 if (mState.attributes.contains(EGL_TEXTURE_TARGET))
121 {
122 pixmapAttribs.push_back(GLX_TEXTURE_TARGET_EXT);
123 pixmapAttribs.push_back(
124 EGLTextureTargetToGLXTextureTarget(mState.attributes.getAsInt(EGL_TEXTURE_TARGET)));
125 }
126
127 pixmapAttribs.push_back(None);
128
129 mGLXPixmap = mGLX.createPixmap(mFBConfig, mXPixmap, pixmapAttribs.data());
130 if (!mGLXPixmap)
131 {
132 return egl::EglBadAlloc() << "Failed to create a native GLX pixmap.";
133 }
134
135 XFlush(mDisplay);
136 displayGLX->syncXCommands(false);
137
138 return egl::NoError();
139 }
140
makeCurrent(const gl::Context * context)141 egl::Error PixmapSurfaceGLX::makeCurrent(const gl::Context *context)
142 {
143 return egl::NoError();
144 }
145
swap(const gl::Context * context)146 egl::Error PixmapSurfaceGLX::swap(const gl::Context *context)
147 {
148 UNREACHABLE();
149 return egl::NoError();
150 }
151
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)152 egl::Error PixmapSurfaceGLX::postSubBuffer(const gl::Context *context,
153 EGLint x,
154 EGLint y,
155 EGLint width,
156 EGLint height)
157 {
158 UNREACHABLE();
159 return egl::NoError();
160 }
161
querySurfacePointerANGLE(EGLint attribute,void ** value)162 egl::Error PixmapSurfaceGLX::querySurfacePointerANGLE(EGLint attribute, void **value)
163 {
164 UNREACHABLE();
165 return egl::NoError();
166 }
167
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)168 egl::Error PixmapSurfaceGLX::bindTexImage(const gl::Context *context,
169 gl::Texture *texture,
170 EGLint buffer)
171 {
172 const int attribs[] = {None};
173 mGLX.bindTexImageEXT(mGLXPixmap, EGLBufferToGLXBuffer(buffer), attribs);
174 return egl::NoError();
175 }
176
releaseTexImage(const gl::Context * context,EGLint buffer)177 egl::Error PixmapSurfaceGLX::releaseTexImage(const gl::Context *context, EGLint buffer)
178 {
179 mGLX.releaseTexImageEXT(mGLXPixmap, EGLBufferToGLXBuffer(buffer));
180 return egl::NoError();
181 }
182
setSwapInterval(const egl::Display * display,EGLint interval)183 void PixmapSurfaceGLX::setSwapInterval(const egl::Display *display, EGLint interval) {}
184
getWidth() const185 EGLint PixmapSurfaceGLX::getWidth() const
186 {
187 return mWidth;
188 }
189
getHeight() const190 EGLint PixmapSurfaceGLX::getHeight() const
191 {
192 return mHeight;
193 }
194
isPostSubBufferSupported() const195 EGLint PixmapSurfaceGLX::isPostSubBufferSupported() const
196 {
197 UNREACHABLE();
198 return EGL_FALSE;
199 }
200
getSwapBehavior() const201 EGLint PixmapSurfaceGLX::getSwapBehavior() const
202 {
203 return EGL_BUFFER_DESTROYED;
204 }
205
checkForResize()206 egl::Error PixmapSurfaceGLX::checkForResize()
207 {
208 // The size of pbuffers never change
209 return egl::NoError();
210 }
211
getDrawable() const212 glx::Drawable PixmapSurfaceGLX::getDrawable() const
213 {
214 return mGLXPixmap;
215 }
216
217 } // namespace rx
218