/**************************************************************************** Copyright (c) 2010 cocos2d-x.org http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "CCEGLView_qnx.h" #include "GLES/gl.h" #include #include #include #include #include #include #include #include #include #include "CCSet.h" #include "CCDirector.h" #include "CCApplication.h" #include "ccMacros.h" #include "CCTouch.h" #include "CCTouchDispatcher.h" #include "CCKeypadDispatcher.h" #include "CCIMEDispatcher.h" using namespace std; namespace cocos2d { bool CCEGLView::m_initializedFunctions = false; const GLubyte *CCEGLView::m_extensions = 0; PFNGLGENERATEMIPMAPOESPROC CCEGLView::glGenerateMipmapOES = 0; PFNGLGENFRAMEBUFFERSOESPROC CCEGLView::glGenFramebuffersOES = 0; PFNGLBINDFRAMEBUFFEROESPROC CCEGLView::glBindFramebufferOES = 0; PFNGLFRAMEBUFFERTEXTURE2DOESPROC CCEGLView::glFramebufferTexture2DOES = 0; PFNGLDELETEFRAMEBUFFERSOESPROC CCEGLView::glDeleteFramebuffersOES = 0; PFNGLCHECKFRAMEBUFFERSTATUSOESPROC CCEGLView::glCheckFramebufferStatusOES = 0; enum Orientation { PORTRAIT, LANDSCAPE, AUTO }; static Orientation orientation = LANDSCAPE; static struct { EGLint surface_type; EGLint red_size; EGLint green_size; EGLint blue_size; EGLint alpha_size; EGLint samples; EGLint config_id; } the_configAttr; #define MAX_TOUCHES 4 static CCTouch *s_pTouches[MAX_TOUCHES] = { NULL }; static CCEGLView* s_pInstance = NULL; CCEGLView::CCEGLView() : m_pDelegate(NULL), m_pEventHandler(NULL), m_fScreenScaleFactor(1.0), m_bNotHVGA(false), m_isWindowActive(false) { s_pInstance = this; m_eglDisplay = EGL_NO_DISPLAY; m_eglContext = EGL_NO_CONTEXT; m_eglSurface = EGL_NO_SURFACE; m_screenEvent = 0; m_screenWindow = 0; strcpy(m_window_group_id, ""); snprintf(m_window_group_id, sizeof(m_window_group_id), "%d", getpid()); bps_initialize(); navigator_request_events(0); navigator_rotation_lock(true); the_configAttr.surface_type = EGL_WINDOW_BIT; the_configAttr.red_size = EGL_DONT_CARE; the_configAttr.green_size = EGL_DONT_CARE; the_configAttr.blue_size = EGL_DONT_CARE; the_configAttr.alpha_size = EGL_DONT_CARE; the_configAttr.samples = EGL_DONT_CARE; the_configAttr.config_id = EGL_DONT_CARE; m_isGLInitialized = initGL(); if (m_isGLInitialized) initEGLFunctions(); } CCEGLView::~CCEGLView() { release(); CC_SAFE_DELETE(m_pDelegate); } void CCEGLView::initEGLFunctions() { m_extensions = glGetString(GL_EXTENSIONS); glGenerateMipmapOES = 0; glGenFramebuffersOES = 0; glBindFramebufferOES = 0; glFramebufferTexture2DOES = 0; glDeleteFramebuffersOES = 0; glCheckFramebufferStatusOES = 0; if (isGLExtension("GL_OES_framebuffer_object")) { glGenerateMipmapOES = (PFNGLGENERATEMIPMAPOESPROC)eglGetProcAddress("glGenerateMipmapOES"); glGenFramebuffersOES = (PFNGLGENFRAMEBUFFERSOESPROC)eglGetProcAddress("glGenFramebuffersOES"); glBindFramebufferOES = (PFNGLBINDFRAMEBUFFEROESPROC)eglGetProcAddress("glBindFramebufferOES"); glFramebufferTexture2DOES = (PFNGLFRAMEBUFFERTEXTURE2DOESPROC)eglGetProcAddress("glFramebufferTexture2DOES"); glDeleteFramebuffersOES = (PFNGLDELETEFRAMEBUFFERSOESPROC)eglGetProcAddress("glDeleteFramebuffersOES"); glCheckFramebufferStatusOES = (PFNGLCHECKFRAMEBUFFERSTATUSOESPROC)eglGetProcAddress("glCheckFramebufferStatusOES"); } m_initializedFunctions = true; } void CCEGLView::setFrameWidthAndHeight(int width, int height) { m_sSizeInPixel.width = width; m_sSizeInPixel.height = height; } bool CCEGLView::Create(int width, int height) { if (width == 0 || height == 0) { return false; } m_sSizeInPoint.width = width; m_sSizeInPoint.height = height; // calculate the factor and the rect of viewport m_fScreenScaleFactor = MIN((float)m_sSizeInPixel.width / m_sSizeInPoint.width, (float)m_sSizeInPixel.height / m_sSizeInPoint.height); int viewPortW = (int)(m_sSizeInPoint.width * m_fScreenScaleFactor); int viewPortH = (int)(m_sSizeInPoint.height * m_fScreenScaleFactor); m_rcViewPort.origin.x = (m_sSizeInPixel.width - viewPortW) / 2; m_rcViewPort.origin.y = (m_sSizeInPixel.height - viewPortH) / 2; m_rcViewPort.size.width = viewPortW; m_rcViewPort.size.height = viewPortH; m_bNotHVGA = true; return true; } EGLConfig CCEGLView::chooseConfig(const EGLDisplay &eglDisplay, const char* str) { EGLConfig config = (EGLConfig)0; EGLConfig *configurations; EGLint egl_num_configs; EGLint val; EGLBoolean rc; const char *tok; EGLint i; if (str != NULL) { tok = str; while (*tok == ' ' || *tok == ',') tok++; while (*tok != '\0') { if (strncmp(tok, "rgba8888", strlen("rgba8888")) == 0) { the_configAttr.red_size = 8; the_configAttr.green_size = 8; the_configAttr.blue_size = 8; the_configAttr.alpha_size = 8; tok += strlen("rgba8888"); } else if (strncmp(tok, "rgba5551", strlen("rgba5551")) == 0) { the_configAttr.red_size = 5; the_configAttr.green_size = 5; the_configAttr.blue_size = 5; the_configAttr.alpha_size = 1; tok += strlen("rgba5551"); } else if (strncmp(tok, "rgba4444", strlen("rgba4444")) == 0) { the_configAttr.red_size = 4; the_configAttr.green_size = 4; the_configAttr.blue_size = 4; the_configAttr.alpha_size = 4; tok += strlen("rgba4444"); } else if (strncmp(tok, "rgb565", strlen("rgb565")) == 0) { the_configAttr.red_size = 5; the_configAttr.green_size = 6; the_configAttr.blue_size = 5; the_configAttr.alpha_size = 0; tok += strlen("rgb565"); } else if (isdigit(*tok)) { val = atoi(tok); while (isdigit(*(++tok))); if (*tok == 'x') { the_configAttr.samples = val; tok++; } else { the_configAttr.config_id = val; } } else { fprintf(stderr, "invalid configuration specifier: "); while (*tok != ' ' && *tok != ',' && *tok != '\0') fputc(*tok++, stderr); fputc('\n', stderr); } while (*tok == ' ' || *tok == ',') tok++; } } rc = eglGetConfigs(eglDisplay, NULL, 0, &egl_num_configs); if (rc != EGL_TRUE) { fprintf(stderr, "eglGetConfigs"); return config; } if (egl_num_configs == 0) { fprintf(stderr, "eglGetConfigs: could not find a configuration\n"); return config; } configurations = (EGLConfig *)malloc(egl_num_configs * sizeof(*configurations)); if (configurations == NULL) { fprintf(stderr, "could not allocate memory for %d EGL configs\n", egl_num_configs); return config; } rc = eglGetConfigs(eglDisplay, configurations, egl_num_configs, &egl_num_configs); if (rc != EGL_TRUE) { fprintf(stderr, "eglGetConfigs"); free(configurations); return config; } for (i = 0; i < egl_num_configs; i++) { if (the_configAttr.config_id != EGL_DONT_CARE) { eglGetConfigAttrib(eglDisplay, configurations[i], EGL_CONFIG_ID, &val); if (val == the_configAttr.config_id) { config = configurations[i]; break; } else { continue; } } eglGetConfigAttrib(eglDisplay, configurations[i], EGL_SURFACE_TYPE, &val); if ((val & the_configAttr.surface_type) != the_configAttr.surface_type) continue; eglGetConfigAttrib(eglDisplay, configurations[i], EGL_RENDERABLE_TYPE, &val); if (!(val & EGL_OPENGL_ES_BIT)) continue; eglGetConfigAttrib(eglDisplay, configurations[i], EGL_DEPTH_SIZE, &val); if (val == 0) continue; if (the_configAttr.red_size != EGL_DONT_CARE) { eglGetConfigAttrib(eglDisplay, configurations[i], EGL_RED_SIZE, &val); if (val != the_configAttr.red_size) continue; } if (the_configAttr.green_size != EGL_DONT_CARE) { eglGetConfigAttrib(eglDisplay, configurations[i], EGL_GREEN_SIZE, &val); if (val != the_configAttr.green_size) continue; } if (the_configAttr.blue_size != EGL_DONT_CARE) { eglGetConfigAttrib(eglDisplay, configurations[i], EGL_BLUE_SIZE, &val); if (val != the_configAttr.blue_size) continue; } if (the_configAttr.alpha_size != EGL_DONT_CARE) { eglGetConfigAttrib(eglDisplay, configurations[i], EGL_ALPHA_SIZE, &val); if (val != the_configAttr.alpha_size) continue; } if (the_configAttr.samples != EGL_DONT_CARE) { eglGetConfigAttrib(eglDisplay, configurations[i], EGL_SAMPLES, &val); if (val != the_configAttr.samples) continue; } config = configurations[i]; break; } free(configurations); if (config == (EGLConfig)0) { fprintf(stderr, "eglChooseConfig: could not find a matching configuration\n"); } return config; } int CCEGLView::chooseFormat(const EGLDisplay &eglDisplay, const EGLConfig &config) { EGLint buffer_bit_depth, alpha_bit_depth; eglGetConfigAttrib(eglDisplay, config, EGL_BUFFER_SIZE, &buffer_bit_depth); eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &alpha_bit_depth); switch (buffer_bit_depth) { case 32: return SCREEN_FORMAT_RGBA8888; case 24: return SCREEN_FORMAT_RGB888; case 16: { switch (alpha_bit_depth) { case 4: return SCREEN_FORMAT_RGBA4444; case 1: return SCREEN_FORMAT_RGBA5551; default: return SCREEN_FORMAT_RGB565; } } default: return 0; } } void CCEGLView::printEGLInfo(const EGLConfig &config) const { int i; fprintf(stderr,"EGL_VENDOR = %s\n", eglQueryString(m_eglDisplay, EGL_VENDOR)); fprintf(stderr,"EGL_VERSION = %s\n", eglQueryString(m_eglDisplay, EGL_VERSION)); fprintf(stderr,"EGL_CLIENT_APIS = %s\n", eglQueryString(m_eglDisplay, EGL_CLIENT_APIS)); fprintf(stderr,"EGL_EXTENSIONS = %s\n\n", eglQueryString(m_eglDisplay, EGL_EXTENSIONS)); i = -1; eglGetConfigAttrib(m_eglDisplay, config, EGL_CONFIG_ID, &i); fprintf(stderr,"EGL_CONFIG_ID = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_RED_SIZE, &i); fprintf(stderr,"EGL_RED_SIZE = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_GREEN_SIZE, &i); fprintf(stderr,"EGL_GREEN_SIZE = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_BLUE_SIZE, &i); fprintf(stderr,"EGL_BLUE_SIZE = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_ALPHA_SIZE, &i); fprintf(stderr,"EGL_ALPHA_SIZE = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_DEPTH_SIZE, &i); fprintf(stderr,"EGL_DEPTH_SIZE = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_LEVEL, &i); fprintf(stderr,"EGL_LEVEL = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_NATIVE_RENDERABLE, &i); fprintf(stderr,"EGL_NATIVE_RENDERABLE = %s\n", i ? "EGL_TRUE" : "EGL_FALSE"); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_NATIVE_VISUAL_TYPE, &i); fprintf(stderr,"EGL_NATIVE_VISUAL_TYPE = %d\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_RENDERABLE_TYPE, &i); fprintf(stderr,"EGL_RENDERABLE_TYPE = 0x%04x\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_SURFACE_TYPE, &i); fprintf(stderr,"EGL_SURFACE_TYPE = 0x%04x\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_TRANSPARENT_TYPE, &i); if (i == EGL_TRANSPARENT_RGB) { fprintf(stderr,"EGL_TRANSPARENT_TYPE = EGL_TRANSPARENT_RGB\n"); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_TRANSPARENT_RED_VALUE, &i); fprintf(stderr,"EGL_TRANSPARENT_RED = 0x%02x\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_TRANSPARENT_GREEN_VALUE, &i); fprintf(stderr,"EGL_TRANSPARENT_GREEN = 0x%02x\n", i); i = 0; eglGetConfigAttrib(m_eglDisplay, config, EGL_TRANSPARENT_BLUE_VALUE, &i); fprintf(stderr,"EGL_TRANSPARENT_BLUE = 0x%02x\n\n", i); } else { fprintf(stderr,"EGL_TRANSPARENT_TYPE = EGL_NONE\n\n"); } } static void printEglError( GLuint errorCode ) { switch( errorCode ) { case EGL_SUCCESS: fprintf( stderr, "EGL_SUCCESS"); break; case EGL_NOT_INITIALIZED: fprintf( stderr, ">>EGL_NOT_INITIALIZED"); break; case EGL_BAD_ACCESS: fprintf( stderr, ">>EGL_BAD_ACCESS"); break; case EGL_BAD_ALLOC: fprintf( stderr, ">>EGL_BAD_ALLOC"); break; case EGL_BAD_ATTRIBUTE: fprintf( stderr, ">>EGL_BAD_ATTRIBUTE"); break; case EGL_BAD_CONTEXT: fprintf( stderr, ">>EGL_BAD_CONTEXT"); break; case EGL_BAD_CONFIG: fprintf( stderr, ">>EGL_BAD_CONFIG"); break; case EGL_BAD_CURRENT_SURFACE: fprintf( stderr, ">>EGL_BAD_CURRENT_SURFACE"); break; case EGL_BAD_DISPLAY: fprintf( stderr, ">>EGL_BAD_DISPLAY"); break; case EGL_BAD_SURFACE: fprintf( stderr, ">>EGL_BAD_SURFACE"); break; case EGL_BAD_MATCH: fprintf( stderr, ">>EGL_BAD_MATCH"); break; case EGL_BAD_PARAMETER: fprintf( stderr, ">>EGL_BAD_PARAMETER"); break; case EGL_BAD_NATIVE_PIXMAP: fprintf( stderr, ">>EGL_BAD_NATIVE_PIXMAP"); break; case EGL_BAD_NATIVE_WINDOW: fprintf( stderr, ">>EGL_BAD_NATIVE_WIN i=i+2DOW"); break; case EGL_CONTEXT_LOST: fprintf( stderr, ">>EGL_CONTEXT_LOST"); break; default: fprintf( stderr, ">>Unknown error"); break; } } bool CCEGLView::initDriver() { int err; int egl_ret; EGLint majorVersion; EGLint minorVersion; // Get EGL display m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); err = eglGetError(); if (m_eglDisplay == EGL_NO_DISPLAY || err != EGL_SUCCESS) { printEglError( err ); return false; } // Initialize EGL egl_ret = eglInitialize(m_eglDisplay, &majorVersion, &minorVersion); err = eglGetError(); if ( egl_ret != EGL_TRUE || err != EGL_SUCCESS ) { printEglError( err ); return false; } return true; } bool CCEGLView::createNativeWindow(const EGLConfig &config) { int usage = SCREEN_USAGE_OPENGL_ES1; int transp = SCREEN_TRANSPARENCY_NONE; int pos[2] = { 0, 0 }; int nbuffers = 2; EGLint interval = 1; int format; EGLint err; err = screen_create_context(&m_screenContext, 0); if (err) { fprintf(stderr, "screen_create_context"); return false; } err = screen_create_window(&m_screenWindow, m_screenContext); if (err) { fprintf(stderr, "screen_create_window"); return false; } err = screen_create_window_group(m_screenWindow, m_window_group_id); if (err) { fprintf(stderr, "screen_create_window_group"); return false; } format = chooseFormat(m_eglDisplay, config); err = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_FORMAT, &format); if (err) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)"); return false; } err = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_USAGE, &usage); if (err) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)"); return false; } if (pos[0] != 0 || pos[1] != 0) { err = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_POSITION, pos); if (err) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_POSITION)"); return false; } } err = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_TRANSPARENCY, &transp); if (err) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_TRANSPARENCY)"); return false; } err = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_SWAP_INTERVAL, &interval); if (err) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_SWAP_INTERVAL)"); return false; } screen_display_t screen_disp; int rc = screen_get_window_property_pv(m_screenWindow, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp); if (rc) { fprintf(stderr, "screen_get_window_property_pv(SCREEN_PROPERTY_DISPLAY)"); return false; } screen_display_mode_t screen_mode; rc = screen_get_display_property_pv(screen_disp, SCREEN_PROPERTY_MODE, (void**)&screen_mode); if (rc) { fprintf(stderr, "screen_get_display_property_pv(SCREEN_PROPERTY_MODE)"); return false; } int size[2]; rc = screen_get_window_property_iv(m_screenWindow, SCREEN_PROPERTY_BUFFER_SIZE, size); if (rc) { fprintf(stderr, "screen_get_window_property_iv(SCREEN_PROPERTY_BUFFER_SIZE)"); return false; } int angle = atoi(getenv("ORIENTATION")); int buffer_size[2] = { size[0], size[1] }; if ((angle == 0) || (angle == 180)) { if (((screen_mode.width > screen_mode.height) && (size[0] < size[1])) || ((screen_mode.width < screen_mode.height) && (size[0] > size[1]))) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else if ((angle == 90) || (angle == 270)) { if (((screen_mode.width > screen_mode.height) && (size[0] > size[1])) || ((screen_mode.width < screen_mode.height && size[0] < size[1]))) { buffer_size[1] = size[0]; buffer_size[0] = size[1]; } } else { fprintf(stderr, "Navigator returned an unexpected orientation angle of %d.\n", angle); return false; } rc = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_BUFFER_SIZE, buffer_size); if (rc) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_BUFFER_SIZE)"); return false; } rc = screen_set_window_property_iv(m_screenWindow, SCREEN_PROPERTY_ROTATION, &angle); if (rc) { fprintf(stderr, "screen_set_window_property_iv(SCREEN_PROPERTY_ROTATION)"); return false; } err = screen_create_window_buffers(m_screenWindow, nbuffers); if (err) { fprintf(stderr, "screen_create_window_buffers"); return false; } return true; } #define N_BPS_EVENTS 1 bool CCEGLView::initGL() { EGLConfig config; EGLint err; initDriver(); config = chooseConfig(m_eglDisplay, "rgb565"); if (config == (EGLConfig)0) { fprintf(stderr, "Failed to find config!" ); return false; } // Create EGL rendering context m_eglContext = eglCreateContext( m_eglDisplay, config, EGL_NO_CONTEXT, NULL ); err = eglGetError( ); if ( m_eglContext == EGL_NO_CONTEXT ) { fprintf(stderr, "Can't create gles2 context!" ); printEglError( err ); return false; } // printEGLInfo(config); if (!createNativeWindow(config)) { fprintf(stderr, "Unable to create a native window\n"); return false; } // set up the screen events err = screen_create_event(&m_screenEvent); if (err) { fprintf(stderr, "screen_create_event"); return false; } #ifdef BPS_EVENTS // Request screen events screen_request_events(m_screenContext); #endif m_eglSurface = eglCreateWindowSurface(m_eglDisplay, config, m_screenWindow, NULL); if (m_eglSurface == EGL_NO_SURFACE) { fprintf(stderr, "Demo Thread Init: can't create surface!" ); printEglError( err ); return false; } err = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); if (err != EGL_TRUE) { fprintf(stderr, "Demo Thread Init: can't make current!" ); return false; } EGLint width, height; if ((m_eglDisplay == EGL_NO_DISPLAY) || (m_eglSurface == EGL_NO_SURFACE) ) return EXIT_FAILURE; eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width); eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height); m_sSizeInPixel.width = width; m_sSizeInPixel.height = height; return true; } CCSize CCEGLView::getSize() { if (m_bNotHVGA) { CCSize size(m_sSizeInPoint.width, m_sSizeInPoint.height); return size; } else { CCSize size(m_sSizeInPixel.width, m_sSizeInPixel.height); return size; } } bool CCEGLView::isOpenGLReady() { return (m_isGLInitialized && m_sSizeInPixel.width != 0 && m_sSizeInPixel.height != 0); } void CCEGLView::release() { if (!m_eglContext || !m_eglDisplay) return; #ifdef BPS_EVENTS screen_stop_events(m_screenContext); #endif bps_shutdown(); screen_destroy_event(m_screenEvent); eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL); eglDestroySurface(m_eglDisplay, m_eglSurface); screen_destroy_window(m_screenWindow); screen_destroy_context(m_screenContext); eglDestroyContext(m_eglDisplay, m_eglContext); eglTerminate(m_eglDisplay); eglReleaseThread(); m_eglDisplay = NULL; m_eglContext = NULL; m_eglSurface = NULL; m_isGLInitialized = false; exit(0); } void CCEGLView::setEventHandler(EventHandler* pHandler) { m_pEventHandler = pHandler; } const char* CCEGLView::getWindowGroupId() const { return m_window_group_id; } void CCEGLView::setTouchDelegate(EGLTouchDelegate * pDelegate) { m_pDelegate = pDelegate; } EGLTouchDelegate* CCEGLView::getDelegate(void) { return m_pDelegate; } bool CCEGLView::HandleEvents() { bps_event_t* event = NULL; mtouch_event_t mtouch_event; int touch_id = 0; int val = 0; int rc = 0; int domain = 0; char buf[4] = {0}; for (;;) { rc = bps_get_event(&event, 1); assert(rc == BPS_SUCCESS); #ifdef BPS_EVENTS // break if no more events if (event == NULL) break; #else if (event != NULL) { #endif if (m_pEventHandler && m_pEventHandler->HandleBPSEvent(event)) continue; domain = bps_event_get_domain(event); if (domain == navigator_get_domain()) { switch (bps_event_get_code(event)) { case NAVIGATOR_SWIPE_DOWN: CCKeypadDispatcher::sharedDispatcher()->dispatchKeypadMSG(kTypeMenuClicked); break; case NAVIGATOR_EXIT: // exit the application // release(); break; case NAVIGATOR_WINDOW_INACTIVE: if(m_isWindowActive) { CCApplication::sharedApplication().applicationDidEnterBackground(); m_isWindowActive = false; } break; case NAVIGATOR_WINDOW_ACTIVE: if(!m_isWindowActive) { CCApplication::sharedApplication().applicationWillEnterForeground(); m_isWindowActive = true; } break; case NAVIGATOR_WINDOW_STATE: { switch(navigator_event_get_window_state(event)) { case NAVIGATOR_WINDOW_FULLSCREEN: if(!m_isWindowActive) { CCApplication::sharedApplication().applicationWillEnterForeground(); m_isWindowActive = true; } break; case NAVIGATOR_WINDOW_THUMBNAIL: if(m_isWindowActive) { CCApplication::sharedApplication().applicationDidEnterBackground(); m_isWindowActive = false; } break; } break; } default: break; } } } #ifndef BPS_EVENTS // for now handle screen events separately from BPS events if (screen_get_event(m_screenContext, m_screenEvent, 0) < 0) { // we have an error condition in the screen event break; } else { #else else if (domain == screen_get_domain()) { m_screenEvent = screen_event_get_event(event); #endif rc = screen_get_event_property_iv(m_screenEvent, SCREEN_PROPERTY_TYPE, &val); if (rc || val == SCREEN_EVENT_NONE) break; switch (val) { case SCREEN_EVENT_CLOSE: fprintf(stderr, "SCREEN CLOSE EVENT!\n"); break; case SCREEN_EVENT_MTOUCH_RELEASE: screen_get_mtouch_event(m_screenEvent, &mtouch_event, 0); touch_id = mtouch_event.contact_id; if (m_pDelegate && touch_id < MAX_TOUCHES) { CCTouch* touch = s_pTouches[touch_id]; if (touch) { CCSet set; touch->SetTouchInfo(((float)(mtouch_event.x) - m_rcViewPort.origin.x) / m_fScreenScaleFactor, ((float)(mtouch_event.y) - m_rcViewPort.origin.y) / m_fScreenScaleFactor); set.addObject(touch); m_pDelegate->touchesEnded(&set, NULL); touch->release(); for (int i = touch_id; i < MAX_TOUCHES; i++) { if (i != (MAX_TOUCHES - 1)) { s_pTouches[i] = s_pTouches[i + 1]; } else { s_pTouches[i] = NULL; } } } } break; case SCREEN_EVENT_MTOUCH_TOUCH: screen_get_mtouch_event(m_screenEvent, &mtouch_event, 0); touch_id = mtouch_event.contact_id; if (m_pDelegate && touch_id < MAX_TOUCHES) { CCTouch* touch = s_pTouches[touch_id]; if (!touch) touch = new CCTouch; touch->SetTouchInfo(((float)(mtouch_event.x) - m_rcViewPort.origin.x) / m_fScreenScaleFactor, ((float)(mtouch_event.y) - m_rcViewPort.origin.y) / m_fScreenScaleFactor); s_pTouches[touch_id] = touch; CCSet set; set.addObject(touch); m_pDelegate->touchesBegan(&set, NULL); } break; case SCREEN_EVENT_MTOUCH_MOVE: screen_get_mtouch_event(m_screenEvent, &mtouch_event, 0); touch_id = mtouch_event.contact_id; if (m_pDelegate && touch_id < MAX_TOUCHES) { CCTouch* touch = s_pTouches[touch_id]; if (touch) { CCSet set; touch->SetTouchInfo(((float)(mtouch_event.x) - m_rcViewPort.origin.x) / m_fScreenScaleFactor, ((float)(mtouch_event.y) - m_rcViewPort.origin.y) / m_fScreenScaleFactor); set.addObject(touch); m_pDelegate->touchesMoved(&set, NULL); } } break; case SCREEN_EVENT_POINTER: { int buttons; int pair[2]; static bool mouse_pressed = false; // this is a mouse move event, it is applicable to a device with a usb mouse or simulator screen_get_event_property_iv(m_screenEvent, SCREEN_PROPERTY_BUTTONS, &buttons); screen_get_event_property_iv(m_screenEvent, SCREEN_PROPERTY_SOURCE_POSITION, pair); if (buttons & SCREEN_LEFT_MOUSE_BUTTON) { if (mouse_pressed) { // Left mouse button was released if (m_pDelegate && touch_id < MAX_TOUCHES) { CCTouch* touch = s_pTouches[touch_id]; if (touch) { CCSet set; touch->SetTouchInfo(((float)(pair[0]) - m_rcViewPort.origin.x) / m_fScreenScaleFactor, ((float)(pair[1]) - m_rcViewPort.origin.y) / m_fScreenScaleFactor); set.addObject(touch); m_pDelegate->touchesMoved(&set, NULL); } } } else { // Left mouse button is pressed mouse_pressed = true; if (m_pDelegate && touch_id < MAX_TOUCHES) { CCTouch* touch = s_pTouches[touch_id]; if (!touch) touch = new CCTouch; touch->SetTouchInfo(((float)(pair[0]) - m_rcViewPort.origin.x) / m_fScreenScaleFactor, ((float)(pair[1]) - m_rcViewPort.origin.y) / m_fScreenScaleFactor); s_pTouches[touch_id] = touch; CCSet set; set.addObject(touch); m_pDelegate->touchesBegan(&set, NULL); } } } else { if (mouse_pressed) { if (m_pDelegate && touch_id < MAX_TOUCHES) { mouse_pressed = false; CCTouch* touch = s_pTouches[touch_id]; if (touch) { CCSet set; touch->SetTouchInfo(((float)(pair[0]) - m_rcViewPort.origin.x) / m_fScreenScaleFactor, ((float)(pair[1]) - m_rcViewPort.origin.y) / m_fScreenScaleFactor); set.addObject(touch); m_pDelegate->touchesEnded(&set, NULL); touch->release(); for (int i = touch_id; i < MAX_TOUCHES; i++) { if (i != (MAX_TOUCHES - 1)) { s_pTouches[i] = s_pTouches[i + 1]; } else { s_pTouches[i] = NULL; } } } } } } } break; case SCREEN_EVENT_KEYBOARD: screen_get_event_property_iv(m_screenEvent, SCREEN_PROPERTY_KEY_FLAGS, &val); if (val & KEY_DOWN) { screen_get_event_property_iv(m_screenEvent, SCREEN_PROPERTY_KEY_SYM, &val); if (val >= ' ' && val < '~') { buf[0] = val; buf[1]= '\0'; CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(buf, 1); } else { val = val - 0xf000; buf[0] = val; buf[1]= '\0'; switch (val) { case 8: // backspace // CCKeypadDispatcher::sharedDispatcher()->dispatchKeypadMSG(kTypeBackClicked); CCIMEDispatcher::sharedDispatcher()->dispatchDeleteBackward(); break; default: CCIMEDispatcher::sharedDispatcher()->dispatchInsertText(buf, 1); break; } } } break; default: break; } } } return true; } void CCEGLView::swapBuffers() { eglSwapBuffers(m_eglDisplay, m_eglSurface); } bool CCEGLView::canSetContentScaleFactor() { // can scale content? return false; } void CCEGLView::setContentScaleFactor(float contentScaleFactor) { m_fScreenScaleFactor = contentScaleFactor; } void CCEGLView::setViewPortInPoints(float x, float y, float w, float h) { if (m_bNotHVGA) { float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); glViewport( (GLint)(x * factor) + m_rcViewPort.origin.x, (GLint)(y * factor) + m_rcViewPort.origin.y, (GLint)(w * factor), (GLint)(h * factor)); } else { glViewport( (GLint)x, (GLint)y, (GLint)w, (GLint)h); } } void CCEGLView::setScissorInPoints(float x, float y, float w, float h) { if (m_bNotHVGA) { float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); glScissor( (GLint)(x * factor) + m_rcViewPort.origin.x, (GLint)(y * factor) + m_rcViewPort.origin.y, (GLint)(w * factor), (GLint)(h * factor)); } else { glScissor( (GLint)x, (GLint)y, (GLint)w, (GLint)h); } } CCEGLView& CCEGLView::sharedOpenGLView() { CCAssert(s_pInstance != NULL, "CCEGLView wasn't constructed yet"); return *s_pInstance; } float CCEGLView::getScreenScaleFactor() { return m_fScreenScaleFactor; } CCRect CCEGLView::getViewPort() { if (m_bNotHVGA) { return m_rcViewPort; } else { CCRect rect(0, 0, 0, 0); return rect; } } bool CCEGLView::isGLExtension(const char *searchName) const { const GLubyte *start; GLubyte *where, *terminator; /* It takes a bit of care to be fool-proof about parsing the OpenGL extensions string. Don't be fooled by sub-strings, etc. */ start = m_extensions; for (;;) { where = (GLubyte *) strstr((const char *) start, searchName); if (!where) break; terminator = where + strlen(searchName); if (where == start || *(where - 1) == ' ') if (*terminator == ' ' || *terminator == '\0') return true; start = terminator; } return false; } void CCEGLView::showKeyboard() { int height; virtualkeyboard_get_height(&height); float factor = m_fScreenScaleFactor / CC_CONTENT_SCALE_FACTOR(); height = (float)height / factor; CCRect rect_begin(0, 0 - height, m_sSizeInPixel.width / factor, height); CCRect rect_end(0, 0, m_sSizeInPixel.width / factor, height); CCIMEKeyboardNotificationInfo info; info.begin = rect_begin; info.end = rect_end; info.duration = 0; CCIMEDispatcher::sharedDispatcher()->dispatchKeyboardWillShow(info); virtualkeyboard_show(); CCIMEDispatcher::sharedDispatcher()->dispatchKeyboardDidShow(info); } void CCEGLView::hideKeyboard() { virtualkeyboard_hide(); } void CCEGLView::setIMEKeyboardState(bool bOpen) { if (bOpen) showKeyboard(); else hideKeyboard(); } } // end of namespace cocos2d