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