Gnash
0.8.10
|
00001 // 00002 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 00003 // Free Software Foundation, Inc 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 // 00019 00020 #ifndef __EGL_DEVICE_H__ 00021 #define __EGL_DEVICE_H__ 1 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include "gnashconfig.h" 00025 #endif 00026 00027 #include <boost/scoped_array.hpp> 00028 #include <boost/scoped_ptr.hpp> 00029 00030 #ifdef HAVE_X11_X_H 00031 #include "x11/X11Device.h" 00032 #endif 00033 #include "GnashDevice.h" 00034 00035 #ifdef HAVE_EGL_EGL_H 00036 # include <EGL/egl.h> 00037 #else 00038 # error "This file needs EGL, which is part of OpenGL-ES" 00039 #endif 00040 00041 #include "Point2d.h" 00042 00043 namespace gnash { 00044 00045 namespace renderer { 00046 00047 struct eglVertex { 00048 eglVertex(float x, float y) 00049 : _x(x), _y(y) { } 00050 00051 eglVertex(const point& p) 00052 : _x(p.x), _y(p.y) { } 00053 float _x; 00054 float _y; 00055 }; 00056 00057 class EGLDevice : public GnashDevice 00058 { 00059 public: 00060 typedef enum {LOW, MEDIUM, HIGH} quality_e; 00061 EGLDevice(); 00062 EGLDevice(int argc, char *argv[]); 00063 EGLDevice(GnashDevice::rtype_t rtype); 00064 00065 virtual ~EGLDevice(); 00066 00067 dtype_t getType() { return EGL; }; 00068 00069 // Initialize EGL Device layer 00070 bool initDevice(int argc, char *argv[]); 00071 00072 // Initialize EGL Window layer 00073 bool attachWindow(GnashDevice::native_window_t window); 00074 00075 // Utility methods not in the base class 00077 const char *getErrorString(int error); 00078 00079 size_t getStride() { 00080 return getDepth() * getWidth(); 00081 }; 00082 00083 // Accessors for the settings needed by higher level code. 00084 // Surface accessors 00085 size_t getWidth() { 00086 return getWidth(_eglSurface); 00087 }; 00088 00089 size_t getHeight() { 00090 return getHeight(_eglSurface); 00091 } 00092 00093 EGLint getDepth() { 00094 EGLint value; 00095 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_DEPTH_SIZE, &value); 00096 return value; 00097 } 00098 00099 int getRedSize() { 00100 EGLint value; 00101 if (_eglConfig && _eglDisplay) { 00102 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_RED_SIZE, &value); 00103 } 00104 return static_cast<int>(value); 00105 }; 00106 int getGreenSize() { 00107 EGLint value; 00108 if (_eglConfig && _eglDisplay) { 00109 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_GREEN_SIZE, &value); 00110 } 00111 return static_cast<int>(value); 00112 }; 00113 int getBlueSize() { 00114 EGLint value; 00115 if (_eglConfig && _eglDisplay) { 00116 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_BLUE_SIZE, &value); 00117 } 00118 return static_cast<int>(value); 00119 }; 00120 00121 bool isSingleBuffered() { 00122 EGLint value; 00123 if (_eglSurface && _eglDisplay) { 00124 eglQuerySurface(_eglDisplay, _eglSurface, EGL_RENDER_BUFFER, &value); 00125 } 00126 if (value == EGL_SINGLE_BUFFER) { 00127 return true; 00128 } 00129 return false; 00130 } 00131 bool isBufferDestroyed() { 00132 return isBufferDestroyed(_eglSurface); 00133 } 00134 00135 int getID() { 00136 return static_cast<int>(getSurfaceID()); 00137 } 00138 00139 bool supportsRenderer(GnashDevice::rtype_t rtype); 00140 00141 bool isNativeRender() { 00142 EGLint value; 00143 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_NATIVE_RENDERABLE, &value); 00144 return value; 00145 } 00146 00147 // Overload some of the base class methods to deal with Device specific 00148 // data types. 00149 bool bindClient(GnashDevice::rtype_t rtype); 00150 00151 size_t getWidth(EGLSurface surface) { 00152 EGLint value; 00153 if (surface && _eglDisplay) { 00154 eglQuerySurface(_eglDisplay, surface, EGL_WIDTH, &value); 00155 } 00156 return static_cast<size_t>(value); 00157 }; 00158 size_t getHeight(EGLSurface surface) { 00159 EGLint value; 00160 if (surface && _eglDisplay) { 00161 eglQuerySurface(_eglDisplay, surface, EGL_HEIGHT, &value); 00162 } 00163 return static_cast<size_t>(value); 00164 } 00165 bool isBufferDestroyed(EGLSurface surface) { 00166 EGLint value; 00167 eglQuerySurface(_eglDisplay, surface, EGL_SWAP_BEHAVIOR, &value); 00168 if (value == EGL_BUFFER_DESTROYED) { 00169 return true; 00170 } 00171 return false; 00172 } 00173 #ifdef BUILD_X11_DEVICE 00174 EGLint getNativeVisual(); 00175 #endif 00176 00178 bool checkEGLConfig(EGLConfig config); 00179 00181 int queryEGLConfig() { return queryEGLConfig(_eglDisplay); }; 00182 int queryEGLConfig(EGLDisplay display); 00183 00184 // Debugging utilities 00185 void printEGLConfig() { return printEGLConfig(_eglConfig); }; 00186 void printEGLConfig(EGLConfig config); 00187 void printEGLContext() { return printEGLContext(_eglContext); }; 00188 void printEGLContext(EGLContext context); 00189 void printEGLSurface() { return printEGLSurface(_eglSurface); }; 00190 void printEGLSurface(EGLSurface surface); 00191 void printEGLAttribs(const EGLint *attrib); 00192 00193 // Create Pbuffers for offscreen rendering 00194 EGLSurface createPbuffer(int width, int height); 00195 EGLSurface createPbuffer(int width, int height, EGLClientBuffer buf, EGLenum type); 00196 EGLSurface createPixmap(int width, int height, NativePixmapType buf); 00197 size_t totalPbuffers() { return _pbuffers.size(); }; 00198 EGLSurface &operator[](int index) { if (!_pbuffers.empty()) { return _pbuffers[index]; }; }; 00199 00200 // Swapping Buffers makes the specified surface active on the display if 00201 // EGL_RENDER_BUFFER is set to EGL_BACK_BUFFER. If it's set to 00202 // EGL_SINGLE_BUFFER then this has no effect, as the display was drawn to 00203 // directly. 00204 // Swap to the default surface 00205 bool swapBuffers() { 00206 // GNASH_REPORT_FUNCTION; 00207 if (!isSingleBuffered()) { 00208 return eglSwapBuffers(_eglDisplay, _eglSurface); 00209 } 00210 return true; 00211 } 00212 bool copyPbuffers(size_t x) { 00213 GNASH_REPORT_FUNCTION; 00214 if (x < _pbuffers.size()) { 00215 NativePixmapType pix; 00216 if (!eglCopyBuffers(_eglDisplay, _pbuffers[x], pix)) { 00217 log_error( "eglCopyBuffers() failed (error 0x%x)", eglGetError()); 00218 return false; 00219 } 00220 return true; 00221 } 00222 return false; 00223 } 00224 // Make one of the pbuffers the current one to draw into 00225 bool makePbufferCurrent() { 00226 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglSurface != EGL_NO_SURFACE)) { 00227 if (!eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext)) { 00228 log_error( "eglMakeCurrent() failed (error 0x%x)", eglGetError()); 00229 return false; 00230 } 00231 } 00232 return false; 00233 } 00234 00235 bool makePbufferCurrent(size_t x) { 00236 if (x < _pbuffers.size()) { 00237 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglContext != EGL_NO_CONTEXT)) { 00238 if (!eglMakeCurrent(_eglDisplay, _pbuffers[x], _pbuffers[x], _eglContext)) { 00239 log_error( "eglMakeCurrent() failed (error 0x%x)", eglGetError()); 00240 return false; 00241 } 00242 return true; 00243 } 00244 } 00245 return false; 00246 } 00247 00248 size_t getVerticalRes() { 00249 EGLint value = 0; 00250 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglSurface != EGL_NO_SURFACE)) { 00251 eglQuerySurface(_eglDisplay, _eglSurface, EGL_VERTICAL_RESOLUTION, &value); 00252 } 00253 return static_cast<size_t>(value); 00254 } 00255 size_t getHorzRes() { 00256 EGLint value = 0; 00257 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglSurface != EGL_NO_SURFACE)) { 00258 eglQuerySurface(_eglDisplay, _eglSurface, EGL_HORIZONTAL_RESOLUTION, &value); 00259 } 00260 return static_cast<size_t>(value); 00261 } 00262 bool isBackBuffered() { 00263 EGLint value; 00264 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglSurface != EGL_NO_SURFACE)) { 00265 eglQuerySurface(_eglDisplay, _eglSurface, EGL_RENDER_BUFFER, &value); 00266 if (value == EGL_BACK_BUFFER) { 00267 return true; 00268 } 00269 return false; 00270 } 00271 return false; 00272 } 00273 00274 bool isMultiSample() { 00275 EGLint value; 00276 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglSurface != EGL_NO_SURFACE)) { 00277 eglQuerySurface(_eglDisplay, _eglSurface, EGL_MULTISAMPLE_RESOLVE, &value); 00278 if (value == EGL_MULTISAMPLE_RESOLVE_BOX) { 00279 return true; 00280 } 00281 return false; 00282 } 00283 return false; 00284 } 00285 00286 EGLint getSurfaceID() { 00287 EGLint value = -1; 00288 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglSurface != EGL_NO_SURFACE)) { 00289 eglQuerySurface(_eglDisplay, _eglSurface, EGL_CONFIG_ID, &value); 00290 } 00291 return value; 00292 } 00293 00294 // Context accessors 00295 EGLint getContextID() { 00296 EGLint value = -1; 00297 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglContext != EGL_NO_CONTEXT)) { 00298 eglQueryContext(_eglDisplay, _eglContext, EGL_CONFIG_ID, &value); 00299 } 00300 return value; 00301 } 00302 bool isContextSingleBuffered() { 00303 EGLint value; 00304 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglContext != EGL_NO_CONTEXT)) { 00305 eglQueryContext(_eglDisplay, _eglContext, EGL_RENDER_BUFFER, &value); 00306 if (value == EGL_SINGLE_BUFFER) { 00307 return true; 00308 } 00309 return false; 00310 } 00311 return false; 00312 } 00313 bool isContextBackBuffered() { 00314 EGLint value; 00315 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglContext != EGL_NO_CONTEXT)) { 00316 eglQueryContext(_eglDisplay, _eglContext, EGL_RENDER_BUFFER, &value); 00317 if (value == EGL_BACK_BUFFER) { 00318 return true; 00319 } 00320 return false; 00321 } 00322 return false; 00323 } 00324 00325 // Config accessors 00326 EGLint getSamples() { 00327 EGLint value = -1; 00328 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglConfig != 0)) { 00329 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_SAMPLES, &value); 00330 } 00331 return value; 00332 } 00333 EGLint getSampleBuffers() { 00334 EGLint value = -1; 00335 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglConfig != 0)) { 00336 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_SAMPLE_BUFFERS, &value); 00337 } 00338 return value; 00339 } 00340 EGLint getMaxSwapInterval() { 00341 EGLint value = -1; 00342 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglConfig != 0)) { 00343 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_MAX_SWAP_INTERVAL, &value); 00344 } 00345 return value; 00346 } 00347 EGLint getMinSwapInterval() { 00348 EGLint value = -1; 00349 if ((_eglDisplay != EGL_NO_DISPLAY) && (_eglConfig != 0)) { 00350 eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_MIN_SWAP_INTERVAL, &value); 00351 } 00352 return value; 00353 } 00354 00355 void setAttrib(int bpp); 00356 static EGLint getRenderableTypes(); 00357 protected: 00358 EGLConfig _eglConfig; 00359 EGLContext _eglContext; 00360 EGLSurface _eglSurface; 00361 EGLDisplay _eglDisplay; 00362 EGLNativeWindowType _nativeWindow; 00363 EGLNativePixmapType _nativePixmap; 00364 quality_e _quality; 00365 const EGLint *_attrib; 00366 unsigned int _bpp; 00367 std::vector<EGLSurface> _pbuffers; 00368 }; 00369 00370 #define DUMP_CURRENT_SURFACE printEGLSurface(eglGetCurrentSurface(EGL_DRAW)) 00371 #define DUMP_CURRENT_CONTEXT printEGLContext(eglGetCurrentContext()) 00372 00373 } // namespace renderer 00374 } // namespace gnash 00375 00376 #endif // end of __EGL_DEVICE_H__ 00377 00378 // local Variables: 00379 // mode: C++ 00380 // indent-tabs-mode: nil 00381 // End: