Gnash  0.8.10
eglDevice.h
Go to the documentation of this file.
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: