예제 #1
1
파일: aa.c 프로젝트: chouquette/vlc
/**
 * Control for vout display
 */
static int Control(vout_display_t *vd, int query, va_list args)
{
    VLC_UNUSED(args);
    vout_display_sys_t *sys = vd->sys;

    switch (query) {
    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
        /* We have to ignore what is requested */
        vout_display_SendEventPicturesInvalid(vd);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_RESET_PICTURES:
        if (sys->pool)
            picture_pool_Release(sys->pool);
        sys->pool = NULL;

        vd->fmt.i_width  = aa_imgwidth(sys->aa_context);
        vd->fmt.i_height = aa_imgheight(sys->aa_context);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_HIDE_MOUSE:
        aa_hidemouse(sys->aa_context);
        return VLC_SUCCESS;

    default:
        msg_Err(vd, "Unsupported query in vout display aalib");
        return VLC_EGENERIC;
    }
}
예제 #2
0
static void Manage(vout_display_t *vd)
{
    vout_display_sys_t *sys = vd->sys;

    CommonManage(vd);

    if (sys->changes & DX_POSITION_CHANGE) {
        /* Update overlay */
        if (sys->use_overlay)
            DirectXUpdateOverlay(vd, NULL);

        /* Check if we are still on the same monitor */
        HMONITOR hmon = MonitorFromWindow(sys->hwnd, MONITOR_DEFAULTTONEAREST);
        if (sys->hmonitor != hmon) {
            vout_display_SendEventPicturesInvalid(vd);
        }
        /* */
        sys->changes &= ~DX_POSITION_CHANGE;
    }

    /* Wallpaper mode change */
    vlc_mutex_lock(&sys->lock);
    const bool ch_wallpaper = sys->ch_wallpaper;
    const bool wallpaper_requested = sys->wallpaper_requested;
    sys->ch_wallpaper = false;
    vlc_mutex_unlock(&sys->lock);

    if (ch_wallpaper)
        WallpaperChange(vd, wallpaper_requested);

    /* */
    if (sys->restore_overlay)
        DirectXUpdateOverlay(vd, NULL);
}
예제 #3
0
파일: evas.c 프로젝트: chouquette/vlc
static int
Control( vout_display_t *vd, int i_query, va_list ap )
{
    vout_display_sys_t *sys = vd->sys;

    switch( i_query )
    {
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
    {
        const video_format_t *p_source;
        vout_display_place_t place;
        video_format_t fmt;

        msg_Dbg( vd, "VOUT_DISPLAY_CHANGE_SOURCE_ASPECT" );

        p_source = va_arg( ap, const video_format_t * );

        video_format_ApplyRotation( &fmt, p_source );
        vout_display_PlacePicture( &place, &fmt, vd->cfg, false );

        if( place.width != (unsigned) sys->i_width
         && place.height != (unsigned) sys->i_height )
        {
            if( vd->info.has_pictures_invalid )
            {
                msg_Warn( vd, "ratio changed: invalidate pictures" );
                vout_display_SendEventPicturesInvalid( vd );
            }
            else
                return VLC_EGENERIC;
        }
        return VLC_SUCCESS;
    }
    case VOUT_DISPLAY_CHANGE_FULLSCREEN:
        return VLC_SUCCESS;
    case VOUT_DISPLAY_RESET_PICTURES:
        msg_Dbg( vd, "VOUT_DISPLAY_RESET_PICTURES" );

        EcoreMainLoopCallSync( vd, EvasResetMainloopCb );

        BuffersClean( vd );

        if( sys->p_pool )
        {
            picture_pool_Release( sys->p_pool );
            sys->p_pool = NULL;
        }
        return VLC_SUCCESS;
    case VOUT_DISPLAY_CHANGE_ZOOM:
    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
    case VOUT_DISPLAY_HIDE_MOUSE:
        return VLC_EGENERIC;
    default:
        msg_Warn( vd, "Unknown request in evas_output" );
        return VLC_EGENERIC;
    }
}
예제 #4
0
파일: direct3d.c 프로젝트: asdlei00/vlc-2.1
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
{
    vout_display_sys_t *sys = vd->sys;
    LPDIRECT3DSURFACE9 surface = picture->p_sys->surface;
#if 0
    picture_Release(picture);
    VLC_UNUSED(subpicture);
#else
    /* FIXME it is a bit ugly, we need the surface to be unlocked for
     * rendering.
     *  The clean way would be to release the picture (and ensure that
     * the vout doesn't keep a reference). But because of the vout
     * wrapper, we can't */

    Direct3DUnlockSurface(picture);
    VLC_UNUSED(subpicture);
#endif

    /* check if device is still available */
    HRESULT hr = IDirect3DDevice9_TestCooperativeLevel(sys->d3ddev);
    if (FAILED(hr)) {
        if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) {
            vout_display_SendEventPicturesInvalid(vd);
            sys->reset_device = true;
            sys->lost_not_ready = false;
        }
        if (hr == D3DERR_DEVICELOST && !sys->lost_not_ready) {
            /* Device is lost but not yet ready for reset. */
            sys->lost_not_ready = true;
        }
        return;
    }

    d3d_region_t picture_region;
    if (!Direct3DImportPicture(vd, &picture_region, surface)) {
        int subpicture_region_count     = 0;
        d3d_region_t *subpicture_region = NULL;
        if (subpicture)
            Direct3DImportSubpicture(vd, &subpicture_region_count, &subpicture_region,
                                     subpicture);

        Direct3DRenderScene(vd, &picture_region,
                            subpicture_region_count, subpicture_region);

        Direct3DDeleteRegions(sys->d3dregion_count, sys->d3dregion);
        sys->d3dregion_count = subpicture_region_count;
        sys->d3dregion       = subpicture_region;
    }
}
예제 #5
0
static void Manage (vout_display_t *vd)
{
    vout_display_sys_t *sys = vd->sys;

    CommonManage(vd);

    /* Desktop mode change */
    vlc_mutex_lock(&sys->lock);
    const bool ch_desktop = sys->ch_desktop;
    sys->ch_desktop = false;
    vlc_mutex_unlock(&sys->lock);

    if (ch_desktop) {
        sys->reopen_device = true;
        vout_display_SendEventPicturesInvalid(vd);
    }

#if 0
    /*
     * Position Change
     */
    if (sys->changes & DX_POSITION_CHANGE) {
#if 0 /* need that when bicubic filter is available */
        RECT rect;
        UINT width, height;

        GetClientRect(p_sys->hvideownd, &rect);
        width  = rect.right-rect.left;
        height = rect.bottom-rect.top;

        if (width != p_sys->d3dpp.BackBufferWidth || height != p_sys->d3dpp.BackBufferHeight)
        {
            msg_Dbg(vd, "resizing device back buffers to (%lux%lu)", width, height);
            // need to reset D3D device to resize back buffer
            if (VLC_SUCCESS != Direct3DResetDevice(vd, width, height))
                return VLC_EGENERIC;
        }
#endif
        sys->changes &= ~DX_POSITION_CHANGE;
    }
#endif
}
예제 #6
0
파일: sdl.c 프로젝트: shanewfx/vlc-arib
/**
 * Control for vout display
 */
