__unused JNIEXPORT void JNICALL Java_pl_droidsonroids_gif_GifInfoHandle_bindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo, jobject jsurface, jlongArray savedState, jboolean isOpaque) { GifInfo *info = (GifInfo *) (intptr_t) gifInfo; if (info->surfaceDescriptor == NULL) { info->surfaceDescriptor = malloc(sizeof(SurfaceDescriptor)); if (!initSurfaceDescriptor(info->surfaceDescriptor, env)) { free(info->surfaceDescriptor); info->surfaceDescriptor = NULL; return; } } POLL_TYPE eftd_ctr; int pollResult; while (1) { pollResult = poll(&info->surfaceDescriptor->eventPollFd, 1, 0); if (pollResult == 0) break; else if (pollResult > 0) { if (read(info->surfaceDescriptor->eventPollFd.fd, &eftd_ctr, POLL_TYPE_SIZE) != POLL_TYPE_SIZE) { throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "Read on flushing failed"); return; } } else { throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "Poll on flushing failed"); return; } } const int32_t windowFormat = isOpaque == JNI_TRUE ? WINDOW_FORMAT_RGBX_8888 : WINDOW_FORMAT_RGBA_8888; info->isOpaque = isOpaque; struct ANativeWindow *window = ANativeWindow_fromSurface(env, jsurface); if (ANativeWindow_setBuffersGeometry(window, (int32_t) info->gifFilePtr->SWidth, (int32_t) info->gifFilePtr->SHeight, windowFormat) != 0) { ANativeWindow_release(window); throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "Buffers geometry setting failed"); return; } struct ANativeWindow_Buffer buffer = {.bits =NULL}; void *oldBufferBits; if (ANativeWindow_lock(window, &buffer, NULL) != 0) { ANativeWindow_release(window); throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "Window lock failed"); return; } const size_t bufferSize = buffer.stride * buffer.height * sizeof(argb); info->stride = buffer.stride; long invalidationDelayMillis; if (info->surfaceDescriptor->surfaceBackupPtr) { memcpy(buffer.bits, info->surfaceDescriptor->surfaceBackupPtr, bufferSize); invalidationDelayMillis = 0; info->surfaceDescriptor->renderHelper = 1; info->surfaceDescriptor->slurpHelper = 0; } else { if (savedState != NULL){ invalidationDelayMillis = restoreSavedState(info, env, savedState, buffer.bits); if (invalidationDelayMillis <0) invalidationDelayMillis =0; } else invalidationDelayMillis = 0; info->surfaceDescriptor->renderHelper = 0; info->surfaceDescriptor->slurpHelper = 1; } info->lastFrameRemainder = -1; ANativeWindow_unlockAndPost(window); if (info->loopCount != 0 && info->currentLoop == info->loopCount) { ANativeWindow_release(window); pollResult = poll(&info->surfaceDescriptor->eventPollFd, 1, -1); if (pollResult < 0) { throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "animation end poll failed"); } return; } pthread_t thread; if (pthread_create(&thread, NULL, slurp, info) != 0) { ANativeWindow_release(window); throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "pthread_create failed"); return; } while (1) { pollResult = poll(&info->surfaceDescriptor->eventPollFd, 1, (int) invalidationDelayMillis); long renderingStartTime = getRealTime(); if (pollResult < 0) { throwException(env, ILLEGAL_STATE_EXCEPTION_ERRNO, "Poll failed"); break; } else if (pollResult > 0) { if (info->surfaceDescriptor->surfaceBackupPtr == NULL) { info->surfaceDescriptor->surfaceBackupPtr = malloc(bufferSize); if (info->surfaceDescriptor->surfaceBackupPtr == NULL) { throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); break; } } memcpy(info->surfaceDescriptor->surfaceBackupPtr, buffer.bits, bufferSize); break; } oldBufferBits = buffer.bits; THROW_AND_BREAK_ON_NONZERO_RESULT(ANativeWindow_lock(window, &buffer, NULL), "Window lock failed"); if (info->currentIndex == 0) prepareCanvas(buffer.bits, info); else memcpy(buffer.bits, oldBufferBits, bufferSize); pthread_mutex_lock(&info->surfaceDescriptor->renderMutex); while (info->surfaceDescriptor->renderHelper == 0) { pthread_cond_wait(&info->surfaceDescriptor->renderCond, &info->surfaceDescriptor->renderMutex); } info->surfaceDescriptor->renderHelper = 0; pthread_mutex_unlock(&info->surfaceDescriptor->renderMutex); const uint_fast32_t frameDuration = getBitmap(buffer.bits, info); pthread_mutex_lock(&info->surfaceDescriptor->slurpMutex); info->surfaceDescriptor->slurpHelper = 1; pthread_cond_signal(&info->surfaceDescriptor->slurpCond); pthread_mutex_unlock(&info->surfaceDescriptor->slurpMutex); ANativeWindow_unlockAndPost(window); invalidationDelayMillis = calculateInvalidationDelay(info, renderingStartTime, frameDuration); if (info->lastFrameRemainder >= 0) { invalidationDelayMillis = info->lastFrameRemainder; info->lastFrameRemainder = -1; } } ANativeWindow_release(window); pthread_mutex_lock(&info->surfaceDescriptor->slurpMutex); info->surfaceDescriptor->slurpHelper = 2; pthread_cond_signal(&info->surfaceDescriptor->slurpCond); pthread_mutex_unlock(&info->surfaceDescriptor->slurpMutex); THROW_ON_NONZERO_RESULT(pthread_join(thread, NULL), "join failed"); }
int StWinHandles::glCreateContext(StWinHandles* theSlave, const StRectI_t& theRect, const int theDepthSize, const bool theIsQuadStereo, const bool theDebugCtx) { (void )theRect; #ifdef _WIN32 ThreadGL = StThread::getCurrentThreadId(); ST_DEBUG_LOG("WinAPI, glCreateContext, ThreadGL= " + ThreadGL + ", ThreadWnd= " + ThreadWnd); hDC = GetDC(hWindowGl); ST_GL_ERROR_CHECK(hDC != NULL, STWIN_ERROR_WIN32_GLDC, "WinAPI, Can't create Master GL Device Context"); if(theSlave != NULL) { theSlave->ThreadGL = ThreadGL; theSlave->hDC = GetDC(theSlave->hWindowGl); ST_GL_ERROR_CHECK(theSlave->hDC != NULL, STWIN_ERROR_WIN32_GLDC, "WinAPI, Can't create Slave GL Device Context"); } HGLRC aRendCtx = NULL; { PIXELFORMATDESCRIPTOR aPixFrmtDesc = THE_PIXELFRMT_DOUBLE; aPixFrmtDesc.cDepthBits = (BYTE )theDepthSize; if(theIsQuadStereo) { aPixFrmtDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_STEREO; } HMODULE aModule = GetModuleHandleW(NULL); hWinTmp = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE, ClassTmp.toCString(), L"TmpWnd", WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED, // always create temporary window on main screen // to workaround sporadic bugs (access violation) in AMD Catalyst drivers 2, 2, 4, 4, //theRect.left() + 2, theRect.top() + 2, 4, 4, NULL, NULL, aModule, NULL); ST_GL_ERROR_CHECK(hWinTmp != NULL, STWIN_ERROR_WIN32_GLDC, "WinAPI, Temporary window creation error"); HDC aDevCtxTmp = GetDC(hWinTmp); int aPixFrmtIdTmp = ChoosePixelFormat(aDevCtxTmp, &aPixFrmtDesc); ST_GL_ERROR_CHECK(aPixFrmtIdTmp != 0, STWIN_ERROR_WIN32_PIXELFORMATF, "WinAPI, Can't find a suitable PixelFormat for Tmp"); ST_GL_ERROR_CHECK(SetPixelFormat(aDevCtxTmp, aPixFrmtIdTmp, &aPixFrmtDesc), STWIN_ERROR_WIN32_PIXELFORMATS, "WinAPI, Can't set the PixelFormat for Master"); StWinGlrcH aRendCtxTmp = new StWinGlrc(aDevCtxTmp, NULL); ST_GL_ERROR_CHECK(aRendCtxTmp->isValid(), STWIN_ERROR_WIN32_GLRC_CREATE, "WinAPI, Can't create GL Rendering Context"); ST_GL_ERROR_CHECK(aRendCtxTmp->makeCurrent(aDevCtxTmp), STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Can't activate Tmp GL Rendering Context"); StGLContext aCtx(false); ST_GL_ERROR_CHECK(aCtx.stglInit(), STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Broken Tmp GL Rendering Context"); int aPixFrmtId = 0; if(aCtx.extAll->wglChoosePixelFormatARB != NULL) { const int aPixAttribs[] = { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_STEREO_ARB, theIsQuadStereo ? GL_TRUE : GL_FALSE, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, //WGL_SAMPLE_BUFFERS_ARB, 1, //WGL_SAMPLES_ARB, 8, // WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 WGL_COLOR_BITS_ARB, 24, WGL_DEPTH_BITS_ARB, theDepthSize, WGL_STENCIL_BITS_ARB, 0, 0, 0, }; unsigned int aFrmtsNb = 0; aCtx.extAll->wglChoosePixelFormatARB(hDC, aPixAttribs, NULL, 1, &aPixFrmtId, &aFrmtsNb); if(theSlave != NULL) { int aPixFrmtIdSlave = 0; aCtx.extAll->wglChoosePixelFormatARB(theSlave->hDC, aPixAttribs, NULL, 1, &aPixFrmtIdSlave, &aFrmtsNb); if(aPixFrmtIdSlave != aPixFrmtId) { ST_ERROR_LOG("Slave window returns another pixel format! Try to ignore..."); } } } else { aPixFrmtId = ChoosePixelFormat(hDC, &aPixFrmtDesc); if(theSlave != NULL && ChoosePixelFormat(theSlave->hDC, &aPixFrmtDesc) != aPixFrmtId) { ST_ERROR_LOG("Slave window returns another pixel format! Try to ignore..."); } } ST_GL_ERROR_CHECK(aPixFrmtId != 0, STWIN_ERROR_WIN32_PIXELFORMATF, "WinAPI, Can't find a suitable PixelFormat for Master"); DescribePixelFormat(hDC, aPixFrmtId, sizeof(PIXELFORMATDESCRIPTOR), &aPixFrmtDesc); if(theIsQuadStereo) { if((aPixFrmtDesc.dwFlags & PFD_STEREO) == 0) { ST_ERROR_LOG("WinAPI, Quad Buffered stereo is not supported"); } } ST_GL_ERROR_CHECK(SetPixelFormat(hDC, aPixFrmtId, &aPixFrmtDesc), STWIN_ERROR_WIN32_PIXELFORMATS, "WinAPI, Can't set the PixelFormat for Master"); ST_GL_ERROR_CHECK(theSlave == NULL || SetPixelFormat(theSlave->hDC, aPixFrmtId, &aPixFrmtDesc), STWIN_ERROR_WIN32_PIXELFORMATS, "WinAPI, Can't set the PixelFormat for Slave"); if(aCtx.extAll->wglCreateContextAttribsARB != NULL) { // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB int aCtxAttribs[] = { //WGL_CONTEXT_MAJOR_VERSION_ARB, 3, //WGL_CONTEXT_MINOR_VERSION_ARB, 2, //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //WGL_CONTEXT_CORE_PROFILE_BIT_ARB, WGL_CONTEXT_FLAGS_ARB, theDebugCtx ? WGL_CONTEXT_DEBUG_BIT_ARB : 0, 0, 0 }; aRendCtx = aCtx.extAll->wglCreateContextAttribsARB(hDC, NULL, aCtxAttribs); } aRendCtxTmp.nullify(); destroyWindow(hWinTmp); } hRC = new StWinGlrc(hDC, aRendCtx); ST_GL_ERROR_CHECK(hRC->isValid(), STWIN_ERROR_WIN32_GLRC_CREATE, "WinAPI, Can't create GL Rendering Context"); if(theSlave != NULL) { theSlave->hRC = hRC; } ST_GL_ERROR_CHECK(hRC->makeCurrent(hDC), STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Can't activate Master GL Rendering Context"); return STWIN_INIT_SUCCESS; #elif defined(__linux__) // create an OpenGL rendering context #if defined(ST_HAVE_EGL) || defined(__ANDROID__) // GL context is created beforehand for EGL ST_GL_ERROR_CHECK(!hRC.isNull() && hRC->isValid(), STWIN_ERROR_X_GLRC_CREATE, "EGL, could not create rendering context for Master"); #if defined(__ANDROID__) EGLint aFormat = 0; eglGetConfigAttrib(hRC->getDisplay(), hRC->getConfig(), EGL_NATIVE_VISUAL_ID, &aFormat); ANativeWindow_setBuffersGeometry(hWindowGl, 0, 0, aFormat); #endif eglSurface = eglCreateWindowSurface(hRC->getDisplay(), hRC->getConfig(), hWindowGl, NULL); if(theSlave != NULL) { theSlave->hRC = hRC; theSlave->eglSurface = eglCreateWindowSurface(hRC->getDisplay(), hRC->getConfig(), theSlave->hWindowGl, NULL); // bind the rendering context to the window ST_GL_ERROR_CHECK(hRC->makeCurrent(theSlave->eglSurface), STWIN_ERROR_X_GLRC_CREATE, "EGL, Can't activate Slave GL Rendering Context"); } // bind the rendering context to the window ST_GL_ERROR_CHECK(hRC->makeCurrent(eglSurface), STWIN_ERROR_X_GLRC_CREATE, "EGL, Can't activate Master GL Rendering Context"); return STWIN_INIT_SUCCESS; #else // GLX hRC = new StWinGlrc(stXDisplay, theDebugCtx); ST_GL_ERROR_CHECK(hRC->isValid(), STWIN_ERROR_X_GLRC_CREATE, "GLX, could not create rendering context for Master"); if(theSlave != NULL) { theSlave->hRC = hRC; // bind the rendering context to the window ST_GL_ERROR_CHECK(hRC->makeCurrent(theSlave->hWindowGl), STWIN_ERROR_X_GLRC_CREATE, "GLX, Can't activate Slave GL Rendering Context"); } // bind the rendering context to the window ST_GL_ERROR_CHECK(hRC->makeCurrent(hWindowGl), STWIN_ERROR_X_GLRC_CREATE, "GLX, Can't activate Master GL Rendering Context"); return STWIN_INIT_SUCCESS; #endif // GLX or EGL #endif }
void GlContext::create(uint32_t _width, uint32_t _height) { # if BX_PLATFORM_RPI bcm_host_init(); # endif // BX_PLATFORM_RPI m_eglLibrary = eglOpen(); if (NULL == g_platformData.context) { BX_UNUSED(_width, _height); EGLNativeDisplayType ndt = (EGLNativeDisplayType)g_platformData.ndt; EGLNativeWindowType nwh = (EGLNativeWindowType )g_platformData.nwh; # if BX_PLATFORM_WINDOWS if (NULL == g_platformData.ndt) { ndt = GetDC( (HWND)g_platformData.nwh); } # endif // BX_PLATFORM_WINDOWS m_display = eglGetDisplay(ndt); BGFX_FATAL(m_display != EGL_NO_DISPLAY, Fatal::UnableToInitialize, "Failed to create display %p", m_display); EGLint major = 0; EGLint minor = 0; EGLBoolean success = eglInitialize(m_display, &major, &minor); BGFX_FATAL(success && major >= 1 && minor >= 3, Fatal::UnableToInitialize, "Failed to initialize %d.%d", major, minor); BX_TRACE("EGL info:"); const char* clientApis = eglQueryString(m_display, EGL_CLIENT_APIS); BX_TRACE(" APIs: %s", clientApis); BX_UNUSED(clientApis); const char* vendor = eglQueryString(m_display, EGL_VENDOR); BX_TRACE(" Vendor: %s", vendor); BX_UNUSED(vendor); const char* version = eglQueryString(m_display, EGL_VERSION); BX_TRACE("Version: %s", version); BX_UNUSED(version); const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS); BX_TRACE("Supported EGL extensions:"); dumpExtensions(extensions); EGLint attrs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, # if BX_PLATFORM_ANDROID EGL_DEPTH_SIZE, 16, # else EGL_DEPTH_SIZE, 24, # endif // BX_PLATFORM_ EGL_STENCIL_SIZE, 8, EGL_NONE }; EGLint numConfig = 0; success = eglChooseConfig(m_display, attrs, &m_config, 1, &numConfig); BGFX_FATAL(success, Fatal::UnableToInitialize, "eglChooseConfig"); # if BX_PLATFORM_ANDROID EGLint format; eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry( (ANativeWindow*)g_platformData.nwh, _width, _height, format); # elif BX_PLATFORM_RPI DISPMANX_DISPLAY_HANDLE_T dispmanDisplay = vc_dispmanx_display_open(0); DISPMANX_UPDATE_HANDLE_T dispmanUpdate = vc_dispmanx_update_start(0); VC_RECT_T dstRect = { 0, 0, _width, _height }; VC_RECT_T srcRect = { 0, 0, _width << 16, _height << 16 }; DISPMANX_ELEMENT_HANDLE_T dispmanElement = vc_dispmanx_element_add(dispmanUpdate , dispmanDisplay , 0 , &dstRect , 0 , &srcRect , DISPMANX_PROTECTION_NONE , NULL , NULL , DISPMANX_NO_ROTATE ); s_dispmanWindow.element = dispmanElement; s_dispmanWindow.width = _width; s_dispmanWindow.height = _height; nwh = &s_dispmanWindow; vc_dispmanx_update_submit_sync(dispmanUpdate); # endif // BX_PLATFORM_ANDROID m_surface = eglCreateWindowSurface(m_display, m_config, nwh, NULL); BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::UnableToInitialize, "Failed to create surface."); const bool hasEglKhrCreateContext = !!bx::findIdentifierMatch(extensions, "EGL_KHR_create_context"); const bool hasEglKhrNoError = !!bx::findIdentifierMatch(extensions, "EGL_KHR_create_context_no_error"); for (uint32_t ii = 0; ii < 2; ++ii) { bx::StaticMemoryBlockWriter writer(s_contextAttrs, sizeof(s_contextAttrs) ); EGLint flags = 0; if (hasEglKhrCreateContext) { bx::write(&writer, EGLint(EGL_CONTEXT_MAJOR_VERSION_KHR) ); bx::write(&writer, EGLint(BGFX_CONFIG_RENDERER_OPENGLES / 10) ); bx::write(&writer, EGLint(EGL_CONTEXT_MINOR_VERSION_KHR) ); bx::write(&writer, EGLint(BGFX_CONFIG_RENDERER_OPENGLES % 10) ); flags |= BGFX_CONFIG_DEBUG && hasEglKhrNoError ? 0 | EGL_CONTEXT_FLAG_NO_ERROR_BIT_KHR : 0 ; if (0 == ii) { flags |= BGFX_CONFIG_DEBUG ? 0 | EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR // | EGL_OPENGL_ES3_BIT_KHR : 0 ; bx::write(&writer, EGLint(EGL_CONTEXT_FLAGS_KHR) ); bx::write(&writer, flags); } } else { bx::write(&writer, EGLint(EGL_CONTEXT_CLIENT_VERSION) ); bx::write(&writer, 2); } bx::write(&writer, EGLint(EGL_NONE) ); m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, s_contextAttrs); if (NULL != m_context) { break; } BX_TRACE("Failed to create EGL context with EGL_CONTEXT_FLAGS_KHR (%08x).", flags); } BGFX_FATAL(m_context != EGL_NO_CONTEXT, Fatal::UnableToInitialize, "Failed to create context."); success = eglMakeCurrent(m_display, m_surface, m_surface, m_context); BGFX_FATAL(success, Fatal::UnableToInitialize, "Failed to set context."); m_current = NULL; eglSwapInterval(m_display, 0); } import(); }
/** * Initialize an EGL context for the current display. */ static int engine_init_display(struct engine_info_t* engine) { uchar engineParameters = 0; char cwd[256]; char lpBuffer[256]; engineParameters |= GL_11_RENDERER ; setenv( "RD", "assets", 1 ); setenv( "WD", "mnt/sdcard/app-data/com.miadzin.shmup", 1 ); assetManager = getAssetManager(); renderer.materialQuality = MATERIAL_QUALITY_HIGH; renderer.glBuffersDimensions[WIDTH] = 480; renderer.glBuffersDimensions[HEIGHT] = 800; renderer.resolution = 1.5f; renderer.props |= PROP_FOG; renderer.props |= PROP_SHADOW ; renderer.props |= PROP_BUMP ; renderer.props |= PROP_SPEC ; int gameOn = 1; dEngine_Init(); // initialize OpenGL ES and EGL /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint w, h, dummy, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(display, attribs, &config, 1, &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); context = eglCreateContext(display, config, NULL, NULL); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); engine->display = display; engine->context = context; engine->surface = surface; engine->width = w; engine->height = h; //engine->state.angle = 0; // Initialize GL state. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glDisable(GL_DEPTH_TEST); dEngine_InitDisplaySystem(engineParameters); commScale[X] = commScale[Y] = renderer.resolution; return 0; }
/** * Initialize an EGL context for the current display. */ static int engine_init_display(struct engine* engine) { // initialize OpenGL ES and EGL /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_NONE }; EGLint w, h, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(display, attribs, &config, 1, &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; context = eglCreateContext(display, config, NULL, contextAttribs); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); engine->display = display; engine->context = context; engine->surface = surface; engine->width = w; engine->height = h; engine->state.angle = 0; if (!engine->mCubeRenderer) { engine->mCubeRenderer.reset(new SimpleRenderer()); engine->mCubeRenderer->UpdateWindowSize(w, h); } return 0; }
static pj_status_t init_opengl(void * data) { struct andgl_stream *strm = (struct andgl_stream *)data; const EGLint attr[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_NONE }; EGLint context_attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLConfig config; EGLint numConfigs; EGLint format; EGLint width; EGLint height; strm->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (strm->display == EGL_NO_DISPLAY || !eglInitialize(strm->display, NULL, NULL)) { EGL_ERR("initialize OpenGL display"); } if (!eglChooseConfig(strm->display, attr, &config, 1, &numConfigs) || (!eglGetConfigAttrib(strm->display, config, EGL_NATIVE_VISUAL_ID, &format))) { EGL_ERR("configure OpenGL display"); } if (ANativeWindow_setBuffersGeometry(strm->window, strm->param.disp_size.w, strm->param.disp_size.h, format) != 0) { EGL_ERR("set window geometry"); } strm->surface = eglCreateWindowSurface(strm->display, config, strm->window, 0); if (strm->surface == EGL_NO_SURFACE) EGL_ERR("create window surface"); strm->context = eglCreateContext(strm->display, config, EGL_NO_CONTEXT, context_attr); if (strm->context == EGL_NO_CONTEXT) EGL_ERR("create OpenGL context"); if (!eglMakeCurrent(strm->display, strm->surface, strm->surface, strm->context)) { EGL_ERR("make OpenGL as current context"); } if (!eglQuerySurface(strm->display, strm->surface, EGL_WIDTH, &width) || !eglQuerySurface(strm->display, strm->surface, EGL_HEIGHT, &height)) { EGL_ERR("query surface"); } /* Create GL buffers */ pjmedia_vid_dev_opengl_create_buffers(strm->pool, PJ_TRUE, &strm->gl_buf); /* Init GL buffers */ return pjmedia_vid_dev_opengl_init_buffers(strm->gl_buf); }
void init(android_app *app) { user_data *p = (user_data *)app->userData; p->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(p->display, 0, 0); int attrib_list[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; EGLConfig config; int num_config; eglChooseConfig(p->display, attrib_list, &config, 1, &num_config); int format; eglGetConfigAttrib(p->display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(app->window, 0, 0, format); p->surface = eglCreateWindowSurface(p->display, config, app->window, 0); const int context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; eglBindAPI(EGL_OPENGL_ES_API); p->context = eglCreateContext(p->display, config, EGL_NO_CONTEXT, context_attribs); eglMakeCurrent(p->display, p->surface, p->surface, p->context); p->program = glCreateProgram(); char *vertex_shader_source = "attribute vec2 a_pos; \n" "attribute vec2 a_tex_coord; \n" "varying vec2 v_tex_coord; \n" "void main() \n" "{ \n" " gl_Position = vec4(a_pos, 0, 1); \n" " v_tex_coord = a_tex_coord; \n" "} \n"; char *fragment_shader_source = "precision mediump float;\n" "varying vec2 v_tex_coord;\n" "uniform sampler2D tex;\n" "void main() \n" "{ \n" " vec4 texture_color = vec4(texture2D( tex, v_tex_coord ).bgr, 1.0);\n" " gl_FragColor = texture_color;\n" "} \n"; uint vertex_shader_id; uint fragment_shader_id; { uint shader = vertex_shader_id = glCreateShader(GL_VERTEX_SHADER); int compiled; glShaderSource(shader, 1, (const char* const *)&vertex_shader_source, 0); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { char info_log[1024]; glGetShaderInfoLog(shader, sizeof(info_log), 0, info_log); __android_log_print(ANDROID_LOG_INFO, p->app_name, "vertex shader failed to compile: %s", info_log); } } { uint shader = fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER); int compiled; glShaderSource(shader, 1, (const char* const *)&fragment_shader_source, 0); glCompileShader(shader); glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { char info_log[1024]; glGetShaderInfoLog(shader, sizeof(info_log), 0, info_log); __android_log_print(ANDROID_LOG_INFO, p->app_name, "fragment shader failed to compile: %s", info_log); } } glAttachShader(p->program, vertex_shader_id); glAttachShader(p->program, fragment_shader_id); glLinkProgram(p->program); int linked; glGetProgramiv(p->program, GL_LINK_STATUS, &linked); if (!linked) { char info_log[1024]; glGetProgramInfoLog(p->program, sizeof(info_log), 0, info_log); __android_log_print(ANDROID_LOG_INFO, p->app_name, "program failed to link: %s", info_log); } glUseProgram(p->program); p->a_pos_id = glGetAttribLocation(p->program, "a_pos"); p->a_tex_coord_id = glGetAttribLocation(p->program, "a_tex_coord"); p->sampler_id = glGetAttribLocation(p->program, "tex"); glEnableVertexAttribArray(p->a_pos_id); glEnableVertexAttribArray(p->a_tex_coord_id); glGenTextures(1, &p->texture_id); glBindTexture(GL_TEXTURE_2D, p->texture_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 960, 540, 0, GL_RGBA, GL_UNSIGNED_BYTE, p->texture_buffer); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glDepthFunc(GL_ALWAYS); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glDisable(GL_CULL_FACE); p->drawable = 1; }
void AndroidEGLWindow::_createInternalResources(NativeWindowType window, AConfiguration* config) { mWindow = window; int minAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BUFFER_SIZE, mMinBufferSize, EGL_DEPTH_SIZE, 16, EGL_NONE }; int maxAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BUFFER_SIZE, mMaxBufferSize, EGL_DEPTH_SIZE, mMaxDepthSize, EGL_STENCIL_SIZE, mMaxStencilSize, EGL_NONE }; bool bAASuccess = false; if (mCSAA) { try { int CSAAminAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BUFFER_SIZE, mMinBufferSize, EGL_DEPTH_SIZE, 16, EGL_COVERAGE_BUFFERS_NV, 1, EGL_COVERAGE_SAMPLES_NV, mCSAA, EGL_NONE }; int CSAAmaxAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BUFFER_SIZE, mMaxBufferSize, EGL_DEPTH_SIZE, mMaxDepthSize, EGL_STENCIL_SIZE, mMaxStencilSize, EGL_COVERAGE_BUFFERS_NV, 1, EGL_COVERAGE_SAMPLES_NV, mCSAA, EGL_NONE }; mEglConfig = mGLSupport->selectGLConfig(CSAAminAttribs, CSAAmaxAttribs); bAASuccess = true; } catch (Exception& e) { LogManager::getSingleton().logMessage("AndroidEGLWindow::_createInternalResources: setting CSAA failed"); } } if (mMSAA && !bAASuccess) { try { int MSAAminAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BUFFER_SIZE, mMinBufferSize, EGL_DEPTH_SIZE, 16, EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES, mMSAA, EGL_NONE }; int MSAAmaxAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BUFFER_SIZE, mMaxBufferSize, EGL_DEPTH_SIZE, mMaxDepthSize, EGL_STENCIL_SIZE, mMaxStencilSize, EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES, mMSAA, EGL_NONE }; mEglConfig = mGLSupport->selectGLConfig(MSAAminAttribs, MSAAmaxAttribs); bAASuccess = true; } catch (Exception& e) { LogManager::getSingleton().logMessage("AndroidEGLWindow::_createInternalResources: setting MSAA failed"); } } mEglDisplay = mGLSupport->getGLDisplay(); if (!bAASuccess) mEglConfig = mGLSupport->selectGLConfig(minAttribs, maxAttribs); EGLint format; eglGetConfigAttrib(mEglDisplay, mEglConfig, EGL_NATIVE_VISUAL_ID, &format); EGL_CHECK_ERROR ANativeWindow_setBuffersGeometry(mWindow, 0, 0, format); mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow); if(config) { bool isLandscape = (int)AConfiguration_getOrientation(config) == 2; mGLSupport->setConfigOption("Orientation", isLandscape ? "Landscape" : "Portrait"); } if(mContext) { mActive = true; mVisible = true; mClosed = false; mContext->_createInternalResources(mEglDisplay, mEglConfig, mEglSurface, NULL); mContext->setCurrent(); windowMovedOrResized(); static_cast<GLES2RenderSystem*>(Ogre::Root::getSingletonPtr()->getRenderSystem())->resetRenderer(this); } }
JNIEXPORT void JNICALL Java_com_example_hellohalide_CameraPreview_processFrame( JNIEnv *env, jobject obj, jbyteArray jSrc, jint j_w, jint j_h, jint j_orientation, jobject surf) { const int w = j_w, h = j_h, orientation = j_orientation; halide_start_clock(NULL); halide_set_error_handler(handler); unsigned char *src = (unsigned char *)env->GetByteArrayElements(jSrc, NULL); if (!src) { LOGD("src is null\n"); return; } LOGD("[output window size] j_w = %d, j_h = %d", j_w, j_h); LOGD("[src array length] jSrc.length = %d", env->GetArrayLength(jSrc)); ANativeWindow *win = ANativeWindow_fromSurface(env, surf); static bool first_call = true; static unsigned counter = 0; static unsigned times[16]; if (first_call) { LOGD("According to Halide, host system has %d cpus\n", halide_host_cpu_count()); LOGD("Resetting buffer format"); ANativeWindow_setBuffersGeometry(win, w, h, 0); first_call = false; for (int t = 0; t < 16; t++) times[t] = 0; } ANativeWindow_Buffer buf; ARect rect = {0, 0, w, h}; if (int err = ANativeWindow_lock(win, &buf, NULL)) { LOGD("ANativeWindow_lock failed with error code %d\n", err); return; } uint8_t *dst = (uint8_t *)buf.bits; // If we're using opencl, use the gpu backend for it. #if COMPILING_FOR_OPENCL halide_opencl_set_device_type("gpu"); #endif // Make these static so that we can reuse device allocations across frames. static halide_buffer_t srcBuf = {0}; static halide_dimension_t srcDim[2]; static halide_buffer_t dstBuf = {0}; static halide_dimension_t dstDim[2]; if (dst) { srcBuf.host = (uint8_t *)src; srcBuf.set_host_dirty(); srcBuf.dim = srcDim; srcBuf.dim[0].min = 0; srcBuf.dim[0].extent = w; srcBuf.dim[0].stride = 1; srcBuf.dim[1].min = 0; srcBuf.dim[1].extent = h; srcBuf.dim[1].stride = w; srcBuf.type = halide_type_of<uint8_t>(); if (orientation >= 180) { // Camera sensor is probably upside down (e.g. Nexus 5x) srcBuf.host += w*h-1; srcBuf.dim[0].stride = -1; srcBuf.dim[1].stride = -w; } dstBuf.host = dst; dstBuf.dim = dstDim; dstBuf.dim[0].min = 0; dstBuf.dim[0].extent = w; dstBuf.dim[0].stride = 1; dstBuf.dim[1].min = 0; dstBuf.dim[1].extent = h; dstBuf.dim[1].stride = w; dstBuf.type = halide_type_of<uint8_t>(); // Just set chroma to gray. memset(dst + w*h, 128, (w*h)/2); int64_t t1 = halide_current_time_ns(); hello(&srcBuf, &dstBuf); halide_copy_to_host(NULL, &dstBuf); int64_t t2 = halide_current_time_ns(); unsigned elapsed_us = (t2 - t1)/1000; times[counter & 15] = elapsed_us; counter++; unsigned min = times[0]; for (int i = 1; i < 16; i++) { if (times[i] < min) min = times[i]; } LOGD("Time taken: %d (%d)", elapsed_us, min); } ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); env->ReleaseByteArrayElements(jSrc, (jbyte *)src, 0); }
JNIEXPORT void JNICALL Java_com_example_hellohalide_CameraPreview_processFrame( JNIEnv *env, jobject obj, jbyteArray jSrc, jint j_w, jint j_h, jobject surf) { const int w = j_w, h = j_h; halide_set_error_handler(handler); unsigned char *src = (unsigned char *)env->GetByteArrayElements(jSrc, NULL); if (!src) { LOGD("src is null\n"); return; } ANativeWindow *win = ANativeWindow_fromSurface(env, surf); ANativeWindow_acquire(win); static bool first_call = true; static unsigned counter = 0; static unsigned times[16]; if (first_call) { LOGD("According to Halide, host system has %d cpus\n", halide_host_cpu_count()); LOGD("Resetting buffer format"); ANativeWindow_setBuffersGeometry(win, w, h, 0); first_call = false; for (int t = 0; t < 16; t++) times[t] = 0; } ANativeWindow_Buffer buf; ARect rect = {0, 0, w, h}; if (int err = ANativeWindow_lock(win, &buf, NULL)) { LOGD("ANativeWindow_lock failed with error code %d\n", err); return; } uint8_t *dst = (uint8_t *)buf.bits; // If we're using opencl, use the gpu backend for it. setenv("HL_OCL_DEVICE", "gpu", 1); // Make these static so that we can reuse device allocations across frames. static buffer_t srcBuf = {0}; static buffer_t dstBuf = {0}; if (dst) { srcBuf.host = (uint8_t *)src; srcBuf.host_dirty = true; srcBuf.extent[0] = w; srcBuf.extent[1] = h; srcBuf.extent[2] = 0; srcBuf.extent[3] = 0; srcBuf.stride[0] = 1; srcBuf.stride[1] = w; srcBuf.min[0] = 0; srcBuf.min[1] = 0; srcBuf.elem_size = 1; dstBuf.host = dst; dstBuf.extent[0] = w; dstBuf.extent[1] = h; dstBuf.extent[2] = 0; dstBuf.extent[3] = 0; dstBuf.stride[0] = 1; dstBuf.stride[1] = w; dstBuf.min[0] = 0; dstBuf.min[1] = 0; dstBuf.elem_size = 1; // Just copy over chrominance untouched memcpy(dst + w*h, src + w*h, (w*h)/2); int64_t t1 = halide_current_time_ns(); halide(&srcBuf, &dstBuf); if (dstBuf.dev) { halide_copy_to_host(NULL, &dstBuf); } int64_t t2 = halide_current_time_ns(); unsigned elapsed_us = (t2 - t1)/1000; times[counter & 15] = elapsed_us; counter++; unsigned min = times[0]; for (int i = 1; i < 16; i++) { if (times[i] < min) min = times[i]; } LOGD("Time taken: %d (%d)", elapsed_us, min); } ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); env->ReleaseByteArrayElements(jSrc, (jbyte *)src, 0); }
bool CEGLManager::generateSurface() { if (EglDisplay == EGL_NO_DISPLAY) return false; if (EglSurface != EGL_NO_SURFACE) return true; // We should assign new WindowID on platforms, where WindowID may change at runtime, // at this time only Android support this feature. // this needs an update method instead! #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) EglWindow = (ANativeWindow*)Data.OGLESAndroid.Window; #endif EGLint EglOpenGLBIT = 0; // We need proper OpenGL BIT. switch (Params.DriverType) { case EDT_OGLES1: EglOpenGLBIT = EGL_OPENGL_ES_BIT; break; case EDT_OGLES2: EglOpenGLBIT = EGL_OPENGL_ES2_BIT; break; default: break; } EGLint Attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, Params.WithAlphaChannel ? 1:0, EGL_BUFFER_SIZE, Params.Bits, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_DEPTH_SIZE, Params.ZBufferBits, EGL_STENCIL_SIZE, Params.Stencilbuffer, EGL_SAMPLE_BUFFERS, Params.AntiAlias ? 1:0, EGL_SAMPLES, Params.AntiAlias, #ifdef EGL_VERSION_1_3 EGL_RENDERABLE_TYPE, EglOpenGLBIT, #endif EGL_NONE, 0 }; EglConfig = 0; EGLint NumConfigs = 0; u32 Steps = 5; // Choose the best EGL config. while (!eglChooseConfig(EglDisplay, Attribs, &EglConfig, 1, &NumConfigs) || !NumConfigs) { switch (Steps) { case 5: // samples if (Attribs[19] > 2) --Attribs[19]; else { Attribs[17] = 0; Attribs[19] = 0; --Steps; } break; case 4: // alpha if (Attribs[7]) { Attribs[7] = 0; if (Params.AntiAlias) { Attribs[17] = 1; Attribs[19] = Params.AntiAlias; Steps = 5; } } else --Steps; break; case 3: // stencil if (Attribs[15]) { Attribs[15] = 0; if (Params.AntiAlias) { Attribs[17] = 1; Attribs[19] = Params.AntiAlias; Steps = 5; } } else --Steps; break; case 2: // depth size if (Attribs[13] > 16) { Attribs[13] -= 8; } else --Steps; break; case 1: // buffer size if (Attribs[9] > 16) { Attribs[9] -= 8; } else --Steps; break; default: os::Printer::log("Could not get config for EGL display."); return false; } } if (Params.AntiAlias && !Attribs[17]) os::Printer::log("No multisampling."); if (Params.WithAlphaChannel && !Attribs[7]) os::Printer::log("No alpha."); if (Params.Stencilbuffer && !Attribs[15]) os::Printer::log("No stencil buffer."); if (Params.ZBufferBits > Attribs[13]) os::Printer::log("No full depth buffer."); if (Params.Bits > Attribs[9]) os::Printer::log("No full color buffer."); #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) EGLint Format = 0; eglGetConfigAttrib(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &Format); ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, Format); #endif // Now we are able to create EGL surface. EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, 0); if (EGL_NO_SURFACE == EglSurface) EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, 0, 0); if (EGL_NO_SURFACE == EglSurface) os::Printer::log("Could not create EGL surface."); #ifdef EGL_VERSION_1_2 if (MinorVersion > 1) eglBindAPI(EGL_OPENGL_ES_API); #endif if (Params.Vsync) eglSwapInterval(EglDisplay, 1); return true; }
int init_display(ANativeWindow *window) { // initialize OpenGL ES and EGL /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint w, h, dummy, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(display, attribs, &config, 1, &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(window, 0, 0, format); surface = eglCreateWindowSurface(display, config, window, NULL); context = eglCreateContext(display, config, NULL, NULL); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { // LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); gDisplay = display; gContext = context; gSurface = surface; width = w; height = h; /* // Initialize GL state. // Set the background color to black ( rgba ). glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Enable Smooth Shading, default not really needed. glShadeModel(GL10.GL_SMOOTH); // Depth buffer setup. glClearDepthf(1.0f); // Enables depth testing. glEnable(GL10.GL_DEPTH_TEST); // The type of depth testing to do. glDepthFunc(GL10.GL_LEQUAL); // Really nice perspective calculations. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); */ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glDisable(GL_DEPTH_TEST); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return 0; }
int GraphicsService::create() { EGLint format, numConfigs, errorResult; EGLConfig config; const EGLint configAttr[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (display_ == EGL_NO_DISPLAY) { Log::error("Fail to get default Display"); stop(); return -1; } if (!eglInitialize(display_, 0, 0)) { Log::error("Fail initialize display"); stop(); return -1; } if (!eglChooseConfig(display_, configAttr, &config, 1, &numConfigs) || (numConfigs <= 0)) { Log::error("Fail to choose a config"); stop(); return -1; } if (!eglGetConfigAttrib(display_, config, EGL_NATIVE_VISUAL_ID, &format)) { Log::error("Fail to config android display with EGL"); stop(); return -1; } //change window buffers ANativeWindow_setBuffersGeometry(application_->window, 0, 0, format); // Create display surface. surface_ = eglCreateWindowSurface(display_, config, application_->window, 0); if (surface_ == EGL_NO_SURFACE) { Log::error("Fail create surface"); stop(); return -1; } const EGLint contextAttr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE}; context_ = eglCreateContext(display_, config, EGL_NO_CONTEXT, contextAttr); if (context_ == EGL_NO_CONTEXT) { Log::error("failed to create context"); stop(); return -1; } // Activate display surface. if (!eglMakeCurrent(display_, surface_, surface_, context_) || !eglQuerySurface(display_, surface_, EGL_WIDTH, &width_) || !eglQuerySurface(display_, surface_, EGL_HEIGHT, &height_) || (width_ <= 0) || (height_ <= 0)) { Log::error("Fail to make current surface"); stop(); return -1; } glViewport(0, 0, width_, height_); return 0; }
static CoglBool _cogl_winsys_egl_context_created (CoglDisplay *display, CoglError **error) { CoglRenderer *renderer = display->renderer; CoglRendererEGL *egl_renderer = renderer->winsys; CoglDisplayEGL *egl_display = display->winsys; CoglDisplayAndroid *android_display = egl_display->platform; const char *error_message; EGLint format; if (android_native_window == NULL) { error_message = "No ANativeWindow window specified with " "cogl_android_set_native_window()"; goto fail; } /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry (). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib (egl_renderer->edpy, egl_display->egl_config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry (android_native_window, 0, 0, format); egl_display->egl_surface = eglCreateWindowSurface (egl_renderer->edpy, egl_display->egl_config, (NativeWindowType) android_native_window, NULL); if (egl_display->egl_surface == EGL_NO_SURFACE) { error_message = "Unable to create EGL window surface"; goto fail; } if (!_cogl_winsys_egl_make_current (display, egl_display->egl_surface, egl_display->egl_surface, egl_display->egl_context)) { error_message = "Unable to eglMakeCurrent with egl surface"; goto fail; } eglQuerySurface (egl_renderer->edpy, egl_display->egl_surface, EGL_WIDTH, &android_display->egl_surface_width); eglQuerySurface (egl_renderer->edpy, egl_display->egl_surface, EGL_HEIGHT, &android_display->egl_surface_height); return TRUE; fail: _cogl_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT, "%s", error_message); return FALSE; }
Status AndroidEventLoop::InitializeDisplay() { int mWidth, mHeight; EGLint lFormat, lNumConfigs, lErrorResult; EGLConfig lConfig; const EGLint lAttributes[] = { EGL_RENDERABLE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_NONE }; const EGLint lContextAttrib[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; // Retrieves a display connection and initializes it. mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (mDisplay == EGL_NO_DISPLAY) { LOGE("EGL_NO_DISPLAY"); goto ERROR; } if (!eglInitialize(mDisplay, NULL, NULL)) { LOGE("Unable to initialize display"); goto ERROR; } // Selects the first OpenGL configuration found. if(!eglChooseConfig(mDisplay, lAttributes, &lConfig, 1, &lNumConfigs) || (lNumConfigs <= 0)) { LOGE("Unable to select display configuration"); goto ERROR; } // Reconfigures the Android window with the EGL format. if (!eglGetConfigAttrib(mDisplay, lConfig, EGL_NATIVE_VISUAL_ID, &lFormat)) { LOGE("Unable to configure window format"); goto ERROR; } ANativeWindow_setBuffersGeometry(Global::pAndroidApp->window, 0, 0, lFormat); // Creates the display surface. mSurface = eglCreateWindowSurface(mDisplay, lConfig, Global::pAndroidApp->window, NULL); if (mSurface == EGL_NO_SURFACE) { LOGE("EGL_NO_SURFACE"); goto ERROR; } mContext = eglCreateContext(mDisplay, lConfig, EGL_NO_CONTEXT, lContextAttrib); if (mContext == EGL_NO_CONTEXT) { LOGE("EGL_NO_CONTEXT"); goto ERROR; } // Activates the display surface. LOGD("Activating the display."); if (!eglMakeCurrent(mDisplay, mSurface, mSurface, mContext) || !eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mWidth) || !eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mHeight) || (mWidth <= 0) || (mHeight <= 0)) { LOGE("Unable to activate display"); goto ERROR; } // Displays information about OpenGL. LOGI("Starting GraphicsService"); LOGI("Version : %s", glGetString(GL_VERSION)); LOGI("Vendor : %s", glGetString(GL_VENDOR)); LOGI("Renderer : %s", glGetString(GL_RENDERER)); LOGI("Viewport : %d x %d", mWidth, mHeight); Render::SetScreenSize(mWidth,mHeight); return STATUS_OK; ERROR: LOGE("Error while starting GraphicsService"); DestroyDisplay(); return STATUS_KO; }
static EGLBoolean IJK_EGL_makeCurrent(IJK_EGL* egl, EGLNativeWindowType window) { if (window && window == egl->window && egl->display && egl->surface && egl->context) { if (!eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context)) { ALOGE("[EGL] elgMakeCurrent() failed (cached)\n"); return EGL_FALSE; } return EGL_TRUE; } IJK_EGL_terminate(egl); egl->window = window; if (!window) return EGL_FALSE; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (display == EGL_NO_DISPLAY) { ALOGE("[EGL] eglGetDisplay failed\n"); return EGL_FALSE; } EGLint major, minor; if (!eglInitialize(display, &major, &minor)) { ALOGE("[EGL] eglInitialize failed\n"); return EGL_FALSE; } ALOGI("[EGL] eglInitialize %d.%d\n", (int)major, (int)minor); static const EGLint configAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; static const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLConfig config; EGLint numConfig; if (!eglChooseConfig(display, configAttribs, &config, 1, &numConfig)) { ALOGE("[EGL] eglChooseConfig failed\n"); eglTerminate(display); return EGL_FALSE; } #ifdef __ANDROID__ { EGLint native_visual_id = 0; if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) { ALOGE("[EGL] eglGetConfigAttrib() returned error %d", eglGetError()); eglTerminate(display); return EGL_FALSE; } int32_t width = ANativeWindow_getWidth(window); int32_t height = ANativeWindow_getWidth(window); ALOGI("[EGL] ANativeWindow_setBuffersGeometry(f=%d);", native_visual_id); int ret = ANativeWindow_setBuffersGeometry(window, width, height, native_visual_id); if (ret) { ALOGE("[EGL] ANativeWindow_setBuffersGeometry(format) returned error %d", ret); eglTerminate(display); return EGL_FALSE; } } #endif EGLSurface surface = eglCreateWindowSurface(display, config, window, NULL); if (surface == EGL_NO_SURFACE) { ALOGE("[EGL] eglCreateWindowSurface failed\n"); eglTerminate(display); return EGL_FALSE; } EGLSurface context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); if (context == EGL_NO_CONTEXT) { ALOGE("[EGL] eglCreateContext failed\n"); eglDestroySurface(display, surface); eglTerminate(display); return EGL_FALSE; } if (!eglMakeCurrent(display, surface, surface, context)) { ALOGE("[EGL] elgMakeCurrent() failed (new)\n"); eglDestroyContext(display, context); eglDestroySurface(display, surface); eglTerminate(display); return EGL_FALSE; } #if 0 #if defined(__ANDROID__) { const char *extensions = (const char *) glGetString(GL_EXTENSIONS); if (extensions) { char *dup_extensions = strdup(extensions); if (dup_extensions) { char *brk = NULL; char *ext = strtok_r(dup_extensions, " ", &brk); while (ext) { if (0 == strcmp(ext, "GL_EXT_texture_rg")) egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg] = 1; ext = strtok_r(NULL, " ", &brk); } free(dup_extensions); } } } #elif defined(__APPLE__) egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg] = 1; #endif ALOGI("[EGL] GLES2 extensions begin:\n"); ALOGI("[EGL] GL_EXT_texture_rg: %d\n", egl->gles2_extensions[IJK_GLES2__GL_EXT_texture_rg]); ALOGI("[EGL] GLES2 extensions end.\n"); #endif IJK_GLES2_Renderer_setupGLES(); egl->context = context; egl->surface = surface; egl->display = display; return EGL_TRUE; }
HWND gkDeviceRenderContext::initDevice(ISystemInitInfo& sii) { ////////////////////////////////////////////////////////////////////////// // native create ogles2 device int bDone; m_NDT = 0;//(EGLNativeDisplayType)OsGetNativeDisplayType(); m_NPT = 0;//(EGLNativePixmapType) OsGetNativePixmapType(); m_NWT = (EGLNativeWindowType)(sii.nativeWindowPTR);//(EGLNativeWindowType) OsGetNativeWindowType(); m_EGLContext = 0; do { bDone = true; m_EGLDisplay = eglGetDisplay(m_NDT); if(m_EGLDisplay == EGL_NO_DISPLAY) { #if defined(BUILD_OGLES2) || defined(BUILD_OVG) || defined(BUILD_OGLES3) m_EGLDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); #else m_EGLDisplay = eglGetDisplay((NativeDisplayType)EGL_DEFAULT_DISPLAY); #endif } if(!eglInitialize(m_EGLDisplay, &m_MajorVersion, &m_MinorVersion)) { gkLogError(_T("RendererGLES2::eglInitialize failed.")); return 0; } gkLogMessage(_T("RendererGLES2::eglInitialize success.")); // Check Extension avaliablility after EGL initialization if (m_MajorVersion > 1 || (m_MajorVersion == 1 && m_MinorVersion >= 1)) { m_bPowerManagementSupported = true; } else { m_bPowerManagementSupported = false; } do { { //#if defined EGL_VERSION_1_3 && defined GL_ES_VERSION_2_0 if(!eglBindAPI(EGL_OPENGL_ES_API)) { gkLogError(_T("RendererGLES2::Failed to bind OpenGL ES API\n")); return 0; } //#endif } gkLogMessage(_T("RendererGLES2::eglBindAPI success.")); // Find an EGL config m_EGLConfig = SelectEGLConfiguration(); eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_CONFIG_ID, &m_iConfig); // Destroy the context if we already created one if (m_EGLContext) { eglDestroyContext(m_EGLDisplay, m_EGLContext); } // Attempt to create a context EGLint ai32ContextAttribs[32]; int i = 0; //#if defined(EGL_VERSION_1_3) && defined(GL_ES_VERSION_2_0) ai32ContextAttribs[i++] = EGL_CONTEXT_CLIENT_VERSION; ai32ContextAttribs[i++] = 2; //#endif // #if defined(BUILD_OGLES2) || defined(BUILD_OGLES) || defined(BUILD_OGLES3) // if(PVRShellIsExtensionSupported(m_EGLDisplay,"EGL_IMG_context_priority")) // { // ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG; // switch(m_pShell->PVRShellGet(prefPriority)) // { // case 0: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_LOW_IMG; break; // case 1: ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; break; // default:ai32ContextAttribs[i++] = EGL_CONTEXT_PRIORITY_HIGH_IMG; // } // } // #endif ai32ContextAttribs[i] = EGL_NONE; m_EGLContext = eglCreateContext(m_EGLDisplay, m_EGLConfig, NULL, ai32ContextAttribs); if(m_EGLContext == EGL_NO_CONTEXT) { if(m_iRequestedConfig > 0) { // We failed to create a context gkLogError(_T("RendererGLES2::eglCreateContext failed.")); return 0; } } gkLogMessage(_T("RendererGLES2::eglCreateContext retry.")); } while(m_EGLContext == EGL_NO_CONTEXT); EGLint attrib_list[16]; int i = 0; // #if defined(EGL_VERSION_1_2) // if(m_pShell->m_pShellData->bNeedAlphaFormatPre) // The default is EGL_ALPHA_FORMAT_NONPRE // { // attrib_list[i++] = EGL_ALPHA_FORMAT; // attrib_list[i++] = EGL_ALPHA_FORMAT_PRE; // } // #endif // Terminate the attribute list with EGL_NONE attrib_list[i] = EGL_NONE; // if(m_pShell->m_pShellData->bNeedPixmap) // { // m_pShell->PVRShellOutputDebug("InitAPI() Using pixmaps, about to create egl surface\n"); // m_EGLWindow = eglCreatePixmapSurface(m_EGLDisplay, m_EGLConfig, m_NPT, attrib_list); // } // else { //#if defined(ANDROID) EGLint visualID; eglGetConfigAttrib(m_EGLDisplay, m_EGLConfig, EGL_NATIVE_VISUAL_ID, &visualID); gkLogMessage(_T("RendererGLES2::eglGetConfigAttrib success.")); // Change the format of our window to match our config ANativeWindow_setBuffersGeometry(m_NWT, 0, 0, visualID); gkLogMessage(_T("RendererGLES2::ANativeWindow_setBuffersGeometry success.")); //#endif m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, m_NWT, attrib_list); // If we have failed to create a surface then try using Null if(m_EGLWindow == EGL_NO_SURFACE) { m_EGLWindow = eglCreateWindowSurface(m_EGLDisplay, m_EGLConfig, NULL, attrib_list); } } if (m_EGLWindow == EGL_NO_SURFACE) { gkLogError(_T("RendererGLES2::eglCreateWindowSurface failed.")); return false; } if (!eglMakeCurrent(m_EGLDisplay, m_EGLWindow, m_EGLWindow, m_EGLContext)) { #ifdef EGL_VERSION_1_3 if((eglGetError() == EGL_CONTEXT_LOST)) #else if((eglGetError() == EGL_CONTEXT_LOST_IMG) && m_bPowerManagementSupported) #endif { bDone = false; } else { gkLogError(_T("RendererGLES2::eglMakeCurrent failed.")); return false; } } } while(!bDone); /* Get correct screen width and height and save them into m_pShell->m_pShellData->nShellDimX and m_pShell->m_pShellData->nShellDimY */ EGLint screenWidth; EGLint screenHeight; eglQuerySurface(m_EGLDisplay, m_EGLWindow, EGL_WIDTH, &screenWidth); eglQuerySurface(m_EGLDisplay, m_EGLWindow, EGL_HEIGHT, &screenHeight); getRenderer()->SetCurrContent(0,0,0,screenWidth, screenHeight); glViewport(0,0,screenWidth, screenHeight); gkLogMessage(_T("RendererGLES2::CreateDevice Success! %d x %d"), screenWidth, screenHeight); eglSwapInterval(m_EGLDisplay, 0); sii.fWidth = screenWidth; sii.fHeight = screenHeight; /* Done - activate requested features */ //ApiActivatePreferences(); //glViewport(0,0,sii.fWidth, sii.fHeight); return (HWND)1; }
JNIEXPORT bool JNICALL Java_com_example_helloandroidcamera2_JNIUtils_edgeDetect( JNIEnv *env, jobject obj, jint srcWidth, jint srcHeight, jobject srcLumaByteBuffer, jint srcLumaRowStrideBytes, jobject dstSurface) { uint8_t *srcLumaPtr = reinterpret_cast<uint8_t *>( env->GetDirectBufferAddress(srcLumaByteBuffer)); if (srcLumaPtr == NULL) { return false; } ANativeWindow *win = ANativeWindow_fromSurface(env, dstSurface); ANativeWindow_acquire(win); ANativeWindow_Buffer buf; if (int err = ANativeWindow_lock(win, &buf, NULL)) { LOGE("ANativeWindow_lock failed with error code %d\n", err); ANativeWindow_release(win); return false; } ANativeWindow_setBuffersGeometry(win, srcWidth, srcHeight, 0 /*format unchanged*/); uint8_t *dstLumaPtr = reinterpret_cast<uint8_t *>(buf.bits); if (dstLumaPtr == NULL) { ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return false; } if (buf.format != IMAGE_FORMAT_YV12) { LOGE("ANativeWindow buffer locked but its format was not YV12."); ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return false; } if (!checkBufferSizesMatch(srcWidth, srcHeight, &buf)) { LOGE("ANativeWindow buffer locked but its size was %d x %d, expected " "%d x %d", buf.width, buf.height, srcWidth, srcHeight); ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return false; } uint32_t dstLumaSizeBytes = buf.stride * buf.height; uint32_t dstChromaRowStrideBytes = ALIGN(buf.stride / 2, 16); // Size of one chroma plane. uint32_t dstChromaSizeBytes = dstChromaRowStrideBytes * buf.height / 2; uint8_t *dstChromaVPtr = dstLumaPtr + dstLumaSizeBytes; uint8_t *dstChromaUPtr = dstLumaPtr + dstLumaSizeBytes + dstChromaSizeBytes; // Make these static so that we can reuse device allocations across frames. // It doesn't matter now, but useful for GPU backends. static buffer_t srcBuf = { 0 }; static buffer_t dstBuf = { 0 }; static buffer_t dstChromaBuf = { 0 }; srcBuf.host = srcLumaPtr; srcBuf.host_dirty = true; srcBuf.extent[0] = srcWidth; srcBuf.extent[1] = srcHeight; srcBuf.extent[2] = 0; srcBuf.extent[3] = 0; srcBuf.stride[0] = 1; srcBuf.stride[1] = srcLumaRowStrideBytes; srcBuf.min[0] = 0; srcBuf.min[1] = 0; srcBuf.elem_size = 1; dstBuf.host = dstLumaPtr; dstBuf.extent[0] = buf.width; // src and dst width/height actually match. dstBuf.extent[1] = buf.height; dstBuf.extent[2] = 0; dstBuf.extent[3] = 0; dstBuf.stride[0] = 1; dstBuf.stride[1] = buf.stride; // src and dst strides actually match. dstBuf.min[0] = 0; dstBuf.min[1] = 0; dstBuf.elem_size = 1; static bool first_call = true; static unsigned counter = 0; static unsigned times[16]; if (first_call) { LOGD("According to Halide, host system has %d cpus\n", halide_host_cpu_count()); first_call = false; for (int t = 0; t < 16; t++) { times[t] = 0; } } // Set chrominance to 128 to appear grayscale. // The dst chroma is guaranteed to be tightly packed since it's YV12. memset(dstChromaVPtr, 128, dstChromaSizeBytes * 2); int64_t t1 = halide_current_time_ns(); int err = edge_detect(&srcBuf, &dstBuf); if (err != halide_error_code_success) { LOGE("edge_detect failed with error code: %d", err); } int64_t t2 = halide_current_time_ns(); unsigned elapsed_us = (t2 - t1) / 1000; times[counter & 15] = elapsed_us; counter++; unsigned min = times[0]; for (int i = 1; i < 16; i++) { if (times[i] < min) { min = times[i]; } } LOGD("Time taken: %d us (minimum: %d us)", elapsed_us, min); ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return (err != halide_error_code_success); }
unsigned int Renderer::Initialize() { if (m_initialized) return CS_ERR_NONE; unsigned int err = CS_ERR_NONE; #ifdef PLATFORM_WINDOWS if (!glfwInit()) return CS_ERR_WINDOW_FAILED; glfwWindowHint(GLFW_SAMPLES, CSSET_GLFW_SAMPLES_VALUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); Engine* engine = System::GetInstance()->GetEngineData(); m_window = glfwCreateWindow(CSSET_WINDOW_WIDTH_DEFAULT, CSSET_WINDOW_HEIGHT_DEFAULT, CSSET_WINDOW_NAME, nullptr, nullptr); engine->width = CSSET_WINDOW_WIDTH_DEFAULT; engine->height = CSSET_WINDOW_HEIGHT_DEFAULT; m_screenRatio = (float)engine->height / (float)engine->width; if (m_window == nullptr) { glfwTerminate(); return CS_ERR_WINDOW_FAILED; } glfwMakeContextCurrent(m_window); glewExperimental = true; if (glewInit() != GLEW_OK) return CS_ERR_WINDOW_FAILED; glfwSwapInterval(CSSET_VSYNC_ENALBED); #else // initialize OpenGL ES and EGL EGLint w, h, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; Engine* engine = System::GetInstance()->GetEngineData(); EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(display, attribs, &config, 1, &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); context = eglCreateContext(display, config, NULL, attribsContext); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); m_screenRatio = (float)w / (float)h; engine->display = display; engine->context = context; engine->surface = surface; engine->width = w; engine->height = h; eglSwapInterval(engine->display, CSSET_VSYNC_ENALBED); AConfiguration_setNavigation(engine->app->config, ACONFIGURATION_NAVHIDDEN_YES); #endif // Shaders Loading m_basicShader = ResourceManager::GetInstance()->LoadShader(&SN_BASIC); m_wireframeShader = ResourceManager::GetInstance()->LoadShader(&SN_WIREFRAME); m_basicWireframeShader = ResourceManager::GetInstance()->LoadShader(&SN_BASICWIREFRAME); m_fontShader = ResourceManager::GetInstance()->LoadShader(&SN_FONT); m_shaderID = m_basicShader; m_mode = BASIC; //////////// options go here glClearColor(CSSET_CLEAR_COLORS[0], CSSET_CLEAR_COLORS[1], CSSET_CLEAR_COLORS[2], CSSET_CLEAR_COLORS[3]); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); if (CSSET_BACKFACE_CULLING) { glEnable(GL_CULL_FACE); } glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_DITHER); //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); /* glEnable(GL_STENCIL); glStencilFunc(GL_LEQUAL, 0, 0xFF); glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ///////////////////////// m_initialized = true; return err; }
JNIEXPORT bool JNICALL Java_com_example_helloandroidcamera2_JNIUtils_blit( JNIEnv *env, jobject obj, jint srcWidth, jint srcHeight, jobject srcLumaByteBuffer, jint srcLumaRowStrideBytes, jobject srcChromaUByteBuffer, jobject srcChromaVByteBuffer, jint srcChromaElementStrideBytes, jint srcChromaRowStrideBytes, jobject dstSurface) { if (srcChromaElementStrideBytes != 1 && srcChromaElementStrideBytes != 2) { return false; } uint8_t *srcLumaPtr = reinterpret_cast<uint8_t *>( env->GetDirectBufferAddress(srcLumaByteBuffer)); uint8_t *srcChromaUPtr = reinterpret_cast<uint8_t *>( env->GetDirectBufferAddress(srcChromaUByteBuffer)); uint8_t *srcChromaVPtr = reinterpret_cast<uint8_t *>( env->GetDirectBufferAddress(srcChromaVByteBuffer)); if (srcLumaPtr == nullptr || srcChromaUPtr == nullptr || srcChromaVPtr == nullptr) { return false; } // Check that if src chroma channels are interleaved if element stride is 2. // Our Halide kernel "directly deinterleaves" UVUVUVUV --> UUUU, VVVV // to handle VUVUVUVU, just swap the destination pointers. uint8_t *srcChromaUVInterleavedPtr = nullptr; bool swapDstUV; if (srcChromaElementStrideBytes == 2) { if (srcChromaVPtr - srcChromaUPtr == 1) { srcChromaUVInterleavedPtr = srcChromaUPtr; // UVUVUV... swapDstUV = false; } else if (srcChromaUPtr - srcChromaVPtr == 1) { srcChromaUVInterleavedPtr = srcChromaVPtr; // VUVUVU... swapDstUV = true; } else { // stride is 2 but the pointers are not off by 1. return false; } } ANativeWindow *win = ANativeWindow_fromSurface(env, dstSurface); ANativeWindow_acquire(win); ANativeWindow_Buffer buf; if (int err = ANativeWindow_lock(win, &buf, NULL)) { LOGE("ANativeWindow_lock failed with error code %d\n", err); ANativeWindow_release(win); return false; } ANativeWindow_setBuffersGeometry(win, srcWidth, srcHeight, 0 /*format unchanged*/); if (buf.format != IMAGE_FORMAT_YV12) { LOGE("ANativeWindow buffer locked but its format was not YV12."); ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return false; } if (!checkBufferSizesMatch(srcWidth, srcHeight, &buf)) { LOGE("ANativeWindow buffer locked but its size was %d x %d, expected " "%d x %d", buf.width, buf.height, srcWidth, srcHeight); ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return false; } int32_t srcChromaWidth = srcWidth / 2; int32_t srcChromaHeight = srcHeight / 2; // This is guaranteed by the YV12 format, see android.graphics.ImageFormat. uint8_t *dstLumaPtr = reinterpret_cast<uint8_t *>(buf.bits); uint32_t dstLumaRowStrideBytes = buf.stride; uint32_t dstLumaSizeBytes = dstLumaRowStrideBytes * buf.height; uint32_t dstChromaRowStrideBytes = ALIGN(buf.stride / 2, 16); // Size of one chroma plane. uint32_t dstChromaSizeBytes = dstChromaRowStrideBytes * buf.height / 2; // Yes, V is actually first. uint8_t *dstChromaVPtr = dstLumaPtr + dstLumaSizeBytes; uint8_t *dstChromaUPtr = dstLumaPtr + dstLumaSizeBytes + dstChromaSizeBytes; // Copy over the luma channel. // If strides match, then it's a single copy. if (srcLumaRowStrideBytes == dstLumaRowStrideBytes) { memcpy(dstLumaPtr, srcLumaPtr, dstLumaSizeBytes); } else { // Else, copy row by row. for (int y = 0; y < srcHeight; y++) { uint8_t *srcLumaRow = srcLumaPtr + y * srcLumaRowStrideBytes; uint8_t *dstLumaRow = dstLumaPtr + y * dstLumaRowStrideBytes; memcpy(dstLumaRow, srcLumaRow, srcLumaRowStrideBytes); } } bool succeeded; // Handle the chroma channels. // If they are not interleaved, then use memcpy. // Otherwise, use Halide to deinterleave. if (srcChromaElementStrideBytes == 1) { // If strides match, then it's a single copy per channel. if (srcChromaRowStrideBytes == dstChromaRowStrideBytes) { memcpy(dstChromaUPtr, srcChromaUPtr, dstChromaSizeBytes); memcpy(dstChromaVPtr, srcChromaVPtr, dstChromaSizeBytes); } else { // Else, copy row by row. for (int y = 0; y < srcHeight; y++) { uint8_t *srcChromaURow = srcChromaUPtr + y * srcChromaRowStrideBytes; uint8_t *dstChromaURow = dstChromaUPtr + y * dstChromaRowStrideBytes; memcpy(dstChromaURow, srcChromaURow, srcChromaRowStrideBytes); } for (int y = 0; y < srcHeight; y++) { uint8_t *srcChromaVRow = srcChromaVPtr + y * srcChromaRowStrideBytes; uint8_t *dstChromaVRow = dstChromaVPtr + y * dstChromaRowStrideBytes; memcpy(dstChromaVRow, srcChromaVRow, srcChromaRowStrideBytes); } } succeeded = true; } else { // Make these static so that we can reuse device allocations across frames. // It doesn't matter now, but useful for GPU backends. static buffer_t srcBuf = { 0 }; static buffer_t dstBuf0 = { 0 }; static buffer_t dstBuf1 = { 0 }; srcBuf.host = srcChromaUVInterleavedPtr; srcBuf.host_dirty = true; srcBuf.extent[0] = 2 * srcChromaWidth; // src is interleaved. srcBuf.extent[1] = srcChromaHeight; srcBuf.extent[2] = 0; srcBuf.extent[3] = 0; srcBuf.stride[0] = 1; srcBuf.stride[1] = 2 * srcChromaWidth; srcBuf.min[0] = 0; srcBuf.min[1] = 0; srcBuf.elem_size = 1; dstBuf0.host = swapDstUV ? dstChromaVPtr : dstChromaUPtr; dstBuf0.extent[0] = srcChromaWidth; // src and dst width and height match. dstBuf0.extent[1] = srcChromaHeight; dstBuf0.extent[2] = 0; dstBuf0.extent[3] = 0; dstBuf0.stride[0] = 1; dstBuf0.stride[1] = dstChromaRowStrideBytes; // Halide stride in pixels but pixel size is 1 byte. dstBuf0.min[0] = 0; dstBuf0.min[1] = 0; dstBuf0.elem_size = 1; dstBuf1.host = swapDstUV ? dstChromaUPtr : dstChromaVPtr; dstBuf1.extent[0] = srcChromaWidth; // src and dst width and height match. dstBuf1.extent[1] = srcChromaHeight; dstBuf1.extent[2] = 0; dstBuf1.extent[3] = 0; dstBuf1.stride[0] = 1; dstBuf1.stride[1] = dstChromaRowStrideBytes; // Halide stride in pixels but pixel size is 1 byte. dstBuf1.min[0] = 0; dstBuf1.min[1] = 0; dstBuf1.elem_size = 1; // Use Halide to deinterleave the chroma channels. int err = deinterleave(&srcBuf, &dstBuf0, &dstBuf1); if (err != halide_error_code_success) { LOGE("deinterleave failed with error code: %d", err); } succeeded = (err != halide_error_code_success); } ANativeWindow_unlockAndPost(win); ANativeWindow_release(win); return succeeded; }
void THEGLInit(THApplicaation* state) { eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint eglMajor,eglMinor; eglInitialize(eglDisplay, &eglMajor,&eglMinor); THLog("EGL Initialization : %d.%d",eglMajor,eglMinor); const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, #if USE_DEPTH_BUFFER==1 EGL_DEPTH_SIZE,8, #endif EGL_NONE }; EGLint numConfigs; EGLConfig config; eglChooseConfig(eglDisplay, attribs, &config, 1, &numConfigs); #if THPLATFORM==THPLATFORM_ANDROID EGLint format; eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(state->window, 0, 0, format); eglSurface = eglCreateWindowSurface(eglDisplay, config, (EGLNativeWindowType)(state->window), NULL); #elif THPLATFORM==THPLATFORM_WINDOWS eglSurface = eglCreateWindowSurface(eglDisplay, config, *state, NULL); if(eglSurface == EGL_NO_SURFACE) { eglGetError(); // Clear error eglSurface = eglCreateWindowSurface(eglDisplay, config, NULL, NULL); } #endif const EGLint attrib_list[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; eglContext = eglCreateContext(eglDisplay, config, NULL, attrib_list); #if THPLATFORM==THPLATFORM_WINDOWS eglBindAPI(EGL_OPENGL_ES_API); #endif if (eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) == EGL_FALSE) { THError("Unable to eglMakeCurrent"); assert(0); return; } EGLint sw,sh; eglQuerySurface(eglDisplay, eglSurface, EGL_WIDTH, &sw); eglQuerySurface(eglDisplay, eglSurface, EGL_HEIGHT, &sh); windowWidthi=sw; windowHeighti=sh; windowSize.Set((float)sw,(float)sh); gameScale.Set(0.0f,0.0f); }
static bool android_gfx_ctx_init(void *data) { int var; EGLint num_config, egl_version_major, egl_version_minor; EGLint format; EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, g_es3 ? 3 : 2, EGL_NONE }; const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE }; driver_t *driver = driver_get_ptr(); gfx_ctx_android_data_t *android = NULL; struct android_app *android_app = (struct android_app*)g_android; if (!android_app) return false; android = (gfx_ctx_android_data_t*) calloc(1, sizeof(gfx_ctx_android_data_t)); if (!android) return false; RARCH_LOG("Android EGL: GLES version = %d.\n", g_es3 ? 3 : 2); android->g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (!android->g_egl_dpy) { RARCH_ERR("[Android/EGL]: Couldn't get EGL display.\n"); goto error; } if (!eglInitialize(android->g_egl_dpy, &egl_version_major, &egl_version_minor)) goto error; RARCH_LOG("[ANDROID/EGL]: EGL version: %d.%d\n", egl_version_major, egl_version_minor); if (!eglChooseConfig(android->g_egl_dpy, attribs, &android->g_egl_config, 1, &num_config)) goto error; var = eglGetConfigAttrib(android->g_egl_dpy, android->g_egl_config, EGL_NATIVE_VISUAL_ID, &format); if (!var) { RARCH_ERR("eglGetConfigAttrib failed: %d.\n", var); goto error; } ANativeWindow_setBuffersGeometry(android_app->window, 0, 0, format); android->g_egl_ctx = eglCreateContext(android->g_egl_dpy, android->g_egl_config, EGL_NO_CONTEXT, context_attributes); if (android->g_egl_ctx == EGL_NO_CONTEXT) goto error; if (android->g_use_hw_ctx) { android->g_egl_hw_ctx = eglCreateContext(android->g_egl_dpy, android->g_egl_config, android->g_egl_ctx, context_attributes); RARCH_LOG("[Android/EGL]: Created shared context: %p.\n", (void*)android->g_egl_hw_ctx); if (android->g_egl_hw_ctx == EGL_NO_CONTEXT) goto error; } android->g_egl_surf = eglCreateWindowSurface(android->g_egl_dpy, android->g_egl_config, android_app->window, 0); if (!android->g_egl_surf) goto error; if (!eglMakeCurrent(android->g_egl_dpy, android->g_egl_surf, android->g_egl_surf, android->g_egl_ctx)) goto error; driver->video_context_data = android; return true; error: android_gfx_ctx_destroy_resources(android); if (android) free(android); return false; }
void EGLRenderer::Init() { LOGD("EGLRenderer Init() begin"); if (m_pState->window == NULL) { LOGD("app_state->window are null, EGLRenderer can not Init() now"); return; } LOGD("Init EGL begin"); if (m_display == EGL_NO_DISPLAY) { m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); assert(m_display!= EGL_NO_DISPLAY); EGLint majorEGLVersion, minorEGLVersion; EGLBoolean res = eglInitialize(m_display, &majorEGLVersion, &minorEGLVersion); assert(res); LOGD("EGL Major Version is %d", majorEGLVersion); LOGD("EGL Minor Version is %d", minorEGLVersion); EGLint OGLESVersionToken; #if defined(USE_GLES3) #if 0 OGLESVersionToken = EGL_OPENGL_ES3_BIT_KHR; // Don't use EGL_OPENGL_ES3_BIT_KHR, since we don't have corresponding header files for EGL 1.4 #endif // Use a magic number which comes from the spec of OGL ES 3.0 static const unsigned int EGL_OPENGL_ES3_BIT_KHR = 0x0040; OGLESVersionToken = EGL_OPENGL_ES3_BIT_KHR; #elif defined(USE_GLES2) OGLESVersionToken = EGL_OPENGL_ES2_BIT; #elif defined(USE_GLES1) OGLESVersionToken = EGL_OPENGL_ES_API; #else OGLESVersionToken = EGL_OPENGL_ES2_BIT; #endif const EGLint RGBX_8888_ATTRIBS[]= { EGL_RENDERABLE_TYPE, OGLESVersionToken, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_NONE }; const EGLint RGB_565_ATTRIBS[]= { EGL_RENDERABLE_TYPE, OGLESVersionToken, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 8, EGL_NONE }; const EGLint* attribList; int windowFormat = ANativeWindow_getFormat(m_pState->window); if ((windowFormat == WINDOW_FORMAT_RGBA_8888) || (windowFormat == WINDOW_FORMAT_RGBX_8888)) { attribList = RGBX_8888_ATTRIBS; } else { attribList = RGB_565_ATTRIBS; } EGLConfig config; EGLint numConfigs; res = eglChooseConfig(m_display, attribList, &config, 1, &numConfigs); assert(res); EGLint format; res = eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_ID, &format); assert(res); EGLint max_swap_interval; res = eglGetConfigAttrib(m_display, config, EGL_MAX_SWAP_INTERVAL, &max_swap_interval); assert(res); EGLint min_swap_interval; res = eglGetConfigAttrib(m_display, config, EGL_MIN_SWAP_INTERVAL, &min_swap_interval); assert(res); LOGD("EGL Max Swap Interval is %d", max_swap_interval); LOGD("EGL Min Swap Interval is %d", min_swap_interval); int32_t setBufRes = ANativeWindow_setBuffersGeometry(m_pState->window, 0, 0, format); assert(setBufRes == 0); EGLNativeWindowType windowType; m_renderSurface = eglCreateWindowSurface(m_display, config, m_pState->window, NULL); assert(m_renderSurface != EGL_NO_SURFACE); LOGD("EGLRenderer eglCreateWindowSurface() success"); EGLint OGLESVersion; #if defined(USE_GLES3) OGLESVersion = 3; #elif defined(USE_GLES2) OGLESVersion = 2; #elif defined(USE_GLES1) OGLESVersion = 1; #else OGLESVersion = 2; #endif EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, OGLESVersion, EGL_NONE }; m_context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, contextAttribs); assert(m_context != EGL_NO_CONTEXT); LOGD("EGLRenderer eglCreateContext() success"); res = eglMakeCurrent(m_display, m_renderSurface, m_renderSurface, m_context); assert(res); LOGD("EGLRenderer eglMakeCurrent() success"); const GLubyte* glVendor; const GLubyte* glRenderer; const GLubyte* glVersion; glVendor = glGetString(GL_VENDOR); glRenderer = glGetString(GL_RENDERER); glVersion = glGetString(GL_VERSION); LOGD("The current GL_VENDOR: %s", glVendor); LOGD("The current GL_RENDERER: %s", glRenderer); LOGD("The current GL_VERSION: %s", glVersion); #if defined(USE_GLES3) GLint glMajorVersion, glMinorVersion; glGetIntegerv(GL_MAJOR_VERSION, &glMajorVersion); glGetIntegerv(GL_MINOR_VERSION, &glMinorVersion); LOGD("These query methods only available in OGL ES 3:"); LOGD(" - The current OGL Context support OGL Major_Version: %d", glMajorVersion); LOGD(" - The current OGL Context support OGL Minor_Version: %d", glMinorVersion); #endif res = eglQuerySurface(m_display, m_renderSurface, EGL_WIDTH, &m_width); assert(res); LOGD("EGLRenderer eglQuerySurface() success, m_width is %d", m_width); res = eglQuerySurface(m_display, m_renderSurface, EGL_HEIGHT, &m_height); assert(res); LOGD("EGLRenderer eglQuerySurface() success, m_height is %d", m_height); // try to disable vsync res = eglSwapInterval(m_display, 0); assert(res); LOGD("EGLRenderer eglSwapInterval to disable vsync success"); } LOGD("Init EGL end"); LOGD("super class Renderer::Init() begin"); Renderer::Init(); LOGD("super class Renderer::Init() end"); LOGD("EGLRenderer Init() end"); }
static bool gfx_ctx_init(void) { struct android_app *android_app = (struct android_app*)g_android; const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint num_config; EGLint egl_version_major, egl_version_minor; EGLint format; EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; RARCH_LOG("Initializing context\n"); if ((g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) { RARCH_ERR("eglGetDisplay failed.\n"); goto error; } if (!eglInitialize(g_egl_dpy, &egl_version_major, &egl_version_minor)) { RARCH_ERR("eglInitialize failed.\n"); goto error; } RARCH_LOG("[ANDROID/EGL]: EGL version: %d.%d\n", egl_version_major, egl_version_minor); if (!eglChooseConfig(g_egl_dpy, attribs, &g_config, 1, &num_config)) { RARCH_ERR("eglChooseConfig failed.\n"); goto error; } int var = eglGetConfigAttrib(g_egl_dpy, g_config, EGL_NATIVE_VISUAL_ID, &format); if (!var) { RARCH_ERR("eglGetConfigAttrib failed: %d.\n", var); goto error; } ANativeWindow_setBuffersGeometry(android_app->window, 0, 0, format); if (!(g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, android_app->window, 0))) { RARCH_ERR("eglCreateWindowSurface failed.\n"); goto error; } if (!(g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, 0, context_attributes))) { RARCH_ERR("eglCreateContext failed.\n"); goto error; } if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx)) { RARCH_ERR("eglMakeCurrent failed.\n"); goto error; } ALooper *looper = ALooper_forThread(); if (!looper) ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); return true; error: RARCH_ERR("EGL error: %d.\n", eglGetError()); gfx_ctx_destroy(); return false; }
void Renderer::Init() { // initialize OpenGL ES and EGL /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint format; EGLint numConfigs; EGLConfig config; m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(m_display, NULL, NULL); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(m_display, attribs, &config, 1, &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(m_pState->window, 0, 0, format); m_surface = eglCreateWindowSurface(m_display, config, m_pState->window, NULL); EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; m_context = eglCreateContext(m_display, config, NULL, contextAttribs); eglMakeCurrent(m_display, m_surface, m_surface, m_context); eglQuerySurface(m_display, m_surface, EGL_WIDTH, &m_width); eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &m_height); for (TextureVectorIterator iter = m_textures.begin(); iter != m_textures.end(); ++iter) { Texture* pCurrent = *iter; pCurrent->Init(); } for (ShaderVectorIterator iter = m_shaders.begin(); iter != m_shaders.end(); ++iter) { ShaderProgram* pCurrent = *iter; pCurrent->Link(); } m_initialized = true; DLOG() << "initialized" << m_initialized; }
/** * Initialize an EGL context for the current display. */ static int engine_init_display(struct engine* engine) { // initialize OpenGL ES and EGL /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE }; EGLint w, h, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(display, attribs, &config, 1, &numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); // ANativeActivity_setWindowFlags(engine->app->activity, AWINDOW_FLAG_FULLSCREEN, 0 ); surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); context = eglCreateContext(display, config, NULL, NULL); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); engine->display = display; engine->context = context; engine->surface = surface; engine->width = w; engine->height = h; pangolin::process::Resize(engine->width,engine->height); // Initialize GL state. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glDisable(GL_DEPTH_TEST); return 0; }
/** * Initialize an EGL context for the current display. */ static int engine_init_display(struct engine* engine,bool p_gl2) { // initialize OpenGL ES and EGL /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint gl2_attribs[] = { // EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 4, EGL_GREEN_SIZE, 4, EGL_RED_SIZE, 4, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, EGL_DONT_CARE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; const EGLint gl1_attribs[] = { // EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 4, EGL_GREEN_SIZE, 4, EGL_RED_SIZE, 4, EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, EGL_DONT_CARE, EGL_NONE }; const EGLint *attribs=p_gl2?gl2_attribs:gl1_attribs; EGLint w, h, dummy, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); /* Here, the application chooses the configuration it desires. In this * sample, we have a very simplified selection process, where we pick * the first EGLConfig that matches our criteria */ eglChooseConfig(display, attribs, &config, 1, &numConfigs); LOGI("Num configs: %i\n",numConfigs); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); //ANativeWindow_setFlags(engine->app->window, 0, 0, format|); surface = eglCreateWindowSurface(display, config, engine->app->window, NULL); const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION,2, EGL_NONE }; context = eglCreateContext(display, config, EGL_NO_CONTEXT, p_gl2?context_attribs:NULL); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); print_line("INIT VIDEO MODE: "+itos(w)+","+itos(h)); //engine->os->set_egl_extensions(eglQueryString(display,EGL_EXTENSIONS)); engine->os->init_video_mode(w,h); engine->display = display; engine->context = context; engine->surface = surface; engine->width = w; engine->height = h; engine->display_active=true; //engine->state.angle = 0; // Initialize GL state. //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glEnable(GL_CULL_FACE); // glShadeModel(GL_SMOOTH); glDisable(GL_DEPTH_TEST); LOGI("GL Version: %s - %s %s\n", glGetString(GL_VERSION),glGetString(GL_VENDOR), glGetString(GL_RENDERER)); return 0; }
// Initialized EGL resources. bool Renderer::initEGL(ANativeWindow *window) { LOGI(">initEGL Got window %p", window); int samples = 0; Properties* config = Game::getInstance()->getConfig()->getNamespace( "window", true); if (config) { samples = std::max(config->getInt("samples"), 0); } LOGI(">initEGL samples=%d", samples); // Hard-coded to 32-bit/OpenGL ES 2.0. // NOTE: EGL_SAMPLE_BUFFERS, EGL_SAMPLES and EGL_DEPTH_SIZE MUST remain at the beginning of the attribute list // since they are expected to be at indices 0-5 in config fallback code later. // EGL_DEPTH_SIZE is also expected to EGLint eglConfigAttrs[] = { EGL_SAMPLE_BUFFERS, samples > 0 ? 1 : 0, EGL_SAMPLES, samples, EGL_DEPTH_SIZE, 24, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; EGLint eglConfigCount; const EGLint eglContextAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; const EGLint eglSurfaceAttrs[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE }; if (_display == EGL_NO_DISPLAY && _context == EGL_NO_CONTEXT) { _display = eglGetCurrentDisplay(); LOGI(">initEGL _display=%p", _display); EGLSurface drawSurface = eglGetCurrentSurface(EGL_DRAW); LOGI(">initEGL drawSurface=%p", drawSurface); EGLSurface readSurface = eglGetCurrentSurface(EGL_READ); LOGI(">initEGL readSurface=%p", readSurface); EGLContext context = eglGetCurrentContext(); LOGI(">initEGL context=%p", context); // Get the EGL display and initialize. _display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (_display == EGL_NO_DISPLAY) { checkErrorEGL("eglGetDisplay"); goto error; } LOGI(">initEGL _display=%p", _display); eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(_display, context); eglDestroySurface(_display, drawSurface); if (eglInitialize(_display, NULL, NULL) != EGL_TRUE) { checkErrorEGL("eglInitialize"); goto error; } // Try both 24 and 16-bit depth sizes since some hardware (i.e. Tegra) does not support 24-bit depth bool validConfig = false; EGLint depthSizes[] = { 24, 16 }; for (unsigned int i = 0; i < 2; ++i) { eglConfigAttrs[1] = samples > 0 ? 1 : 0; eglConfigAttrs[3] = samples; eglConfigAttrs[5] = depthSizes[i]; if (eglChooseConfig(_display, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0) { LOGI(">initEGL depthSizes[i]=%d", depthSizes[i]); validConfig = true; break; } if (samples) { // Try lowering the MSAA sample size until we find a config int sampleCount = samples; while (sampleCount) { GP_WARN( "No EGL config found for depth_size=%d and samples=%d. Trying samples=%d instead.", depthSizes[i], sampleCount, sampleCount / 2); sampleCount /= 2; eglConfigAttrs[1] = sampleCount > 0 ? 1 : 0; eglConfigAttrs[3] = sampleCount; if (eglChooseConfig(_display, eglConfigAttrs, &__eglConfig, 1, &eglConfigCount) == EGL_TRUE && eglConfigCount > 0) { validConfig = true; break; } } if (validConfig) break; } else { GP_WARN("No EGL config found for depth_size=%d.", depthSizes[i]); } } if (!validConfig) { checkErrorEGL("eglChooseConfig"); goto error; } _context = eglCreateContext(_display, __eglConfig, EGL_NO_CONTEXT, eglContextAttrs); if (_context == EGL_NO_CONTEXT) { checkErrorEGL("eglCreateContext"); goto error; } } // EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is // guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). // As soon as we picked a EGLConfig, we can safely reconfigure the // ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. EGLint format; eglGetConfigAttrib(_display, __eglConfig, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(window, 0, 0, format); _surface = eglCreateWindowSurface(_display, __eglConfig, window, eglSurfaceAttrs); if (_surface == EGL_NO_SURFACE) { checkErrorEGL("eglCreateWindowSurface"); goto error; } if (eglMakeCurrent(_display, _surface, _surface, _context) != EGL_TRUE) { checkErrorEGL("eglMakeCurrent"); goto error; } eglQuerySurface(_display, _surface, EGL_WIDTH, &__width); eglQuerySurface(_display, _surface, EGL_HEIGHT, &__height); // __orientationAngle = getRotation() * 90; // Set vsync. eglSwapInterval(_display, WINDOW_VSYNC ? 1 : 0); // Initialize OpenGL ES extensions. __glExtensions = (const char*) glGetString(GL_EXTENSIONS); if (strstr(__glExtensions, "GL_OES_vertex_array_object") || strstr(__glExtensions, "GL_ARB_vertex_array_object")) { // Disable VAO extension for now. glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC) eglGetProcAddress( "glBindVertexArrayOES"); glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC) eglGetProcAddress( "glDeleteVertexArraysOES"); glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC) eglGetProcAddress( "glGenVertexArraysOES"); glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC) eglGetProcAddress( "glIsVertexArrayOES"); } LOGI("<initEGL true"); return true; error: LOGI("<initEGL false"); return false; }
static int engine_init_display(struct engine* engine) { // initialize OpenGL ES and EGL const EGLint attribs[] = { EGL_NATIVE_VISUAL_ID, WINDOW_FORMAT_RGB_565, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_BLUE_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_RED_SIZE, 5, EGL_DEPTH_SIZE,1, EGL_NONE }; EGLint w, h, dummy, format; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint majorVersion; EGLint minorVersion; eglInitialize(display, &majorVersion, &minorVersion); //eglInitialize(display, 0, 0); LOGI("OpenGL %i.%i", majorVersion,minorVersion); //query num of configs int* num_conf = new int[1]; eglGetConfigs(display, NULL, 0, num_conf); //if configuration array is null it still returns the number of configurations int configurations = num_conf[0]; LOGI("total num configs: %i", configurations); //just some debugging info if the need arises... LOGI("EGL_OPENGL_ES2_BIT id:%i", EGL_OPENGL_ES2_BIT); //print the numerical code for the ES2 bit mask, etc LOGI("EGL_SURFACE_TYPE::EGL_WINDOW_BIT id:%i", EGL_WINDOW_BIT); LOGI("WINDOW_FORMAT_RGB_565 id:%i", WINDOW_FORMAT_RGB_565); //now query the configs EGLConfig* conf = new EGLConfig[configurations]; eglGetConfigs(display, conf, configurations, num_conf); int* depth = new int[1]; int* r = new int[1]; int* g = new int[1]; int* b = new int[1]; int* a = new int[1]; int* s = new int[1]; int* renderType = new int[1]; int* surfaceType = new int[1]; int* formatType = new int[1]; EGLConfig configToUse; //this is the one true config that we will use for(int i = 0; i < configurations; i++) { eglGetConfigAttrib(display, conf[i], EGL_DEPTH_SIZE, depth); eglGetConfigAttrib(display, conf[i], EGL_RED_SIZE, r); eglGetConfigAttrib(display, conf[i], EGL_GREEN_SIZE, g); eglGetConfigAttrib(display, conf[i], EGL_BLUE_SIZE, b); eglGetConfigAttrib(display, conf[i], EGL_ALPHA_SIZE, a); eglGetConfigAttrib(display, conf[i], EGL_RENDERABLE_TYPE, renderType); eglGetConfigAttrib(display, conf[i], EGL_STENCIL_SIZE, s); eglGetConfigAttrib(display, conf[i], EGL_SURFACE_TYPE, surfaceType); eglGetConfigAttrib(display, conf[i], EGL_NATIVE_VISUAL_ID, formatType); LOGI("(R%i,G%i,B%i,A%i)depth:(%i) stencil:(%i) surfaceType:(%i) renderType:(%i) formatType:(%i)",r[0],g[0],b[0],a[0],depth[0],s[0],surfaceType[0], renderType[0],formatType[0]); if((renderType[0] & EGL_OPENGL_ES2_BIT) > 0 && (surfaceType[0] & EGL_WINDOW_BIT) > 0 && (formatType[0] & WINDOW_FORMAT_RGB_565) > 0 && depth[0]>0) { configToUse=conf[i]; LOGI("Config #%i" , i ); LOGI("(R%i,G%i,B%i,A%i) %idepth %istencil %isurfaceType %iNativeVisualId",r[0],g[0],b[0],a[0],depth[0],s[0],surfaceType[0],formatType[0]); } } //bridge the pixel format back into android eglGetConfigAttrib(display, configToUse, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format); surface = eglCreateWindowSurface(display, configToUse, engine->app->window, NULL); if(surface == EGL_NO_SURFACE ) { LOGW("Error making surface, EGL_NO_SURFACE"); } //now create the OpenGL ES2 context const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION , 2, EGL_NONE }; context = eglCreateContext(display, configToUse, NULL, contextAttribs); if(context == EGL_NO_CONTEXT ) { LOGW("Error making context, EGL_NO_CONTEXT"); } if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { LOGW("Unable to eglMakeCurrent"); return -1; } eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); ContextWidth = w; ContextHeight = h; engine->display = display; engine->context = context; engine->surface = surface; engine->width = w; engine->height = h; engine->state.angle = 0; glEnable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); //GLubyte* rendererString = new GLubyte[512]; const GLubyte* rendererString = rendererString=glGetString(GL_VERSION); LOGI("Renderer: %s",rendererString); // // // LOAD ALL RESOURCES // // ////////////////// // PHONG SHADER // ////////////////// if(!PhongShader.createShader((char*)"phong.vs",(char*)"phong.fs")) { LOGE("Could not create phong program."); return false; } PositionAttributes = glGetAttribLocation(PhongShader.ID, "aPosition"); NormalAttributes = glGetAttribLocation(PhongShader.ID, "aNormal"); TexCoordAttributes = glGetAttribLocation(PhongShader.ID, "aTexCoords"); MVPMatrixUniform = glGetUniformLocation( PhongShader.ID, "MVPMatrixUniform" ); EyePosUniform = glGetUniformLocation(PhongShader.ID,"EyePosUniform"); LightPosUniform = glGetUniformLocation(PhongShader.ID,"LightPosUniform"); TextureSampler = glGetUniformLocation(PhongShader.ID,"sTexture"); LOGI("===PHONG-DEBUG VALUES==="); LOGI("PositionAttributes: %i",PositionAttributes); LOGI("NormalAttributes: %i",NormalAttributes); LOGI("TexCoordAttributes: %i",TexCoordAttributes); LOGI("MVPMatrixUniform: %i",MVPMatrixUniform); LOGI("EyePosUniform: %i",EyePosUniform); LOGI("LightPosUniform: %i",LightPosUniform); LOGI("TextureSampler: %i",TextureSampler); LOGI("===END==="); ////////////////// // DEPTH SHADER // ////////////////// if(!DepthShader.createShader((char*)"depthcolor.vs",(char*)"depthcolor.fs")) { LOGE("Could not create depth shader program."); return false; } DepthShaderMVPMatrixUniform = glGetUniformLocation(DepthShader.ID, "MVPMatrixUniform"); DepthShaderPositionAttributes = glGetAttribLocation(DepthShader.ID, "aPosition"); LOGI("===DEPTH-DEBUG VALUES==="); LOGI("DepthShaderPositionAttributes: %i",DepthShaderPositionAttributes); LOGI("DepthShaderMVPMatrixUniform: %i",DepthShaderMVPMatrixUniform); LOGI("===END==="); ///////////////////////////////// // TEXPASSTHRU (SKYBOX) SHADER // ///////////////////////////////// if(!TexPassThruShader.createShader((char*)"texpassthru.vs",(char*)"texpassthru.fs")) { LOGE("Could not create texpassthru program."); return false; } TexPassThruSampler = glGetUniformLocation(TexPassThruShader.ID,"sTexture"); TexPassThruMVPMatrixUniform = glGetUniformLocation(TexPassThruShader.ID,"MVPMatrixUniform"); TexPassThruPositionAttributes = glGetAttribLocation(TexPassThruShader.ID, "aPosition"); TexPassThruTexCoordAttributes = glGetAttribLocation(TexPassThruShader.ID, "aTexCoords"); LOGI("===TEXPASSTHRU-DEBUG VALUES==="); LOGI("TexPassThruSampler: %i",TexPassThruSampler); LOGI("TexPassThruMVPMatrixUniform: %i",TexPassThruMVPMatrixUniform); LOGI("TexPassThruPositionAttributes: %i",TexPassThruPositionAttributes); LOGI("TexPassThruTexCoordAttributes: %i",TexPassThruTexCoordAttributes); LOGI("===END==="); //////////////////////// // ENVIRONMENT SHADER // //////////////////////// if (!EnvironmentMappingShader.createShader((char*)"environmentcubemap.vs",(char*)"environmentcubemap.fs")) { LOGE("Could not create program."); return false; } EnvironmentMappingShaderMVPMatrixUniform=glGetUniformLocation(EnvironmentMappingShader.ID,"MVPMatrixUniform"); EnvironmentMappingShaderPositionAttributes=glGetAttribLocation(EnvironmentMappingShader.ID, "aPosition"); EnvironmentMappingShaderNormalAttributes=glGetAttribLocation(EnvironmentMappingShader.ID, "aNormal"); EnvironmentMappingShaderCubeSampler=glGetUniformLocation(EnvironmentMappingShader.ID,"sCubeTexture"); LOGI("===ENVIRONMENT-DEBUG VALUES==="); LOGI("EnvironmentMappingShaderCubeSampler: %i",EnvironmentMappingShaderCubeSampler); LOGI("EnvironmentMappingShaderMVPMatrixUniform: %i",EnvironmentMappingShaderMVPMatrixUniform); LOGI("EnvironmentMappingShaderPositionAttributes: %i",EnvironmentMappingShaderPositionAttributes); LOGI("TexPassThruTeEnvironmentMappingShaderNormalAttributesxCoordAttributes: %i",EnvironmentMappingShaderNormalAttributes); LOGI("===END==="); //Matrices esMatrixLoadIdentity(&MVPMatrix); //viewport glViewport(0, 0, w, h); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); checkGlError("glViewport"); //load resources internally from the APK StatueMesh.loadMesh((char*)"athena.obj"); checkGlError("loadMesh"); if(!StoneTexture.loadTexture((char*)"rockish.tga")) { LOGE("texture loading FAILED"); } CubeSkyBox.loadSkyBox(); if(!EnvironmentCubeTexture.loadCubeTexture()) LOGE("Could not load cube texture."); return 0; }
__unused JNIEXPORT void JNICALL Java_pl_droidsonroids_gif_GifInfoHandle_bindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo, jobject jsurface, jlongArray savedState) { GifInfo *info = (GifInfo *) (intptr_t) gifInfo; SurfaceDescriptor *descriptor = info->frameBufferDescriptor; if (descriptor == NULL) { descriptor = malloc(sizeof(SurfaceDescriptor)); if (descriptor == NULL) { throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); return; } descriptor->eventPollFd.events = POLL_IN; descriptor->eventPollFd.fd = eventfd(0, 0); if (descriptor->eventPollFd.fd == -1) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Eventfd creation failed "); free(descriptor); return; } errno = pthread_cond_init(&descriptor->slurpCond, NULL); THROW_ON_NONZERO_RESULT(errno, "Slurp condition variable initialization failed "); errno = pthread_cond_init(&descriptor->renderCond, NULL); THROW_ON_NONZERO_RESULT(errno, "Render condition variable initialization failed "); errno = pthread_mutex_init(&descriptor->slurpMutex, NULL); THROW_ON_NONZERO_RESULT(errno, "Slurp mutex initialization failed "); errno = pthread_mutex_init(&descriptor->renderMutex, NULL); THROW_ON_NONZERO_RESULT(errno, "Render mutex initialization failed "); descriptor->frameBuffer = NULL; info->frameBufferDescriptor = descriptor; info->destructor = releaseSurfaceDescriptor; } eventfd_t eventValue; int pollResult; while (1) { pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, 0)); if (pollResult == 0) break; else if (pollResult > 0) { const int readResult = TEMP_FAILURE_RETRY(eventfd_read(descriptor->eventPollFd.fd, &eventValue)); if (readResult != 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not read from eventfd "); return; } } else { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not poll on eventfd "); return; } } const int32_t windowFormat = info->isOpaque ? WINDOW_FORMAT_RGBX_8888 : WINDOW_FORMAT_RGBA_8888; struct ANativeWindow *window = ANativeWindow_fromSurface(env, jsurface); GifFileType *const gifFilePtr = info->gifFilePtr; if (ANativeWindow_setBuffersGeometry(window, (int32_t) gifFilePtr->SWidth, (int32_t) gifFilePtr->SHeight, windowFormat) != 0) { ANativeWindow_release(window); throwException(env, RUNTIME_EXCEPTION_ERRNO, "Buffers geometry setting failed "); return; } struct ANativeWindow_Buffer buffer = {.bits =NULL}; void *oldBufferBits; if (ANativeWindow_lock(window, &buffer, NULL) != 0) { #ifdef DEBUG LOGE("Window lock failed %d", errno); #endif ANativeWindow_release(window); return; } const size_t bufferSize = buffer.stride * buffer.height * sizeof(argb); info->stride = buffer.stride; long long invalidationDelayMillis; if (descriptor->frameBuffer) { memcpy(buffer.bits, descriptor->frameBuffer, bufferSize); invalidationDelayMillis = 0; descriptor->renderHelper = 1; descriptor->slurpHelper = 0; } else { if (savedState != NULL) { invalidationDelayMillis = restoreSavedState(info, env, savedState, buffer.bits); if (invalidationDelayMillis < 0) invalidationDelayMillis = 0; } else invalidationDelayMillis = 0; descriptor->renderHelper = 0; descriptor->slurpHelper = 1; } info->lastFrameRemainder = -1; ANativeWindow_unlockAndPost(window); if (info->loopCount != 0 && info->currentLoop == info->loopCount) { ANativeWindow_release(window); pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, -1)); if (pollResult < 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Animation end poll failed "); } return; } errno = pthread_create(&descriptor->slurpThread, NULL, slurp, info); if (errno != 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Slurp thread creation failed "); ANativeWindow_release(window); return; } while (1) { pollResult = TEMP_FAILURE_RETRY(poll(&descriptor->eventPollFd, 1, (int) invalidationDelayMillis)); long renderingStartTime = getRealTime(); if (pollResult < 0) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Display loop poll failed "); break; } else if (pollResult > 0) { if (descriptor->frameBuffer == NULL) { descriptor->frameBuffer = malloc(bufferSize); if (descriptor->frameBuffer == NULL) { throwException(env, OUT_OF_MEMORY_ERROR, OOME_MESSAGE); break; } } memcpy(descriptor->frameBuffer, buffer.bits, bufferSize); break; } oldBufferBits = buffer.bits; struct ARect *dirtyRectPtr; if (info->currentIndex == 0) { dirtyRectPtr = NULL; } else { const GifImageDesc imageDesc = gifFilePtr->SavedImages[info->currentIndex].ImageDesc; struct ARect dirtyRect = { .left = imageDesc.Left, .top = imageDesc.Top, .right = imageDesc.Left + imageDesc.Width, .bottom = imageDesc.Top + imageDesc.Height }; dirtyRectPtr = &dirtyRect; } if (ANativeWindow_lock(window, &buffer, dirtyRectPtr) != 0) { #ifdef DEBUG LOGE("Window lock failed %d", errno); #endif break; } if (info->currentIndex == 0) prepareCanvas(buffer.bits, info); else memcpy(buffer.bits, oldBufferBits, bufferSize); pthread_mutex_lock(&descriptor->renderMutex); while (descriptor->renderHelper == 0) { pthread_cond_wait(&descriptor->renderCond, &descriptor->renderMutex); } descriptor->renderHelper = 0; pthread_mutex_unlock(&descriptor->renderMutex); const uint_fast32_t frameDuration = getBitmap(buffer.bits, info); pthread_mutex_lock(&descriptor->slurpMutex); descriptor->slurpHelper = 1; pthread_cond_signal(&descriptor->slurpCond); pthread_mutex_unlock(&descriptor->slurpMutex); ANativeWindow_unlockAndPost(window); invalidationDelayMillis = calculateInvalidationDelay(info, renderingStartTime, frameDuration); if (info->lastFrameRemainder >= 0) { invalidationDelayMillis = info->lastFrameRemainder; info->lastFrameRemainder = -1; } } ANativeWindow_release(window); pthread_mutex_lock(&descriptor->slurpMutex); descriptor->slurpHelper = 2; pthread_cond_signal(&descriptor->slurpCond); pthread_mutex_unlock(&descriptor->slurpMutex); errno = pthread_join(descriptor->slurpThread, NULL); THROW_ON_NONZERO_RESULT(errno, "Slurp thread join failed"); } __unused JNIEXPORT void JNICALL Java_pl_droidsonroids_gif_GifInfoHandle_postUnbindSurface(JNIEnv *env, jclass __unused handleClass, jlong gifInfo) { GifInfo *info = (GifInfo *) (intptr_t) gifInfo; if (info == NULL || info->frameBufferDescriptor == NULL) { return; } SurfaceDescriptor const *descriptor = info->frameBufferDescriptor; const int writeResult = TEMP_FAILURE_RETRY(eventfd_write(descriptor->eventPollFd.fd, 1)); if (writeResult != 0 && errno != EBADF) { throwException(env, RUNTIME_EXCEPTION_ERRNO, "Could not write to eventfd "); } }