// Helper function EGLenum currentEglApi() { EGLenum api = 0; if (EGL_NO_CONTEXT != eglGetCurrentContext()) api = eglQueryAPI(); return api; }
/** * Initialize the given _EGLContext object to defaults and/or the values * in the attrib_list. */ EGLBoolean _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { const EGLenum api = eglQueryAPI(); EGLint err; if (api == EGL_NONE) { _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); return EGL_FALSE; } _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy); ctx->ClientAPI = api; ctx->Config = conf; ctx->WindowRenderBuffer = EGL_NONE; ctx->ClientVersion = 1; /* the default, per EGL spec */ err = _eglParseContextAttribList(ctx, attrib_list); if (err == EGL_SUCCESS && ctx->Config) { EGLint api_bit; api_bit = _eglGetContextAPIBit(ctx); if (!(ctx->Config->RenderableType & api_bit)) { _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", api_bit, ctx->Config->RenderableType); err = EGL_BAD_CONFIG; } } if (err != EGL_SUCCESS) return _eglError(err, "eglCreateContext"); return EGL_TRUE; }
/* EGLenum eglQueryAPI ( void ) */ static jint android_eglQueryAPI (JNIEnv *_env, jobject _this) { EGLenum _returnValue = (EGLenum) 0; _returnValue = eglQueryAPI(); return (jint)_returnValue; }
/** * Initialize the given _EGLContext object to defaults and/or the values * in the attrib_list. */ EGLBoolean _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { const EGLenum api = eglQueryAPI(); EGLint err; if (api == EGL_NONE) { _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); return EGL_FALSE; } memset(ctx, 0, sizeof(_EGLContext)); ctx->Resource.Display = dpy; ctx->ClientAPI = api; ctx->Config = conf; ctx->WindowRenderBuffer = EGL_NONE; ctx->ClientVersion = 1; /* the default, per EGL spec */ err = _eglParseContextAttribList(ctx, attrib_list); if (err != EGL_SUCCESS) return _eglError(err, "eglCreateContext"); return EGL_TRUE; }
EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void) { EGLenum api = eglQueryAPI(); eglBindAPI(EGL_OPENGL_ES_API); eglWaitClient(); eglBindAPI(api); return EGL_TRUE; }
/* hypothesis: at this step all textures, etc are destroyed */ void DRI2FallbackDestroy(struct DRI2priv *priv) { EGLenum current_api; current_api = eglQueryAPI(); eglBindAPI(EGL_OPENGL_API); eglMakeCurrent(priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(priv->display, priv->context); eglTerminate(priv->display); eglBindAPI(current_api); free(priv); }
void WindowSurfaceImpl::saveEglState() { // Some painter needs to be active on the device // in order to get correct data from EGL, so if // there's no active painter, activate one here if(!mMainSurface.device->paintingActive()) { mPainter.begin(mMainSurface.device); } mEgl.drawSurface = eglGetCurrentSurface(EGL_DRAW); mEgl.readSurface = eglGetCurrentSurface(EGL_READ); mEgl.display = eglGetCurrentDisplay(); mEgl.context = eglGetCurrentContext(); mEgl.api = eglQueryAPI(); }
Context * createContext(const Visual *_visual, Context *shareContext, Profile profile, bool debug) { const EglVisual *visual = static_cast<const EglVisual *>(_visual); EGLContext share_context = EGL_NO_CONTEXT; EGLContext context; Attributes<EGLint> attribs; if (shareContext) { share_context = static_cast<EglContext*>(shareContext)->context; } EGLint api = eglQueryAPI(); switch (profile) { case PROFILE_COMPAT: load("libGL.so.1"); eglBindAPI(EGL_OPENGL_API); break; case PROFILE_CORE: assert(0); return NULL; case PROFILE_ES1: load("libGLESv1_CM.so.1"); eglBindAPI(EGL_OPENGL_ES_API); break; case PROFILE_ES2: load("libGLESv2.so.2"); eglBindAPI(EGL_OPENGL_ES_API); attribs.add(EGL_CONTEXT_CLIENT_VERSION, 2); break; default: return NULL; } attribs.end(EGL_NONE); context = eglCreateContext(eglDisplay, visual->config, share_context, attribs); if (!context) return NULL; eglBindAPI(api); return new EglContext(visual, profile, context); }
/** * Initialize the given _EGLContext object to defaults and/or the values * in the attrib_list. */ EGLBoolean _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { const EGLenum api = eglQueryAPI(); EGLint err; if (api == EGL_NONE) { _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); return EGL_FALSE; } memset(ctx, 0, sizeof(_EGLContext)); _eglInitResource(&ctx->Resource, sizeof(_EGLResource), dpy); ctx->ClientAPI = api; ctx->Config = conf; ctx->WindowRenderBuffer = EGL_NONE; ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ ctx->ClientMinorVersion = 0; ctx->Flags = 0; ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; err = _eglParseContextAttribList(ctx, dpy, attrib_list); if (err == EGL_SUCCESS && ctx->Config) { EGLint api_bit; api_bit = _eglGetContextAPIBit(ctx); if (!(ctx->Config->RenderableType & api_bit)) { _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", api_bit, ctx->Config->RenderableType); err = EGL_BAD_CONFIG; } } if (err != EGL_SUCCESS) return _eglError(err, "eglCreateContext"); return EGL_TRUE; }
/* Destroy the content, except the link and the struct mem */ static void PRESENTDestroyPixmapContent(Display *dpy, PRESENTPixmapPriv *present_pixmap) { XFreePixmap(dpy, present_pixmap->pixmap); #ifdef D3DADAPTER9_DRI2 if (present_pixmap->dri2_info.is_dri2) { struct DRI2priv *dri2_priv = present_pixmap->dri2_info.dri2_priv; EGLenum current_api; current_api = eglQueryAPI(); eglBindAPI(EGL_OPENGL_API); if(eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context)) { glDeleteFramebuffers(1, &present_pixmap->dri2_info.fbo_read); glDeleteFramebuffers(1, &present_pixmap->dri2_info.fbo_write); glDeleteTextures(1, &present_pixmap->dri2_info.texture_read); glDeleteTextures(1, &present_pixmap->dri2_info.texture_write); } else { ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError()); } eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglBindAPI(current_api); } #endif }
/** * Initialize the given _EGLContext object to defaults and/or the values * in the attrib_list. */ EGLBoolean _eglInitContext(_EGLDriver *drv, _EGLContext *ctx, _EGLConfig *conf, const EGLint *attrib_list) { EGLint i; const EGLenum api = eglQueryAPI(); if (api == EGL_NONE) { _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); return EGL_FALSE; } memset(ctx, 0, sizeof(_EGLContext)); ctx->ClientVersion = 1; /* the default, per EGL spec */ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { case EGL_CONTEXT_CLIENT_VERSION: i++; ctx->ClientVersion = attrib_list[i]; break; default: _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext"); return EGL_FALSE; } } ctx->Config = conf; ctx->DrawSurface = EGL_NO_SURFACE; ctx->ReadSurface = EGL_NO_SURFACE; ctx->ClientAPI = api; ctx->WindowRenderBuffer = EGL_NONE; return EGL_TRUE; }
JNIEXPORT jint JNICALL Java_org_lwjgl_opengles_EGL_eglQueryAPI(JNIEnv *env, jclass clazz) { return eglQueryAPI(); }
/*!*********************************************************************** @Function ApiScreenCaptureBuffer @Input Width Width of the region to capture @Input Height Height of the region to capture @Input pBuf A buffer to put the screen capture into @description API-specific function to store the current content of the FrameBuffer into the memory allocated by the user. *************************************************************************/ bool PVRShellInit::ApiScreenCaptureBuffer(int Width,int Height,unsigned char *pBuf) { unsigned char *pLines2; int i, j; bool bRet = true; #ifdef BUILD_OVG if(eglQueryAPI() != EGL_OPENVG_API) { m_pShell->PVRShellOutputDebug("PVRShell: Screen capture failed. OpenVG is not the current API"); return false; } #endif /* Allocate memory for line */ pLines2 = (unsigned char *)calloc(4 * Width * Height, sizeof(unsigned char)); if (!pLines2) return false; #ifdef BUILD_OVG while (vgGetError()); vgReadPixels(pLines2, Width * 4, VG_sRGBA_8888, 0, 0, Width, Height); if(vgGetError()) { bRet = false; } else { /* Convert RGB to BGR in line */ for (j = 0, i = 0; j < 4 * Width * Height; j += 4, i += 3) { pBuf[i] = pLines2[j+1]; pBuf[i+1] = pLines2[j+2]; pBuf[i+2] = pLines2[j+3]; } } #else while (glGetError()); /* Read line from frame buffer */ glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, pLines2); if(glGetError()) { bRet = false; } else { /* Convert RGB to BGR in line */ for (j = 0, i = 0; j < 4 * Width * Height; j += 4, i += 3) { pBuf[i] = pLines2[j+2]; pBuf[i+1] = pLines2[j+1]; pBuf[i+2] = pLines2[j]; } } #endif free(pLines2); return bRet; }
int ngi_context_egl_init(ngi_context* ctx, ngi_window* win) { EGLNativeDisplayType ndpy = NULL; EGLNativeWindowType nwnd = 0; #ifdef NGI_WINDOW_XLIB if(win->app->type == ngi_wm_api_xlib ) { ndpy = (EGLNativeDisplayType)win->app->plat.xlib.dpy; nwnd = (EGLNativeWindowType)win->plat.xlib.win; } #endif ctx->type = ngi_context_api_egl; EGLDisplay edpy = ctx->platform.egl.edpy = eglGetDisplay( ndpy ); EGLint majorVersion, minorVersion; int succ; EGLConfig ecfg; EGLint num_config; EGLContext ectxt; EGLSurface esfc; EGLint ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; EGLint attr[] = { /* EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT,*/ /* EGL_NATIVE_RENDERABLE, 1,*/ /* EGL_CONFIG_CAVEAT, EGL_NONE,*/ EGL_NONE }; printf("eglGetDisplay: %p\n", edpy); checkEGL(); succ = eglInitialize(edpy, &majorVersion, &minorVersion); printf("eglInitialize: %d\n", succ); checkEGL(); // eglBindAPI(EGL_OPENGL_API); const char* apis = eglQueryString(edpy, EGL_CLIENT_APIS); const char* exts = eglQueryString(edpy, EGL_EXTENSIONS); printf("EGL APIs: %s\n", apis); printf("EGL Extensions: %s\n", exts); if(!eglChooseConfig(edpy, attr, &ecfg, 1, &num_config)) { printf("eglChooseConfig error\n"); return 0; } if(num_config != 1) { printf("More than one config: %d\n", num_config); return 0; } checkEGL(); esfc = ctx->platform.egl.esfc = eglCreateWindowSurface(edpy, ecfg, nwnd, NULL); if(esfc == EGL_NO_SURFACE) { printf("Unable to create EGL surface (%x)\n", eglGetError()); return 0; } ectxt = ctx->platform.egl.ectx = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, ctxattr); if(ectxt == EGL_NO_CONTEXT) { printf("Unable to create EGL context (%x)\n", eglGetError()); return 0; } eglMakeCurrent(edpy, esfc, esfc, ectxt); checkEGL(); EGLint val = 0; eglQueryContext(edpy, ectxt, EGL_CONTEXT_CLIENT_TYPE, &val); printf("Context client type: %x\n", val); eglQueryContext(edpy, ectxt, EGL_CONTEXT_CLIENT_VERSION, &val); printf("Context client version: %d\n", val); EGLenum api = eglQueryAPI(); int ver=0; switch(api) { case EGL_OPENGL_ES_API: eglQueryContext(edpy, ectxt, EGL_CONTEXT_CLIENT_VERSION, &ver); switch(ver) { case 1: ctx->graphics = ngi_graphics_api_gles1; break; case 2: ctx->graphics = ngi_graphics_api_gles2; break; default: printf("Unsupported GLES version %d\n", ver); } break; case EGL_OPENGL_API: ctx->graphics = ngi_graphics_api_opengl; break; default: printf("Unsupported EGL Graphics api 0x%x\n", api); } eglSwapInterval(edpy,1); win->context = ctx; return 1; }
//-------------------------------------------------------------------------------------- // Name: WndProc() // Desc: The application window's message proc //-------------------------------------------------------------------------------------- LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { // Get the application data CFrmAppContainer* pAppContainer = (CFrmAppContainer*)GetWindowLong( hWnd, GWL_USERDATA ); switch( uMsg ) { case WM_SETCURSOR: // User has tapped the screen PostQuitMessage( 0 ); break; case WM_KEYDOWN: case WM_KEYUP: { // Ignore redundant messages from automatically repeated keystrokes if( ( uMsg == WM_KEYDOWN ) && ( HIWORD(lParam) & KF_REPEAT ) ) return 0; BOOL bShiftKeyState = ( GetKeyState( VK_SHIFT ) & 0x8000 ) ? TRUE : FALSE; BOOL bCtrlKeyState = ( GetKeyState( VK_CONTROL ) & 0x8000 ) ? TRUE : FALSE; // Handle the ESC key if( wParam == VK_ESCAPE ) { PostQuitMessage( 0 ); return 0; } // Handle remaining keys // Note: some mappings may only apply to US keyboards UINT32 nButtonMask = 0; switch( wParam ) { case '1': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_1; break; case '2': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_2; break; case '3': nButtonMask = bShiftKeyState ? FRM_INPUT::KEY_HASH : FRM_INPUT::KEY_3; break; case '4': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_4; break; case '5': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_5; break; case '6': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_6; break; case '7': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_7; break; case '8': nButtonMask = bShiftKeyState ? FRM_INPUT::KEY_STAR : FRM_INPUT::KEY_8; break; case '9': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_9; break; case '0': nButtonMask = bShiftKeyState ? FRM_INPUT::NONE : FRM_INPUT::KEY_0; break; case VK_NUMPAD1: nButtonMask = FRM_INPUT::KEY_1; break; case VK_NUMPAD2: nButtonMask = FRM_INPUT::KEY_2; break; case VK_NUMPAD3: nButtonMask = FRM_INPUT::KEY_3; break; case VK_NUMPAD4: nButtonMask = FRM_INPUT::KEY_4; break; case VK_NUMPAD5: nButtonMask = FRM_INPUT::KEY_5; break; case VK_NUMPAD6: nButtonMask = FRM_INPUT::KEY_6; break; case VK_NUMPAD7: nButtonMask = FRM_INPUT::KEY_7; break; case VK_NUMPAD8: nButtonMask = FRM_INPUT::KEY_8; break; case VK_NUMPAD9: nButtonMask = FRM_INPUT::KEY_9; break; case VK_NUMPAD0: nButtonMask = FRM_INPUT::KEY_0; break; case VK_MULTIPLY: nButtonMask = FRM_INPUT::KEY_STAR; break; case VK_LEFT: nButtonMask = FRM_INPUT::DPAD_LEFT; break; case VK_RIGHT: nButtonMask = FRM_INPUT::DPAD_RIGHT; break; case VK_UP: nButtonMask = FRM_INPUT::DPAD_UP; break; case VK_DOWN: nButtonMask = FRM_INPUT::DPAD_DOWN; break; case VK_SPACE: nButtonMask = FRM_INPUT::SELECT; break; case VK_RETURN: nButtonMask = FRM_INPUT::SELECT; break; case VK_BACK: nButtonMask = FRM_INPUT::KEY_CLEAR; break; case VK_DELETE: nButtonMask = FRM_INPUT::KEY_CLEAR; break; case VK_INSERT: nButtonMask = FRM_INPUT::KEY_EDIT; break; } if( nButtonMask ) { if( uMsg == WM_KEYDOWN ) pAppContainer->m_pApplication->m_Input.m_nButtons |= nButtonMask; else pAppContainer->m_pApplication->m_Input.m_nButtons &= ~nButtonMask; } // Toggle the window orientation between portrait and landscape mode EGLenum nAPI = eglQueryAPI(); if( nAPI == EGL_OPENGL_ES_API && uMsg == WM_KEYDOWN && nButtonMask == FRM_INPUT::KEY_STAR ) pAppContainer->ToggleOrientation(); return 0; } case WM_DESTROY: case WM_CLOSE: PostQuitMessage( 0 ); return 0; } // Pass all unhandled messages to the default WndProc return DefWindowProc( hWnd, uMsg, wParam, lParam ); }
BOOL DRI2FallbackPRESENTPixmap(PRESENTpriv *present_priv, struct DRI2priv *dri2_priv, int fd, int width, int height, int stride, int depth, int bpp, PRESENTPixmapPriv **present_pixmap_priv) { Window root = RootWindow(dri2_priv->dpy, DefaultScreen(dri2_priv->dpy)); Pixmap pixmap; EGLImageKHR image; GLuint texture_read, texture_write, fbo_read, fbo_write; EGLint attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_ARGB8888, EGL_DMA_BUF_PLANE0_FD_EXT, 0, EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, EGL_NONE }; EGLenum current_api = 0; int status; pthread_mutex_lock(&present_priv->mutex_present); pixmap = XCreatePixmap(dri2_priv->dpy, root, width, height, 24); if (!pixmap) goto fail; attribs[1] = width; attribs[3] = height; attribs[7] = fd; attribs[11] = stride; current_api = eglQueryAPI(); eglBindAPI(EGL_OPENGL_API); /* We bind the dma-buf to a EGLImage, then to a texture, and then to a fbo. * Note that we can delete the EGLImage, but we shouldn't delete the texture, * else the fbo is invalid */ image = dri2_priv->eglCreateImageKHR_func(dri2_priv->display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); if (image == EGL_NO_IMAGE_KHR) goto fail; close(fd); if(eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context)) { glGenTextures(1, &texture_read); glBindTexture(GL_TEXTURE_2D, texture_read); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); dri2_priv->glEGLImageTargetTexture2DOES_func(GL_TEXTURE_2D, image); glGenFramebuffers(1, &fbo_read); glBindFramebuffer(GL_FRAMEBUFFER, fbo_read); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_read, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; glBindTexture(GL_TEXTURE_2D, 0); dri2_priv->eglDestroyImageKHR_func(dri2_priv->display, image); /* We bind a newly created pixmap (to which we want to copy the content) * to an EGLImage, then to a texture, then to a fbo. */ image = dri2_priv->eglCreateImageKHR_func(dri2_priv->display, dri2_priv->context, EGL_NATIVE_PIXMAP_KHR, (void *)pixmap, NULL); if (image == EGL_NO_IMAGE_KHR) goto fail; glGenTextures(1, &texture_write); glBindTexture(GL_TEXTURE_2D, texture_write); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); dri2_priv->glEGLImageTargetTexture2DOES_func(GL_TEXTURE_2D, image); glGenFramebuffers(1, &fbo_write); glBindFramebuffer(GL_FRAMEBUFFER, fbo_write); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_write, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) goto fail; glBindTexture(GL_TEXTURE_2D, 0); dri2_priv->eglDestroyImageKHR_func(dri2_priv->display, image); } else { ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError()); } eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); *present_pixmap_priv = (PRESENTPixmapPriv *) calloc(1, sizeof(PRESENTPixmapPriv)); if (!*present_pixmap_priv) { goto fail; } (*present_pixmap_priv)->released = TRUE; (*present_pixmap_priv)->pixmap = pixmap; (*present_pixmap_priv)->present_priv = present_priv; (*present_pixmap_priv)->next = present_priv->first_present_priv; (*present_pixmap_priv)->width = width; (*present_pixmap_priv)->height = height; (*present_pixmap_priv)->depth = depth; (*present_pixmap_priv)->dri2_info.is_dri2 = TRUE; (*present_pixmap_priv)->dri2_info.dri2_priv = dri2_priv; (*present_pixmap_priv)->dri2_info.fbo_read = fbo_read; (*present_pixmap_priv)->dri2_info.fbo_write = fbo_write; (*present_pixmap_priv)->dri2_info.texture_read = texture_read; (*present_pixmap_priv)->dri2_info.texture_write = texture_write; present_priv->last_serial_given++; (*present_pixmap_priv)->serial = present_priv->last_serial_given; present_priv->first_present_priv = *present_pixmap_priv; eglBindAPI(current_api); pthread_mutex_unlock(&present_priv->mutex_present); return TRUE; fail: eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglBindAPI(current_api); pthread_mutex_unlock(&present_priv->mutex_present); return FALSE; }
BOOL DRI2FallbackInit(Display *dpy, struct DRI2priv **priv) { PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_func; PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR_func; PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT_func; PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR_func; EGLDisplay display; EGLint major, minor; EGLConfig config; EGLContext context; EGLint i; EGLBoolean b; EGLenum current_api = 0; const char *extensions; EGLint config_attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; EGLint context_compatibility_attribs[] = { EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR, EGL_NONE }; current_api = eglQueryAPI(); eglGetPlatformDisplayEXT_func = (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress("eglGetPlatformDisplayEXT"); if (!eglGetPlatformDisplayEXT_func) return FALSE; display = eglGetPlatformDisplayEXT_func(EGL_PLATFORM_X11_EXT, dpy, NULL); if (!display) return FALSE; if (eglInitialize(display, &major, &minor) != EGL_TRUE) goto clean_egl_display; extensions = eglQueryString(display, EGL_CLIENT_APIS); if (!extensions || !strstr(extensions, "OpenGL")) goto clean_egl_display; extensions = eglQueryString(display, EGL_EXTENSIONS); if (!extensions || !strstr(extensions, "EGL_EXT_image_dma_buf_import") || !strstr(extensions, "EGL_KHR_create_context") || !strstr(extensions, "EGL_KHR_surfaceless_context") || !strstr(extensions, "EGL_KHR_image_base")) goto clean_egl_display; if (!eglChooseConfig(display, config_attribs, &config, 1, &i)) goto clean_egl_display; b = eglBindAPI(EGL_OPENGL_API); if (b == EGL_FALSE) goto clean_egl_display; context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_compatibility_attribs); if (context == EGL_NO_CONTEXT) goto clean_egl_display; glEGLImageTargetTexture2DOES_func = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress("glEGLImageTargetTexture2DOES"); eglCreateImageKHR_func = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); eglDestroyImageKHR_func = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR"); if (!eglCreateImageKHR_func || !glEGLImageTargetTexture2DOES_func || !eglDestroyImageKHR_func) { ERR("eglGetProcAddress failed !"); goto clean_egl_display; } eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); *priv = calloc(1, sizeof(struct DRI2priv)); if (!*priv) goto clean_egl; (*priv)->dpy = dpy; (*priv)->display = display; (*priv)->context = context; (*priv)->glEGLImageTargetTexture2DOES_func = glEGLImageTargetTexture2DOES_func; (*priv)->eglCreateImageKHR_func = eglCreateImageKHR_func; (*priv)->eglDestroyImageKHR_func = eglDestroyImageKHR_func; eglBindAPI(current_api); return TRUE; clean_egl: clean_egl_display: eglTerminate(display); eglBindAPI(current_api); return FALSE; }
BOOL PRESENTPixmap(Display *dpy, XID window, PRESENTPixmapPriv *present_pixmap_priv, D3DPRESENT_PARAMETERS *pPresentationParameters, const RECT *pSourceRect, const RECT *pDestRect, const RGNDATA *pDirtyRegion) { PRESENTpriv *present_priv = present_pixmap_priv->present_priv; #ifdef D3DADAPTER9_DRI2 struct DRI2priv *dri2_priv = present_pixmap_priv->dri2_info.dri2_priv; EGLenum current_api = 0; #endif xcb_void_cookie_t cookie; xcb_generic_error_t *error; int64_t target_msc, presentationInterval; xcb_xfixes_region_t valid, update; int16_t x_off, y_off; uint32_t options = XCB_PRESENT_OPTION_NONE; pthread_mutex_lock(&present_priv->mutex_present); if (window != present_priv->window) PRESENTPrivChangeWindow(present_priv, window); if (!window) { ERR("ERROR: Try to Present a pixmap on a NULL window\n"); pthread_mutex_unlock(&present_priv->mutex_present); return FALSE; } PRESENTflush_events(present_priv, FALSE); if (!present_pixmap_priv->released || present_pixmap_priv->present_complete_pending) { ERR("FATAL ERROR: Trying to Present a pixmap not released\n"); pthread_mutex_unlock(&present_priv->mutex_present); return FALSE; } #ifdef D3DADAPTER9_DRI2 if (present_pixmap_priv->dri2_info.is_dri2) { current_api = eglQueryAPI(); eglBindAPI(EGL_OPENGL_API); if(eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, dri2_priv->context)) { glBindFramebuffer(GL_READ_FRAMEBUFFER, present_pixmap_priv->dri2_info.fbo_read); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, present_pixmap_priv->dri2_info.fbo_write); glBlitFramebuffer(0, 0, present_pixmap_priv->width, present_pixmap_priv->height, 0, 0, present_pixmap_priv->width, present_pixmap_priv->height, GL_COLOR_BUFFER_BIT, GL_NEAREST); glFlush(); /* Perhaps useless */ } else { ERR("eglMakeCurrent failed with 0x%0X\n", eglGetError()); } eglMakeCurrent(dri2_priv->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglBindAPI(current_api); } #endif target_msc = present_priv->last_msc; switch(pPresentationParameters->PresentationInterval) { case D3DPRESENT_INTERVAL_DEFAULT: case D3DPRESENT_INTERVAL_ONE: presentationInterval = 1; break; case D3DPRESENT_INTERVAL_TWO: presentationInterval = 2; break; case D3DPRESENT_INTERVAL_THREE: presentationInterval = 3; break; case D3DPRESENT_INTERVAL_FOUR: presentationInterval = 4; break; case D3DPRESENT_INTERVAL_IMMEDIATE: default: presentationInterval = 0; options |= XCB_PRESENT_OPTION_ASYNC; break; } target_msc += presentationInterval * (present_priv->pixmap_present_pending + 1); /* Note: PRESENT defines some way to do partial copy: * presentproto: * 'x-off' and 'y-off' define the location in the window where * the 0,0 location of the pixmap will be presented. valid-area * and update-area are relative to the pixmap. */ if (!pSourceRect && !pDestRect && !pDirtyRegion) { valid = 0; update = 0; x_off = 0; y_off = 0; } else { xcb_rectangle_t rect_update; xcb_rectangle_t *rect_updates; int i; rect_update.x = 0; rect_update.y = 0; rect_update.width = present_pixmap_priv->width; rect_update.height = present_pixmap_priv->height; x_off = 0; y_off = 0; if (pSourceRect) { x_off = -pSourceRect->left; y_off = -pSourceRect->top; rect_update.x = pSourceRect->left; rect_update.y = pSourceRect->top; rect_update.width = pSourceRect->right - pSourceRect->left; rect_update.height = pSourceRect->bottom - pSourceRect->top; } if (pDestRect) { x_off += pDestRect->left; y_off += pDestRect->top; rect_update.width = pDestRect->right - pDestRect->left; rect_update.height = pDestRect->bottom - pDestRect->top; /* Note: the size of pDestRect and pSourceRect are supposed to be the same size * because the driver would have done things to assure that. */ } valid = xcb_generate_id(present_priv->xcb_connection_bis); update = xcb_generate_id(present_priv->xcb_connection_bis); xcb_xfixes_create_region(present_priv->xcb_connection_bis, valid, 1, &rect_update); if (pDirtyRegion && pDirtyRegion->rdh.nCount) { rect_updates = (void *) calloc(pDirtyRegion->rdh.nCount, sizeof(xcb_rectangle_t)); for (i = 0; i < pDirtyRegion->rdh.nCount; i++) { RECT rc; memcpy(&rc, pDirtyRegion->Buffer + i * sizeof(RECT), sizeof(RECT)); rect_update.x = rc.left; rect_update.y = rc.top; rect_update.width = rc.right - rc.left; rect_update.height = rc.bottom - rc.top; memcpy(rect_updates + i * sizeof(xcb_rectangle_t), &rect_update, sizeof(xcb_rectangle_t)); } xcb_xfixes_create_region(present_priv->xcb_connection_bis, update, pDirtyRegion->rdh.nCount, rect_updates); free(rect_updates); } else xcb_xfixes_create_region(present_priv->xcb_connection_bis, update, 1, &rect_update); } if (pPresentationParameters->SwapEffect == D3DSWAPEFFECT_COPY) options |= XCB_PRESENT_OPTION_COPY; cookie = xcb_present_pixmap_checked(present_priv->xcb_connection_bis, window, present_pixmap_priv->pixmap, present_pixmap_priv->serial, valid, update, x_off, y_off, None, None, None, options, target_msc, 0, 0, 0, NULL); error = xcb_request_check(present_priv->xcb_connection_bis, cookie); /* performs a flush */ if (update) xcb_xfixes_destroy_region(present_priv->xcb_connection_bis, update); if (valid) xcb_xfixes_destroy_region(present_priv->xcb_connection_bis, valid); if (error) { xcb_get_geometry_cookie_t cookie_geom; xcb_get_geometry_reply_t *reply; cookie_geom = xcb_get_geometry(present_priv->xcb_connection_bis, window); reply = xcb_get_geometry_reply(present_priv->xcb_connection_bis, cookie_geom, NULL); ERR("Error using PRESENT. Here some debug info\n"); if (!reply) { ERR("Error querying window info. Perhaps it doesn't exist anymore\n"); pthread_mutex_unlock(&present_priv->mutex_present); return FALSE; } ERR("Pixmap: width=%d, height=%d, depth=%d\n", present_pixmap_priv->width, present_pixmap_priv->height, present_pixmap_priv->depth); ERR("Window: width=%d, height=%d, depth=%d, x=%d, y=%d\n", (int) reply->width, (int) reply->height, (int) reply->depth, (int) reply->x, (int) reply->y); ERR("Present parameter: PresentationInterval=%d, BackBufferCount=%d, Pending presentations=%d\n", pPresentationParameters->PresentationInterval, pPresentationParameters->BackBufferCount, present_priv->pixmap_present_pending ); if (present_pixmap_priv->depth != reply->depth) ERR("Depths are different. PRESENT needs the pixmap and the window have same depth\n"); free(reply); pthread_mutex_unlock(&present_priv->mutex_present); return FALSE; } present_priv->last_target = target_msc; present_priv->pixmap_present_pending++; present_pixmap_priv->present_complete_pending = TRUE; present_pixmap_priv->released = FALSE; pthread_mutex_unlock(&present_priv->mutex_present); return TRUE; }