static int Control(vout_display_t *vd, int query, va_list args)
{
    vout_display_sys_t *sys = vd->sys;

    switch (query)
    {
    case VOUT_DISPLAY_HIDE_MOUSE:
        SDL_ShowCursor(0);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);

        /* */
        sys->display = SDL_SetVideoMode(cfg->display.width,
                                        cfg->display.height,
                                        sys->display_bpp, sys->display_flags);
        if (!sys->display) {
            sys->display = SDL_SetVideoMode(vd->cfg->display.width,
                                            vd->cfg->display.height,
                                            sys->display_bpp, sys->display_flags);
            return VLC_EGENERIC;
        }
        if (sys->overlay)
            vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay);
        else
            vout_display_SendEventPicturesInvalid(vd);
        return VLC_SUCCESS;
    }
    case VOUT_DISPLAY_CHANGE_FULLSCREEN: {
        vout_display_cfg_t cfg = *va_arg(args, const vout_display_cfg_t *);

        /* Fix flags */
        sys->display_flags &= ~(SDL_FULLSCREEN | SDL_RESIZABLE);
        sys->display_flags |= cfg.is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;

        if (cfg.is_fullscreen) {
            cfg.display.width = sys->desktop_width;
            cfg.display.height = sys->desktop_height;
        }

        if (sys->overlay) {
            sys->display = SDL_SetVideoMode(cfg.display.width, cfg.display.height,
                                            sys->display_bpp, sys->display_flags);

            vout_display_PlacePicture(&sys->place, &vd->source, &cfg, !sys->overlay);
        }
        vout_display_SendEventDisplaySize(vd, cfg.display.width, cfg.display.height, cfg.is_fullscreen);
        return VLC_SUCCESS;
    }
    case VOUT_DISPLAY_CHANGE_ZOOM:
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: {
        const vout_display_cfg_t *cfg;
        const video_format_t *source;

        if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
            source = va_arg(args, const video_format_t *);
            cfg = vd->cfg;
        } else {
            source = &vd->source;
            cfg = va_arg(args, const vout_display_cfg_t *);
        }
        if (sys->overlay) {
            sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height,
                                            sys->display_bpp, sys->display_flags);

            vout_display_PlacePicture(&sys->place, source, cfg, !sys->overlay);
        } else {
            vout_display_SendEventPicturesInvalid(vd);
        }
        return VLC_SUCCESS;
    }
