/** * @return return code of activecontroller draw function * * Draw function repeatedly called, it calls all the * other draw functions */ int SpringApp::Update () { if (FSAA) glEnable(GL_MULTISAMPLE_ARB); mouseInput->Update (); int ret = 1; if(activeController) { if(activeController->Update()==0) ret = 0; else ret = activeController->Draw(); } #ifndef WIN32 if (vsyncFrames > 0) { if (!GLXEW_SGI_video_sync) { vsyncFrames = 0; // disable } else { GLuint frameCount; if (glXGetVideoSyncSGI(&frameCount) == 0) { glXWaitVideoSyncSGI(vsyncFrames, frameCount % vsyncFrames, &frameCount); } } } #endif SDL_GL_SwapBuffers(); if (FSAA) glDisable(GL_MULTISAMPLE_ARB); return ret; }
void render(double dt){ glClear(GL_COLOR_BUFFER_BIT); float x = pos_cat.x; float z = pos_cat.y; bool render = true; animation_t* anim = NULL; switch ( state ){ case CAT_WAIVING: case CAT_IDLE: anim = &animation[ANIM_WAIVING]; break; case CAT_WALKING: { const pos_t delta = pos_cat_next - pos_cat; x = (float)delta.x * step + pos_cat.x; z = (float)delta.y * step + pos_cat.y; /* left or right? */ if ( delta.x > 0 ){ anim = &animation[ANIM_WALKING_EAST]; } else if ( delta.x < 0 ){ anim = &animation[ANIM_WALKING_WEST]; } else if ( delta.y > 0 ){ anim = &animation[ANIM_WALKING_NORTH]; } else if ( delta.y < 0 ){ anim = &animation[ANIM_WALKING_SOUTH]; } } break; case CAT_FROBNICATING: case CAT_FRIST: render = false; break; default: printf("default\n"); break; } if ( render ){ render_cat(anim, x, z, dt); } #ifdef VSYNC unsigned int retraceCount; glXGetVideoSyncSGI(&retraceCount); glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount); #endif SDL_GL_SwapBuffers(); }
void openGL_sync_with_raster(void) { extern int glXWaitVideoSyncSGI(int m, int d, unsigned int *c); int r; unsigned int c; if (openGL_sync && !no_sync) if ((r = glXWaitVideoSyncSGI(mult, 0, &c))) log_error(openGL_log, "glXWaitVideoSyncSGI() returned %d", r); }
void SDLWindow::swapBuffers(bool waitForVSync) { if ( waitForVSync && glXGetVideoSyncSGI && glXWaitVideoSyncSGI ) { unsigned int retraceCount; glXGetVideoSyncSGI( &retraceCount ); glXWaitVideoSyncSGI( 2, ( retraceCount + 1 ) & 1, &retraceCount); } SDL_GL_SwapBuffers(); // XXX More? }
static bool xdpy_wait_for_vsync(ALLEGRO_DISPLAY *display) { (void) display; if (al_get_opengl_extension_list()->ALLEGRO_GLX_SGI_video_sync) { unsigned int count; glXGetVideoSyncSGI(&count); glXWaitVideoSyncSGI(2, (count+1) & 1, &count); return true; } return false; }
void GlxBackend::waitSync() { // NOTE that vsync has no effect with indirect rendering if (haveWaitSync) { uint sync; #if 0 // TODO: why precisely is this important? // the sync counter /can/ perform multiple steps during glXGetVideoSync & glXWaitVideoSync // but this only leads to waiting for two frames??!? glXGetVideoSync(&sync); glXWaitVideoSync(2, (sync + 1) % 2, &sync); #else glXWaitVideoSyncSGI(1, 0, &sync); #endif } }
static PyObject* opengl_init( PyObject* self, PyObject* args ) { GL_ERROR_CHECK("top of opengl_init"); printf( " vendor : %s\n", glGetString( GL_VENDOR ) ); printf( " renderer : %s\n", glGetString( GL_RENDERER ) ); printf( " version : %s\n", glGetString( GL_VERSION ) ); printf( "glu version : %s\n", gluGetString( GLU_VERSION ) ); /*printf( "extensions : %s\n", glGetString( GL_EXTENSIONS ) );*/ glewExperimental=GL_TRUE; GLenum err = glewInit(); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ printf("Error: %s\n", glewGetErrorString(err)); } printf("Status: Using GLEW %s\n", glewGetString(GLEW_VERSION)); if (glewIsSupported("GLX_SGI_swap_control")) { /* It is safe to use the ARB_vertex_program extension here. */ printf("GLX_SGI_swap_control supported!\n"); //glXSwapIntervalSGI(1); } else { printf("No GLX_SGI_swap_control support.\n"); } if (glewIsSupported("GLX_SGI_video_sync")) { /* It is safe to use the ARB_vertex_program extension here. */ printf("GLX_SGI_video_sync supported!\n"); //glXSwapIntervalSGI(1); int retraceCount; glXGetVideoSyncSGI(&retraceCount); glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount); } else { printf("GLX_SGI_video_sync support.\n"); int c; //__glewXWaitVideoSyncSGI(5,0,&c); } glEnable( GL_VERTEX_ARRAY ); /* on mac, we expect that to fail; must be enabled as client state instead, */ if(glGetError() != GL_NO_ERROR) { glEnableClientState( GL_VERTEX_ARRAY ); GL_ERROR_CHECK( "enable client gl_vertex_array" ); } glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_DEPTH_TEST ); glDepthFunc( GL_ALWAYS ); glClearDepth( 0.0 ); GL_ERROR_CHECK( "end of opengl_init" ); //glEnable( GL_POLYGON_SMOOTH ); Py_INCREF( Py_None ); return Py_None; }
static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) { IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; struct wined3d_context *context; RECT src_rect, dst_rect; BOOL render_to_fbo; unsigned int sync; int retval; #ifdef VBOX_WITH_WDDM /* quickly sort out invalid swapchains */ if (!This->hDC) { WARN("Invalid swapchain"); return WINED3D_OK; } #endif IWineD3DSwapChain_SetDestWindowOverride(iface, hDestWindowOverride); context = context_acquire(This->device, This->backBuffer[0], CTXUSAGE_RESOURCELOAD); if (!context->valid) { context_release(context); WARN("Invalid context, skipping present.\n"); return WINED3D_OK; } /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ if (This->device->bCursorVisible && This->device->cursorTexture) { IWineD3DSurfaceImpl cursor; RECT destRect = { This->device->xScreenSpace - This->device->xHotSpot, This->device->yScreenSpace - This->device->yHotSpot, This->device->xScreenSpace + This->device->cursorWidth - This->device->xHotSpot, This->device->yScreenSpace + This->device->cursorHeight - This->device->yHotSpot, }; TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor); /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by * the application because we are only supposed to copy the information out. Using a fake surface * allows to use the Blitting engine and avoid copying the whole texture -> render target blitting code. */ memset(&cursor, 0, sizeof(cursor)); cursor.lpVtbl = &IWineD3DSurface_Vtbl; cursor.resource.ref = 1; cursor.resource.device = This->device; cursor.resource.pool = WINED3DPOOL_SCRATCH; cursor.resource.format_desc = getFormatDescEntry(WINED3DFMT_B8G8R8A8_UNORM, context->gl_info); cursor.resource.resourceType = WINED3DRTYPE_SURFACE; cursor.texture_name = This->device->cursorTexture; cursor.texture_target = GL_TEXTURE_2D; cursor.texture_level = 0; cursor.currentDesc.Width = This->device->cursorWidth; cursor.currentDesc.Height = This->device->cursorHeight; /* The cursor must have pow2 sizes */ cursor.pow2Width = cursor.currentDesc.Width; cursor.pow2Height = cursor.currentDesc.Height; /* The surface is in the texture */ cursor.Flags |= SFLAG_INTEXTURE; /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0, * which is exactly what we want :-) */ if (This->presentParms.Windowed) { #ifdef VBOX_WITH_WDDM /* @todo: can we actualy be here? */ #endif MapWindowPoints(NULL, This->win_handle, (LPPOINT)&destRect, 2); } IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *)&cursor, NULL, WINEDDBLT_KEYSRC, NULL, WINED3DTEXF_POINT); } if (This->device->logo_surface) { /* Blit the logo into the upper left corner of the drawable. */ IWineD3DSurface_BltFast(This->backBuffer[0], 0, 0, This->device->logo_surface, NULL, WINEDDBLTFAST_SRCCOLORKEY); } #ifdef VBOX_WITH_WDDM TRACE("Presenting HDC %p.\n", context->currentSwapchain->hDC); #else TRACE("Presenting HDC %p.\n", context->hdc); #endif render_to_fbo = This->render_to_fbo; if (pSourceRect) { src_rect = *pSourceRect; if (!render_to_fbo && (src_rect.left || src_rect.top || src_rect.right != This->presentParms.BackBufferWidth || src_rect.bottom != This->presentParms.BackBufferHeight)) { render_to_fbo = TRUE; } } else { src_rect.left = 0; src_rect.top = 0; src_rect.right = This->presentParms.BackBufferWidth; src_rect.bottom = This->presentParms.BackBufferHeight; } if (pDestRect) dst_rect = *pDestRect; #ifndef VBOX_WITH_WDDM else GetClientRect(This->win_handle, &dst_rect); if (!render_to_fbo && (dst_rect.left || dst_rect.top || dst_rect.right != This->presentParms.BackBufferWidth || dst_rect.bottom != This->presentParms.BackBufferHeight)) { render_to_fbo = TRUE; } #else else { dst_rect.left = 0; dst_rect.top = 0; dst_rect.right = This->presentParms.BackBufferWidth; dst_rect.bottom = This->presentParms.BackBufferHeight; } #endif /* Rendering to a window of different size, presenting partial rectangles, * or rendering to a different window needs help from FBO_blit or a textured * draw. Render the swapchain to a FBO in the future. * * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve * all these issues - this fails if the window is smaller than the backbuffer. */ if (!This->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO) { IWineD3DSurface_LoadLocation(This->backBuffer[0], SFLAG_INTEXTURE, NULL); IWineD3DSurface_ModifyLocation(This->backBuffer[0], SFLAG_INDRAWABLE, FALSE); This->render_to_fbo = TRUE; /* Force the context manager to update the render target configuration next draw. */ context->current_rt = NULL; } if(This->render_to_fbo) { /* This codepath should only be hit with the COPY swapeffect. Otherwise a backbuffer- * window size mismatch is impossible(fullscreen) and src and dst rectangles are * not allowed(they need the COPY swapeffect) * * The DISCARD swap effect is ok as well since any backbuffer content is allowed after * the swap */ if(This->presentParms.SwapEffect == WINED3DSWAPEFFECT_FLIP ) { FIXME("Render-to-fbo with WINED3DSWAPEFFECT_FLIP\n"); } swapchain_blit(This, context, &src_rect, &dst_rect); } #ifdef VBOX_WITH_WDDM if (This->device->numContexts > 1) wglFinish(); #else if (This->num_contexts > 1) wglFinish(); #endif #if defined(VBOX_WITH_WDDM) && defined(DEBUG) { HWND wnd = WindowFromDC(context->currentSwapchain->hDC); Assert(wnd == context->currentSwapchain->win_handle); } #endif #ifdef VBOX_WITH_WDDM /* We're directly using wglMakeCurrent calls skipping GDI layer, which causes GDI SwapBuffers to fail trying to * call glFinish, which doesn't have any context set. So we use wglSwapLayerBuffers directly as well. */ pwglSwapLayerBuffers(context->currentSwapchain->hDC, WGL_SWAP_MAIN_PLANE); #else # ifdef VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT pwglSwapLayerBuffers(context->hdc, WGL_SWAP_MAIN_PLANE); # else SwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */ # endif #endif TRACE("SwapBuffers called, Starting new frame\n"); /* FPS support */ if (TRACE_ON(fps)) { DWORD time = GetTickCount(); This->frames++; /* every 1.5 seconds */ if (time - This->prev_time > 1500) { TRACE_(fps)("%p @ approx %.2ffps\n", This, 1000.0*This->frames/(time - This->prev_time)); This->prev_time = time; This->frames = 0; } } #if defined(FRAME_DEBUGGING) { if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) { if (!isOn) { isOn = TRUE; FIXME("Enabling D3D Trace\n"); __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1); #if defined(SHOW_FRAME_MAKEUP) FIXME("Singe Frame snapshots Starting\n"); isDumpingFrames = TRUE; ENTER_GL(); glClear(GL_COLOR_BUFFER_BIT); LEAVE_GL(); #endif #if defined(SINGLE_FRAME_DEBUGGING) } else { #if defined(SHOW_FRAME_MAKEUP) FIXME("Singe Frame snapshots Finishing\n"); isDumpingFrames = FALSE; #endif FIXME("Singe Frame trace complete\n"); DeleteFileA("C:\\D3DTRACE"); __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); #endif } } else { if (isOn) { isOn = FALSE; #if defined(SHOW_FRAME_MAKEUP) FIXME("Single Frame snapshots Finishing\n"); isDumpingFrames = FALSE; #endif FIXME("Disabling D3D Trace\n"); __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0); } } } #endif /* This is disabled, but the code left in for debug purposes. * * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip, * we can clear it with some ugly color to make bad drawing visible and ease debugging. * The Debug runtime does the same on Windows. However, a few games do not redraw the * screen properly, like Max Payne 2, which leaves a few pixels undefined. * * Tests show that the content of the back buffer after a discard flip is indeed not * reliable, so no game can depend on the exact content. However, it resembles the * old contents in some way, for example by showing fragments at other locations. In * general, the color theme is still intact. So Max payne, which draws rather dark scenes * gets a dark background image. If we clear it with a bright ugly color, the game's * bug shows up much more than it does on Windows, and the players see single pixels * with wrong colors. * (The Max Payne bug has been confirmed on Windows with the debug runtime) */ if (FALSE && This->presentParms.SwapEffect == WINED3DSWAPEFFECT_DISCARD) { TRACE("Clearing the color buffer with cyan color\n"); IWineD3DDevice_Clear((IWineD3DDevice *)This->device, 0, NULL, WINED3DCLEAR_TARGET, 0xff00ffff, 1.0f, 0); } if(!This->render_to_fbo && ( ((IWineD3DSurfaceImpl *) This->frontBuffer)->Flags & SFLAG_INSYSMEM || ((IWineD3DSurfaceImpl *) This->backBuffer[0])->Flags & SFLAG_INSYSMEM ) ) { /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying * Doesn't work with render_to_fbo because we're not flipping */ IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer; IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0]; if(front->resource.size == back->resource.size) { DWORD fbflags; flip_surface(front, back); /* Tell the front buffer surface that is has been modified. However, * the other locations were preserved during that, so keep the flags. * This serves to update the emulated overlay, if any */ fbflags = front->Flags; IWineD3DSurface_ModifyLocation(This->frontBuffer, SFLAG_INDRAWABLE, TRUE); front->Flags = fbflags; } else { IWineD3DSurface_ModifyLocation((IWineD3DSurface *) front, SFLAG_INDRAWABLE, TRUE); IWineD3DSurface_ModifyLocation((IWineD3DSurface *) back, SFLAG_INDRAWABLE, TRUE); } } else { IWineD3DSurface_ModifyLocation(This->frontBuffer, SFLAG_INDRAWABLE, TRUE); /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM * and INTEXTURE copies can keep their old content if they have any defined content. * If the swapeffect is COPY, the content remains the same. If it is FLIP however, * the texture / sysmem copy needs to be reloaded from the drawable */ if(This->presentParms.SwapEffect == WINED3DSWAPEFFECT_FLIP) { IWineD3DSurface_ModifyLocation(This->backBuffer[0], SFLAG_INDRAWABLE, TRUE); } } if (This->device->stencilBufferTarget) { if (This->presentParms.Flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL || ((IWineD3DSurfaceImpl *)This->device->stencilBufferTarget)->Flags & SFLAG_DISCARD) { surface_modify_ds_location(This->device->stencilBufferTarget, SFLAG_DS_DISCARDED); } } if (This->presentParms.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE && context->gl_info->supported[SGI_VIDEO_SYNC]) { retval = GL_EXTCALL(glXGetVideoSyncSGI(&sync)); if(retval != 0) { ERR("glXGetVideoSyncSGI failed(retval = %d\n", retval); } switch(This->presentParms.PresentationInterval) { case WINED3DPRESENT_INTERVAL_DEFAULT: case WINED3DPRESENT_INTERVAL_ONE: if(sync <= This->vSyncCounter) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(1, 0, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; case WINED3DPRESENT_INTERVAL_TWO: if(sync <= This->vSyncCounter + 1) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(2, This->vSyncCounter & 0x1, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; case WINED3DPRESENT_INTERVAL_THREE: if(sync <= This->vSyncCounter + 2) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(3, This->vSyncCounter % 0x3, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; case WINED3DPRESENT_INTERVAL_FOUR: if(sync <= This->vSyncCounter + 3) { retval = GL_EXTCALL(glXWaitVideoSyncSGI(4, This->vSyncCounter & 0x3, &This->vSyncCounter)); } else { This->vSyncCounter = sync; } break; default: FIXME("Unknown presentation interval %08x\n", This->presentParms.PresentationInterval); } } context_release(context); TRACE("returning\n"); return WINED3D_OK; }
void GlxBackend::init() { initGLX(); // Require at least GLX 1.3 if (!hasGLXVersion(1, 3)) { setFailed(QStringLiteral("Requires at least GLX 1.3")); return; } initVisualDepthHashTable(); if (!initBuffer()) { setFailed(QStringLiteral("Could not initialize the buffer")); return; } if (!initRenderingContext()) { setFailed(QStringLiteral("Could not initialize rendering context")); return; } // Initialize OpenGL GLPlatform *glPlatform = GLPlatform::instance(); glPlatform->detect(GlxPlatformInterface); if (GLPlatform::instance()->driver() == Driver_Intel) options->setUnredirectFullscreen(false); // bug #252817 options->setGlPreferBufferSwap(options->glPreferBufferSwap()); // resolve autosetting if (options->glPreferBufferSwap() == Options::AutoSwapStrategy) options->setGlPreferBufferSwap('e'); // for unknown drivers - should not happen glPlatform->printResults(); initGL(GlxPlatformInterface); // Check whether certain features are supported m_haveMESACopySubBuffer = hasGLExtension(QByteArrayLiteral("GLX_MESA_copy_sub_buffer")); m_haveMESASwapControl = hasGLExtension(QByteArrayLiteral("GLX_MESA_swap_control")); m_haveEXTSwapControl = hasGLExtension(QByteArrayLiteral("GLX_EXT_swap_control")); m_haveSGISwapControl = hasGLExtension(QByteArrayLiteral("GLX_SGI_swap_control")); // only enable Intel swap event if env variable is set, see BUG 342582 m_haveINTELSwapEvent = hasGLExtension(QByteArrayLiteral("GLX_INTEL_swap_event")) && qgetenv("KWIN_USE_INTEL_SWAP_EVENT") == QByteArrayLiteral("1"); if (m_haveINTELSwapEvent) { m_swapEventFilter = std::make_unique<SwapEventFilter>(window, glxWindow); glXSelectEvent(display(), glxWindow, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } haveSwapInterval = m_haveMESASwapControl || m_haveEXTSwapControl || m_haveSGISwapControl; setSupportsBufferAge(false); if (hasGLExtension(QByteArrayLiteral("GLX_EXT_buffer_age"))) { const QByteArray useBufferAge = qgetenv("KWIN_USE_BUFFER_AGE"); if (useBufferAge != "0") setSupportsBufferAge(true); } setSyncsToVBlank(false); setBlocksForRetrace(false); haveWaitSync = false; gs_tripleBufferNeedsDetection = false; m_swapProfiler.init(); const bool wantSync = options->glPreferBufferSwap() != Options::NoSwapEncourage; if (wantSync && glXIsDirect(display(), ctx)) { if (haveSwapInterval) { // glXSwapInterval is preferred being more reliable setSwapInterval(1); setSyncsToVBlank(true); const QByteArray tripleBuffer = qgetenv("KWIN_TRIPLE_BUFFER"); if (!tripleBuffer.isEmpty()) { setBlocksForRetrace(qstrcmp(tripleBuffer, "0") == 0); gs_tripleBufferUndetected = false; } gs_tripleBufferNeedsDetection = gs_tripleBufferUndetected; } else if (hasGLExtension(QByteArrayLiteral("GLX_SGI_video_sync"))) { unsigned int sync; if (glXGetVideoSyncSGI(&sync) == 0 && glXWaitVideoSyncSGI(1, 0, &sync) == 0) { setSyncsToVBlank(true); setBlocksForRetrace(true); haveWaitSync = true; } else qCWarning(KWIN_CORE) << "NO VSYNC! glXSwapInterval is not supported, glXWaitVideoSync is supported but broken"; } else qCWarning(KWIN_CORE) << "NO VSYNC! neither glSwapInterval nor glXWaitVideoSync are supported"; } else { // disable v-sync (if possible) setSwapInterval(0); } if (glPlatform->isVirtualBox()) { // VirtualBox does not support glxQueryDrawable // this should actually be in kwinglutils_funcs, but QueryDrawable seems not to be provided by an extension // and the GLPlatform has not been initialized at the moment when initGLX() is called. glXQueryDrawable = NULL; } setIsDirectRendering(bool(glXIsDirect(display(), ctx))); qCDebug(KWIN_CORE) << "Direct rendering:" << isDirectRendering(); }
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_GLXSGIVideoSync_nglXWaitVideoSyncSGI(JNIEnv *__env, jclass clazz, jint divisor, jint remainder, jlong countAddress, jlong __functionAddress) { unsigned int *count = (unsigned int *)(intptr_t)countAddress; glXWaitVideoSyncSGIPROC glXWaitVideoSyncSGI = (glXWaitVideoSyncSGIPROC)(intptr_t)__functionAddress; UNUSED_PARAMS(__env, clazz) return (jint)glXWaitVideoSyncSGI(divisor, remainder, count); }