00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eglGraphicsStateGuardian.h"
00016 #include "config_egldisplay.h"
00017 #include "lightReMutexHolder.h"
00018
00019 #include <dlfcn.h>
00020
00021 TypeHandle eglGraphicsStateGuardian::_type_handle;
00022
00023
00024
00025
00026
00027
00028 eglGraphicsStateGuardian::
00029 eglGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
00030 eglGraphicsStateGuardian *share_with) :
00031 #ifdef OPENGLES_2
00032 GLES2GraphicsStateGuardian(engine, pipe)
00033 #else
00034 GLESGraphicsStateGuardian(engine, pipe)
00035 #endif
00036 {
00037 _share_context=0;
00038 _context=0;
00039 _display=0;
00040 _egl_display=0;
00041 _screen=0;
00042 _visual=0;
00043 _visuals=0;
00044 _fbconfig=0;
00045
00046 if (share_with != (eglGraphicsStateGuardian *)NULL) {
00047 _prepared_objects = share_with->get_prepared_objects();
00048 _share_context = share_with->_context;
00049 }
00050 }
00051
00052
00053
00054
00055
00056
00057 eglGraphicsStateGuardian::
00058 ~eglGraphicsStateGuardian() {
00059 if (_visuals != (XVisualInfo *)NULL) {
00060 XFree(_visuals);
00061 }
00062 if (_context != (EGLContext)NULL) {
00063 if (!eglDestroyContext(_egl_display, _context)) {
00064 egldisplay_cat.error() << "Failed to destroy EGL context: "
00065 << get_egl_error_string(eglGetError()) << "\n";
00066 }
00067 _context = (EGLContext)NULL;
00068 }
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 void eglGraphicsStateGuardian::
00078 get_properties(FrameBufferProperties &properties,
00079 bool &pbuffer_supported, bool &pixmap_supported,
00080 bool &slow, EGLConfig config) {
00081
00082 properties.clear();
00083
00084
00085 EGLint red_size, green_size, blue_size,
00086 alpha_size,
00087 depth_size, stencil_size, samples, surface_type, caveat;
00088
00089 eglGetConfigAttrib(_egl_display, config, EGL_RED_SIZE, &red_size);
00090 eglGetConfigAttrib(_egl_display, config, EGL_GREEN_SIZE, &green_size);
00091 eglGetConfigAttrib(_egl_display, config, EGL_BLUE_SIZE, &blue_size);
00092 eglGetConfigAttrib(_egl_display, config, EGL_ALPHA_SIZE, &alpha_size);
00093 eglGetConfigAttrib(_egl_display, config, EGL_DEPTH_SIZE, &depth_size);
00094 eglGetConfigAttrib(_egl_display, config, EGL_STENCIL_SIZE, &stencil_size);
00095 eglGetConfigAttrib(_egl_display, config, EGL_SAMPLES, &samples);
00096 eglGetConfigAttrib(_egl_display, config, EGL_SURFACE_TYPE, &surface_type);
00097 eglGetConfigAttrib(_egl_display, config, EGL_CONFIG_CAVEAT, &caveat);
00098 int err = eglGetError();
00099 if (err != EGL_SUCCESS) {
00100 egldisplay_cat.error() << "Failed to get EGL config attrib: "
00101 << get_egl_error_string(err) << "\n";
00102 }
00103
00104 pbuffer_supported = false;
00105 if ((surface_type & EGL_PBUFFER_BIT)!=0) {
00106 pbuffer_supported = true;
00107 }
00108
00109 pixmap_supported = false;
00110 if ((surface_type & EGL_PIXMAP_BIT)!=0) {
00111 pixmap_supported = true;
00112 }
00113
00114 slow = false;
00115 if (caveat == EGL_SLOW_CONFIG) {
00116 slow = true;
00117 }
00118
00119 if ((surface_type & EGL_WINDOW_BIT)==0) {
00120
00121 return;
00122 }
00123
00124 properties.set_back_buffers(1);
00125 properties.set_rgb_color(1);
00126 properties.set_color_bits(red_size+green_size+blue_size);
00127 properties.set_stencil_bits(stencil_size);
00128 properties.set_depth_bits(depth_size);
00129 properties.set_alpha_bits(alpha_size);
00130 properties.set_multisamples(samples);
00131
00132
00133 properties.set_force_software(1);
00134 properties.set_force_hardware(1);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144 void eglGraphicsStateGuardian::
00145 choose_pixel_format(const FrameBufferProperties &properties,
00146 X11_Display *display,
00147 int screen, bool need_pbuffer, bool need_pixmap) {
00148
00149 _display = display;
00150 _egl_display = eglGetDisplay((NativeDisplayType) display);
00151 _screen = screen;
00152 _context = 0;
00153 _fbconfig = 0;
00154 _visual = 0;
00155 _visuals = 0;
00156 _fbprops.clear();
00157
00158 int attrib_list[] = {
00159 #ifdef OPENGLES_1
00160 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
00161 #endif
00162 #ifdef OPENGLES_2
00163 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
00164 #endif
00165 EGL_SURFACE_TYPE, EGL_DONT_CARE,
00166 EGL_NONE
00167 };
00168
00169
00170 int num_configs = 0, returned_configs;
00171 if (!eglChooseConfig(_egl_display, attrib_list, NULL, num_configs, &returned_configs) || returned_configs <= 0) {
00172 egldisplay_cat.error() << "eglChooseConfig failed: "
00173 << get_egl_error_string(eglGetError()) << "\n";
00174 return;
00175 }
00176
00177 num_configs = returned_configs;
00178 EGLConfig *configs = new EGLConfig[num_configs];
00179
00180 if (!eglChooseConfig(_egl_display, attrib_list, configs, num_configs, &returned_configs) || returned_configs <= 0) {
00181 egldisplay_cat.error() << "eglChooseConfig failed: "
00182 << get_egl_error_string(eglGetError()) << "\n";
00183 delete[] configs;
00184 return;
00185 }
00186
00187 int best_quality = 0;
00188 int best_result = 0;
00189 FrameBufferProperties best_props;
00190
00191 for (int i = 0; i < num_configs; ++i) {
00192 FrameBufferProperties fbprops;
00193 bool pbuffer_supported, pixmap_supported, slow;
00194 get_properties(fbprops, pbuffer_supported, pixmap_supported,
00195 slow, configs[i]);
00196
00197
00198 const char *pbuffertext = pbuffer_supported ? " (pbuffer)" : "";
00199 const char *pixmaptext = pixmap_supported ? " (pixmap)" : "";
00200 const char *slowtext = slow ? " (slow)" : "";
00201 egldisplay_cat.debug()
00202 << i << ": " << fbprops << pbuffertext << pixmaptext << slowtext << "\n";
00203 int quality = fbprops.get_quality(properties);
00204 if ((quality > 0)&&(slow)) quality -= 10000000;
00205
00206 if (need_pbuffer && !pbuffer_supported) {
00207 continue;
00208 }
00209 if (need_pixmap && !pixmap_supported) {
00210 continue;
00211 }
00212
00213 if (quality > best_quality) {
00214 best_quality = quality;
00215 best_result = i;
00216 best_props = fbprops;
00217 }
00218 }
00219 int depth = DefaultDepth(_display, _screen);
00220 _visual = new XVisualInfo;
00221 XMatchVisualInfo(_display, _screen, depth, TrueColor, _visual);
00222
00223 if (best_quality > 0) {
00224 egldisplay_cat.debug()
00225 << "Chosen config " << best_result << ": " << best_props << "\n";
00226 _fbconfig = configs[best_result];
00227 #ifdef OPENGLES_2
00228 EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
00229 _context = eglCreateContext(_egl_display, _fbconfig, _share_context, context_attribs);
00230 #else
00231 _context = eglCreateContext(_egl_display, _fbconfig, _share_context, NULL);
00232 #endif
00233 int err = eglGetError();
00234 if (_context && err == EGL_SUCCESS) {
00235 if (_visual) {
00236 _fbprops = best_props;
00237 delete[] configs;
00238 return;
00239 }
00240 }
00241
00242 egldisplay_cat.error()
00243 << "Could not create EGL context!\n"
00244 << get_egl_error_string(err) << "\n";
00245 _fbconfig = 0;
00246 _context = 0;
00247 _visual = 0;
00248 _visuals = 0;
00249 }
00250
00251 egldisplay_cat.error() <<
00252 "Could not find a usable pixel format.\n";
00253
00254 delete[] configs;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 void eglGraphicsStateGuardian::
00264 reset() {
00265 #ifdef OPENGLES_2
00266 GLES2GraphicsStateGuardian::reset();
00267 #else
00268 GLESGraphicsStateGuardian::reset();
00269 #endif
00270
00271
00272
00273
00274 if (_gl_renderer.find("Mesa") != string::npos &&
00275 _gl_renderer.find("Mesa DRI") == string::npos) {
00276
00277 _fbprops.set_force_software(1);
00278 _fbprops.set_force_hardware(0);
00279 } else {
00280 _fbprops.set_force_hardware(1);
00281 _fbprops.set_force_software(0);
00282 }
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 bool eglGraphicsStateGuardian::
00292 egl_is_at_least_version(int major_version, int minor_version) const {
00293 if (_egl_version_major < major_version) {
00294 return false;
00295 }
00296 if (_egl_version_minor < minor_version) {
00297 return false;
00298 }
00299 return true;
00300 }
00301
00302
00303
00304
00305
00306
00307 void eglGraphicsStateGuardian::
00308 gl_flush() const {
00309
00310 LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
00311 #ifdef OPENGLES_2
00312 GLES2GraphicsStateGuardian::gl_flush();
00313 #else
00314 GLESGraphicsStateGuardian::gl_flush();
00315 #endif
00316 }
00317
00318
00319
00320
00321
00322
00323 GLenum eglGraphicsStateGuardian::
00324 gl_get_error() const {
00325
00326 LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
00327 #ifdef OPENGLES_2
00328 return GLES2GraphicsStateGuardian::gl_get_error();
00329 #else
00330 return GLESGraphicsStateGuardian::gl_get_error();
00331 #endif
00332 }
00333
00334
00335
00336
00337
00338
00339 void eglGraphicsStateGuardian::
00340 query_gl_version() {
00341 #ifdef OPENGLES_2
00342 GLES2GraphicsStateGuardian::query_gl_version();
00343 #else
00344 GLESGraphicsStateGuardian::query_gl_version();
00345 #endif
00346
00347
00348
00349 if (!eglInitialize(_egl_display, &_egl_version_major, &_egl_version_minor)) {
00350 egldisplay_cat.error() << "Failed to get EGL version number: "
00351 << get_egl_error_string(eglGetError()) << "\n";
00352 }
00353
00354
00355
00356
00357 #ifdef OPENGLES_2
00358 if (gles2gsg_cat.is_debug()) {
00359 gles2gsg_cat.debug()
00360 #else
00361 if (glesgsg_cat.is_debug()) {
00362 glesgsg_cat.debug()
00363 #endif
00364 << "EGL_VERSION = " << _egl_version_major << "." << _egl_version_minor
00365 << "\n";
00366 }
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 void eglGraphicsStateGuardian::
00378 get_extra_extensions() {
00379 save_extensions(eglQueryString(_egl_display, EGL_EXTENSIONS));
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 void *eglGraphicsStateGuardian::
00393 do_get_extension_func(const char *prefix, const char *name) {
00394 string fullname = string(prefix) + string(name);
00395
00396 return (void *)eglGetProcAddress(fullname.c_str());
00397 }