예제 #7
0
/**
 * It copies picture surface into a texture and renders into a scene.
 *
 * This function is intented for higher end 3D cards, with pixel shader support
 * and at least 64 MiB of video RAM.
 */
static void Direct3DRenderScene(vout_display_t *vd, LPDIRECT3DSURFACE9 surface)
{
    vout_display_sys_t *sys = vd->sys;
    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
    HRESULT hr;

    // check if device is still available
    hr = IDirect3DDevice9_TestCooperativeLevel(d3ddev);
    if (FAILED(hr)) {
        if (hr == D3DERR_DEVICENOTRESET && !sys->reset_device) {
            vout_display_SendEventPicturesInvalid(vd);
            sys->reset_device = true;
        }
        return;
    }
    /* */
    LPDIRECT3DTEXTURE9      d3dtex  = sys->d3dtex;
    LPDIRECT3DVERTEXBUFFER9 d3dvtc  = sys->d3dvtc;

    /* Clear the backbuffer and the zbuffer */
    hr = IDirect3DDevice9_Clear(d3ddev, 0, NULL, D3DCLEAR_TARGET,
                              D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }
    /*  retrieve picture surface */
    LPDIRECT3DSURFACE9 d3dsrc = surface;
    if (!d3dsrc) {
        msg_Dbg(vd, "no surface to render ?");
        return;
    }

    /* retrieve texture top-level surface */
    LPDIRECT3DSURFACE9 d3ddest;
    hr = IDirect3DTexture9_GetSurfaceLevel(d3dtex, 0, &d3ddest);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }

    /* Copy picture surface into texture surface
     * color space conversion and scaling happen here */
    RECT src = vd->sys->rect_src_clipped;
    RECT dst = vd->sys->rect_dest_clipped;

    hr = IDirect3DDevice9_StretchRect(d3ddev, d3dsrc, &src, d3ddest, &dst, D3DTEXF_LINEAR);
    IDirect3DSurface9_Release(d3ddest);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }

    /* Update the vertex buffer */
    CUSTOMVERTEX *vertices;
    hr = IDirect3DVertexBuffer9_Lock(d3dvtc, 0, 0, (void **)&vertices, D3DLOCK_DISCARD);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }

    /* Setup vertices */
    const float f_width  = vd->sys->d3dpp.BackBufferWidth;
    const float f_height = vd->sys->d3dpp.BackBufferHeight;

    /* -0.5f is a "feature" of DirectX and it seems to apply to Direct3d also */
    /* http://www.sjbrown.co.uk/2003/05/01/fix-directx-rasterisation/ */
    vertices[0].x       = -0.5f;       // left
    vertices[0].y       = -0.5f;       // top
    vertices[0].z       = 0.0f;
    vertices[0].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
    vertices[0].rhw     = 1.0f;
    vertices[0].tu      = 0.0f;
    vertices[0].tv      = 0.0f;

    vertices[1].x       = f_width - 0.5f;    // right
    vertices[1].y       = -0.5f;       // top
    vertices[1].z       = 0.0f;
    vertices[1].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
    vertices[1].rhw     = 1.0f;
    vertices[1].tu      = 1.0f;
    vertices[1].tv      = 0.0f;

    vertices[2].x       = f_width - 0.5f;    // right
    vertices[2].y       = f_height - 0.5f;   // bottom
    vertices[2].z       = 0.0f;
    vertices[2].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
    vertices[2].rhw     = 1.0f;
    vertices[2].tu      = 1.0f;
    vertices[2].tv      = 1.0f;

    vertices[3].x       = -0.5f;       // left
    vertices[3].y       = f_height - 0.5f;   // bottom
    vertices[3].z       = 0.0f;
    vertices[3].diffuse = D3DCOLOR_ARGB(255, 255, 255, 255);
    vertices[3].rhw     = 1.0f;
    vertices[3].tu      = 0.0f;
    vertices[3].tv      = 1.0f;

    hr= IDirect3DVertexBuffer9_Unlock(d3dvtc);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }

    // Begin the scene
    hr = IDirect3DDevice9_BeginScene(d3ddev);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }

    // Setup our texture. Using textures introduces the texture stage states,
    // which govern how textures get blended together (in the case of multiple
    // textures) and lighting information. In this case, we are modulating
    // (blending) our texture with the diffuse color of the vertices.
    hr = IDirect3DDevice9_SetTexture(d3ddev, 0, (LPDIRECT3DBASETEXTURE9)d3dtex);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        IDirect3DDevice9_EndScene(d3ddev);
        return;
    }

    // Render the vertex buffer contents
    hr = IDirect3DDevice9_SetStreamSource(d3ddev, 0, d3dvtc, 0, sizeof(CUSTOMVERTEX));
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        IDirect3DDevice9_EndScene(d3ddev);
        return;
    }

    // we use FVF instead of vertex shader
    hr = IDirect3DDevice9_SetFVF(d3ddev, D3DFVF_CUSTOMVERTEX);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        IDirect3DDevice9_EndScene(d3ddev);
        return;
    }

    // draw rectangle
    hr = IDirect3DDevice9_DrawPrimitive(d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        IDirect3DDevice9_EndScene(d3ddev);
        return;
    }

    // End the scene
    hr = IDirect3DDevice9_EndScene(d3ddev);
    if (FAILED(hr)) {
        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
        return;
    }
}
예제 #8
0
파일: x11.c 프로젝트: Annovae/vlc
static int Control (vout_display_t *vd, int query, va_list ap)
{
    vout_display_sys_t *sys = vd->sys;

    switch (query)
    {
    case VOUT_DISPLAY_CHANGE_FULLSCREEN:
    {
        const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *);
        return vout_window_SetFullScreen (sys->embed, c->is_fullscreen);
    }

    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
    {
        const vout_display_cfg_t *p_cfg =
            (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
        const bool is_forced = (bool)va_arg (ap, int);

        if (is_forced)
        {   /* Changing the dimensions of the parent window takes place
             * asynchronously (in the X server). Also it might fail or result
             * in different dimensions than requested. Request the size change
             * and return a failure since the size is not (yet) changed.
             * If the change eventually succeeds, HandleParentStructure()
             * will trigger a non-forced display size change later. */
            vout_window_SetSize (sys->embed, p_cfg->display.width,
                                 p_cfg->display.height);
            return VLC_EGENERIC;
        }

        vout_display_place_t place;
        vout_display_PlacePicture (&place, &vd->source, p_cfg, false);

        if (place.width  != vd->fmt.i_visible_width ||
            place.height != vd->fmt.i_visible_height)
        {
            vout_display_SendEventPicturesInvalid (vd);
            return VLC_SUCCESS;
        }

        /* Move the picture within the window */
        const uint32_t values[] = { place.x, place.y };
        xcb_configure_window (sys->conn, sys->window,
                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
                              values);
        return VLC_SUCCESS;
    }
    case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
    {
        unsigned state = va_arg (ap, unsigned);
        return vout_window_SetState (sys->embed, state);
    }

    case VOUT_DISPLAY_CHANGE_ZOOM:
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
        /* I am not sure it is always necessary, but it is way simpler ... */
        vout_display_SendEventPicturesInvalid (vd);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_RESET_PICTURES:
    {
        ResetPictures (vd);

        vout_display_place_t place;
        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);

        vd->fmt.i_width  = vd->source.i_width  * place.width  / vd->source.i_visible_width;
        vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height;

        vd->fmt.i_visible_width  = place.width;
        vd->fmt.i_visible_height = place.height;
        vd->fmt.i_x_offset = vd->source.i_x_offset * place.width  / vd->source.i_visible_width;
        vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height;
        return VLC_SUCCESS;
    }

    /* Hide the mouse. It will be send when
     * vout_display_t::info.b_hide_mouse is false */
    case VOUT_DISPLAY_HIDE_MOUSE:
        xcb_change_window_attributes (sys->conn, sys->embed->handle.xid,
                                  XCB_CW_CURSOR, &(uint32_t){ sys->cursor });
        xcb_flush (sys->conn);
        return VLC_SUCCESS;

    default:
        msg_Err (vd, "Unknown request in XCB vout display");
        return VLC_EGENERIC;
    }
}
예제 #9
0
파일: common.c 프로젝트: paa/vlc
/*****************************************************************************
 * UpdateRects: update clipping rectangles
 *****************************************************************************
 * This function is called when the window position or size are changed, and
 * its job is to update the source and destination RECTs used to display the
 * picture.
 *****************************************************************************/
void UpdateRects(vout_display_t *vd,
                  const vout_display_cfg_t *cfg,
                  const video_format_t *source,
                  bool is_forced)
{
    vout_display_sys_t *sys = vd->sys;
#define rect_src sys->rect_src
#define rect_src_clipped sys->rect_src_clipped
#define rect_dest sys->rect_dest
#define rect_dest_clipped sys->rect_dest_clipped

    RECT  rect;
    POINT point;

    /* */
    if (!cfg)
        cfg = vd->cfg;
    if (!source)
        source = &vd->source;

    /* Retrieve the window size */
    GetClientRect(sys->hwnd, &rect);

    /* Retrieve the window position */
    point.x = point.y = 0;
    ClientToScreen(sys->hwnd, &point);

    /* If nothing changed, we can return */
    bool has_moved;
    bool is_resized;
    EventThreadUpdateWindowPosition(sys->event, &has_moved, &is_resized,
                                    point.x, point.y,
                                    rect.right, rect.bottom);
    if (is_resized)
        vout_display_SendEventDisplaySize(vd, rect.right, rect.bottom, cfg->is_fullscreen);
    if (!is_forced && !has_moved && !is_resized )
        return;

    /* Update the window position and size */
    vout_display_cfg_t place_cfg = *cfg;
    place_cfg.display.width  = rect.right;
    place_cfg.display.height = rect.bottom;

    vout_display_place_t place;
    vout_display_PlacePicture(&place, source, &place_cfg, false);

    EventThreadUpdateSourceAndPlace(sys->event, source, &place);
#if defined(MODULE_NAME_IS_wingapi)
    if (place.width != vd->fmt.i_width || place.height != vd->fmt.i_height)
        vout_display_SendEventPicturesInvalid(vd);
#endif

    if (sys->hvideownd)
        SetWindowPos(sys->hvideownd, 0,
                     place.x, place.y, place.width, place.height,
                     SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS);

    /* Destination image position and dimensions */
#if defined(MODULE_NAME_IS_direct3d)
    rect_dest.left   = 0;
    rect_dest.right  = place.width;
    rect_dest.top    = 0;
    rect_dest.bottom = place.height;
#else
    rect_dest.left = point.x + place.x;
    rect_dest.right = rect_dest.left + place.width;
    rect_dest.top = point.y + place.y;
    rect_dest.bottom = rect_dest.top + place.height;

#ifdef MODULE_NAME_IS_directx
    /* Apply overlay hardware constraints */
    if (sys->use_overlay)
        AlignRect(&rect_dest, sys->i_align_dest_boundary, sys->i_align_dest_size);
#endif

#endif

#if defined(MODULE_NAME_IS_directx) || defined(MODULE_NAME_IS_direct3d)
    /* UpdateOverlay directdraw function doesn't automatically clip to the
     * display size so we need to do it otherwise it will fail
     * It is also needed for d3d to avoid exceding our surface size */

    /* Clip the destination window */
    if (!IntersectRect(&rect_dest_clipped, &rect_dest,
                       &sys->rect_display)) {
        SetRectEmpty(&rect_src_clipped);
        goto exit;
    }

#ifndef NDEBUG
    msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped coords:"
                " %li,%li,%li,%li",
                rect_dest_clipped.left, rect_dest_clipped.top,
                rect_dest_clipped.right, rect_dest_clipped.bottom);
