Beispiel #1
0
/**
 * @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;
}
EXTERN_C_ENTER

JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_GLXSGIVideoSync_nglXGetVideoSyncSGI(JNIEnv *__env, jclass clazz, jlong countAddress, jlong __functionAddress) {
	unsigned int *count = (unsigned int *)(intptr_t)countAddress;
	glXGetVideoSyncSGIPROC glXGetVideoSyncSGI = (glXGetVideoSyncSGIPROC)(intptr_t)__functionAddress;
	UNUSED_PARAMS(__env, clazz)
	return (jint)glXGetVideoSyncSGI(count);
}
Beispiel #3
0
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 SDLWindow::swapBuffers(bool waitForVSync)
    {
        if ( waitForVSync && glXGetVideoSyncSGI && glXWaitVideoSyncSGI )
        {
            unsigned int retraceCount;
            glXGetVideoSyncSGI( &retraceCount );
            glXWaitVideoSyncSGI( 2, ( retraceCount + 1 ) & 1, &retraceCount);
        }

        SDL_GL_SwapBuffers();
        // XXX More?
    }
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #8
0
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();
}
Beispiel #9
0
void gl_thread::run()
{
    if (dispatch::parameters().stereo_mode() == parameters::mode_3DVision)
    {
        Runnable3DVision();
        return;
    }
        
    try {
        assert(_vo_qt_widget->context()->isValid());
        _vo_qt_widget->makeCurrent();
        assert(QGLContext::currentContext() == _vo_qt_widget->context());
        while (_render) {
#if HAVE_X11
            GLuint counter;
            if (GLXEW_SGI_video_sync && glXGetVideoSyncSGI(&counter) == 0)
                _display_frameno = counter;
            else
                _display_frameno++;
#else
            _display_frameno++;
#endif
            // In alternating mode, we should always present both left and right view of
            // a stereo video frame before advancing to the next video frame. This means we
            // can only switch video frames every other output frame.
            if (dispatch::parameters().stereo_mode() != parameters::mode_alternating
                    || _display_frameno % 2 == 0) {
                _wait_mutex.lock();
                if (_action_activate) {
                    try {
                        _vo_qt->video_output::activate_next_frame();
                    }
                    catch (std::exception& e) {
                        _e = e;
                        _render = false;
                        _failure = true;
                    }
                    _action_activate = false;
                    _wait_cond.wake_one();
                    _redisplay = true;
                }
                _wait_mutex.unlock();
            }
            if (_failure)
                break;
            _wait_mutex.lock();
            if (_action_prepare) {
                try {
                    _vo_qt->video_output::prepare_next_frame(_next_frame, _next_subtitle);
                }
                catch (std::exception& e) {
                    _e = e;
                    _render = false;
                    _failure = true;
                }
                _action_prepare = false;
                _wait_cond.wake_one();
            }
            _wait_mutex.unlock();
            if (_failure)
                break;
            if (_w > 0 && _h > 0
                    && (_vo_qt->full_display_width() != _w
                        || _vo_qt->full_display_height() != _h)) {
                _vo_qt->reshape(_w, _h);
                _redisplay = true;
            }
            // In alternating mode, we always need to redisplay
            if (dispatch::parameters().stereo_mode() == parameters::mode_alternating)
                _redisplay = true;
            // If DLP 3-D Ready Sync is active, we always need to redisplay
            if (dispatch::parameters().fullscreen() && dispatch::parameters().fullscreen_3d_ready_sync()
                    && (dispatch::parameters().stereo_mode() == parameters::mode_left_right
                        || dispatch::parameters().stereo_mode() == parameters::mode_left_right_half
                        || dispatch::parameters().stereo_mode() == parameters::mode_top_bottom
                        || dispatch::parameters().stereo_mode() == parameters::mode_top_bottom_half
                        || dispatch::parameters().stereo_mode() == parameters::mode_alternating))
                _redisplay = true;
            // Redisplay if necessary
            if (_redisplay) {
                _redisplay = false;
#if HAVE_LIBXNVCTRL
                _vo_qt->sdi_output(_display_frameno);
#endif // HAVE_LIBXNVCTRL
                _vo_qt->display_current_frame(_display_frameno);
                _vo_qt_widget->swapBuffers();
            } else if (!dispatch::parameters().benchmark()) {
                // do not busy loop
                usleep(1000);
            }
        }
    }
    catch (std::exception& e) {
        _e = e;
        _render = false;
        _failure = true;
    }
    _wait_mutex.lock();
    if (_action_activate || _action_prepare) {
        while (!_action_finished) {
            _wait_cond.wake_one();
            _wait_mutex.unlock();
            _wait_mutex.lock();
        }
    }
    _wait_mutex.unlock();
    _vo_qt_widget->doneCurrent();
#if QT_VERSION >= 0x050000
    _vo_qt_widget->context()->moveToThread(QCoreApplication::instance()->thread());
#endif
}