#endif

#else

    /* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */
    rect_dest_clipped = rect_dest;

#endif

    /* the 2 following lines are to fix a bug when clicking on the desktop */
    if ((rect_dest_clipped.right - rect_dest_clipped.left) == 0 ||
        (rect_dest_clipped.bottom - rect_dest_clipped.top) == 0) {
        SetRectEmpty(&rect_src_clipped);
        goto exit;
    }

    /* src image dimensions */
    rect_src.left   = 0;
    rect_src.top    = 0;
    rect_src.right  = source->i_width;
    rect_src.bottom = source->i_height;

    /* Clip the source image */
    rect_src_clipped.left = source->i_x_offset +
      (rect_dest_clipped.left - rect_dest.left) *
      source->i_visible_width / (rect_dest.right - rect_dest.left);
    rect_src_clipped.right = source->i_x_offset +
      source->i_visible_width -
      (rect_dest.right - rect_dest_clipped.right) *
      source->i_visible_width / (rect_dest.right - rect_dest.left);
    rect_src_clipped.top = source->i_y_offset +
      (rect_dest_clipped.top - rect_dest.top) *
      source->i_visible_height / (rect_dest.bottom - rect_dest.top);
    rect_src_clipped.bottom = source->i_y_offset +
      source->i_visible_height -
      (rect_dest.bottom - rect_dest_clipped.bottom) *
      source->i_visible_height / (rect_dest.bottom - rect_dest.top);

#ifdef MODULE_NAME_IS_directx
    /* Apply overlay hardware constraints */
    if (sys->use_overlay)
        AlignRect(&rect_src_clipped, sys->i_align_src_boundary, sys->i_align_src_size);
#elif defined(MODULE_NAME_IS_direct3d)
    /* Needed at least with YUV content */
    rect_src_clipped.left &= ~1;
    rect_src_clipped.right &= ~1;
    rect_src_clipped.top &= ~1;
    rect_src_clipped.bottom &= ~1;
#endif

#ifndef NDEBUG
    msg_Dbg(vd, "DirectXUpdateRects image_src_clipped"
                " coords: %li,%li,%li,%li",
                rect_src_clipped.left, rect_src_clipped.top,
                rect_src_clipped.right, rect_src_clipped.bottom);
#endif

#ifdef MODULE_NAME_IS_directx
    /* The destination coordinates need to be relative to the current
     * directdraw primary surface (display) */
    rect_dest_clipped.left -= sys->rect_display.left;
    rect_dest_clipped.right -= sys->rect_display.left;
    rect_dest_clipped.top -= sys->rect_display.top;
    rect_dest_clipped.bottom -= sys->rect_display.top;
#endif

    CommonChangeThumbnailClip(vd, true);

exit:
    /* Signal the change in size/position */
    sys->changes |= DX_POSITION_CHANGE;

#undef rect_src
#undef rect_src_clipped
#undef rect_dest
#undef rect_dest_clipped
}
예제 #10
0
파일: x11.c 프로젝트: maniacs-m/vlc
static int Control (vout_display_t *vd, int query, va_list ap)
{
    vout_display_sys_t *sys = vd->sys;

    switch (query)
    {
    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
    {
        const vout_display_cfg_t *p_cfg =
            (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
        vout_display_place_t place;

        vout_display_PlacePicture (&place, &vd->source, p_cfg, false);

        if (place.width  != vd->fmt.i_visible_width ||
            place.height != vd->fmt.i_visible_height)
        {
            vout_display_SendEventPicturesInvalid (vd);
            return VLC_SUCCESS;
        }

        /* Move the picture within the window */
        const uint32_t values[] = { place.x, place.y };
        xcb_configure_window (sys->conn, sys->window,
                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
                              values);
        return VLC_SUCCESS;
    }

    case VOUT_DISPLAY_CHANGE_ZOOM:
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
        /* I am not sure it is always necessary, but it is way simpler ... */
        vout_display_SendEventPicturesInvalid (vd);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_RESET_PICTURES:
    {
        ResetPictures (vd);

        vout_display_place_t place;
        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);

        video_format_t src;
        video_format_ApplyRotation(&src, &vd->source);

        vd->fmt.i_width  = src.i_width  * place.width / src.i_visible_width;
        vd->fmt.i_height = src.i_height * place.height / src.i_visible_height;

        vd->fmt.i_visible_width  = place.width;
        vd->fmt.i_visible_height = place.height;
        vd->fmt.i_x_offset = src.i_x_offset * place.width / src.i_visible_width;
        vd->fmt.i_y_offset = src.i_y_offset * place.height / src.i_visible_height;
        return VLC_SUCCESS;
    }

    /* Hide the mouse. It will be send when
     * vout_display_t::info.b_hide_mouse is false */
    case VOUT_DISPLAY_HIDE_MOUSE:
        xcb_change_window_attributes (sys->conn, sys->embed->handle.xid,
                                  XCB_CW_CURSOR, &(uint32_t){ sys->cursor });
        xcb_flush (sys->conn);
        return VLC_SUCCESS;

    default:
        msg_Err (vd, "Unknown request in XCB vout display");
        return VLC_EGENERIC;
    }
}
예제 #11
0
파일: x11.c 프로젝트: paa/vlc
static int Control (vout_display_t *vd, int query, va_list ap)
{
    vout_display_sys_t *p_sys = vd->sys;

    switch (query)
    {
    case VOUT_DISPLAY_CHANGE_FULLSCREEN:
    {
        const vout_display_cfg_t *c = va_arg (ap, const vout_display_cfg_t *);
        return vout_window_SetFullScreen (p_sys->embed, c->is_fullscreen);
    }

    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE:
    {
        const vout_display_cfg_t *p_cfg =
            (const vout_display_cfg_t*)va_arg (ap, const vout_display_cfg_t *);
        const bool is_forced = (bool)va_arg (ap, int);

        if (is_forced
         && vout_window_SetSize (p_sys->embed,
                                 p_cfg->display.width,
                                 p_cfg->display.height))
            return VLC_EGENERIC;

        vout_display_place_t place;
        vout_display_PlacePicture (&place, &vd->source, p_cfg, false);

        if (place.width  != vd->fmt.i_visible_width ||
            place.height != vd->fmt.i_visible_height)
        {
            vout_display_SendEventPicturesInvalid (vd);
            return VLC_SUCCESS;
        }

        /* Move the picture within the window */
        const uint32_t values[] = { place.x, place.y };
        xcb_configure_window (p_sys->conn, p_sys->window,
                              XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y,
                              values);
        return VLC_SUCCESS;
    }
    case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
    {
        unsigned state = va_arg (ap, unsigned);
        return vout_window_SetState (p_sys->embed, state);
    }

    case VOUT_DISPLAY_CHANGE_ZOOM:
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
        /* I am not sure it is always necessary, but it is way simpler ... */
        vout_display_SendEventPicturesInvalid (vd);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_RESET_PICTURES:
    {
        ResetPictures (vd);

        vout_display_place_t place;
        vout_display_PlacePicture (&place, &vd->source, vd->cfg, false);

        vd->fmt.i_width  = vd->source.i_width  * place.width  / vd->source.i_visible_width;
        vd->fmt.i_height = vd->source.i_height * place.height / vd->source.i_visible_height;

        vd->fmt.i_visible_width  = place.width;
        vd->fmt.i_visible_height = place.height;
        vd->fmt.i_x_offset = vd->source.i_x_offset * place.width  / vd->source.i_visible_width;
        vd->fmt.i_y_offset = vd->source.i_y_offset * place.height / vd->source.i_visible_height;
        return VLC_SUCCESS;
    }

    /* Hide the mouse. It will be send when
     * vout_display_t::info.b_hide_mouse is false */
    case VOUT_DISPLAY_HIDE_MOUSE:
        xcb_change_window_attributes (p_sys->conn, p_sys->embed->handle.xid,
                                  XCB_CW_CURSOR, &(uint32_t){ p_sys->cursor });
        xcb_flush (p_sys->conn);
        return VLC_SUCCESS;

    default:
        msg_Err (vd, "Unknown request in XCB vout display");
        return VLC_EGENERIC;
    }
}