Chinaunix首页 | 论坛 | 博客
  • 博客访问: 244355
  • 博文数量: 33
  • 博客积分: 2511
  • 博客等级: 少校
  • 技术积分: 391
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-06 09:24
文章分类
文章存档

2011年(3)

2010年(9)

2009年(3)

2008年(18)

我的朋友

分类: LINUX

2010-09-30 14:07:36

1. 注册新的硬件底层

注意:所有代码基于1.2版本

1). VideoBootStrap
在初始化的时候被直接调用

typedef struct VideoBootStrap {
    const char *name;
    const char *desc;
    int (*available)(void);                   // 判断设备是否可用
    SDL_VideoDevice *(*create)(int devindex); // 创建一个实例
} VideoBootStrap;


2). SDL_VideoDevice
创建一个Video实例, 具体使用的实例为SDL_VideoDevice *current_video = NULL;

依次为:
a). Video
b). 硬件加速
c). gamma支持
d). Opengl支持
e). 窗口管理
f). 光标管理
g). 事件管理
h). 通用数据
i). Opengl的数据
j). 私有数据
k). Free函数

/* The SDL video driver */
typedef struct SDL_VideoDevice SDL_VideoDevice;

#define SDL_VideoSurface    (current_video->screen)
#define SDL_ShadowSurface    (current_video->shadow)
#define SDL_PublicSurface    (current_video->visible)

/* Create a shadow surface if necessary */
/* There are three conditions under which we create a shadow surface:
    1.  We need a particular bits-per-pixel that we didn't get.
    2.  We need a hardware palette and didn't get one.
    3.  We need a software surface and got a hardware surface.
*/

/* Define the SDL video driver structure */
#define _THIS    SDL_VideoDevice *_this
#ifndef _STATUS
#define _STATUS    SDL_status *status
#endif
struct SDL_VideoDevice {
    /* * * */
    /* The name of this video driver */
    const char *name;

    /* * * */
    /* Initialization/Query functions */

    /* Initialize the native video subsystem, filling 'vformat' with the
       "best" display pixel format, returning 0 or -1 if there's an error.
     */
    int (*VideoInit)(_THIS, SDL_PixelFormat *vformat);

    /* List the available video modes for the given pixel format, sorted
       from largest to smallest.
     */
    SDL_Rect **(*ListModes)(_THIS, SDL_PixelFormat *format, Uint32 flags);

    /* Set the requested video mode, returning a surface which will be
       set to the SDL_VideoSurface.  The width and height will already
       be verified by ListModes(), and the video subsystem is free to
       set the mode to a supported bit depth different from the one
       specified -- the desired bpp will be emulated with a shadow
       surface if necessary.  If a new mode is returned, this function
       should take care of cleaning up the current mode.
     */
    SDL_Surface *(*SetVideoMode)(_THIS, SDL_Surface *current,
                int width, int height, int bpp, Uint32 flags);

    /* Toggle the fullscreen mode */
    int (*ToggleFullScreen)(_THIS, int on);

    /* This is called after the video mode has been set, to get the
       initial mouse state.  It should queue events as necessary to
       properly represent the current mouse focus and position.
     */
    void (*UpdateMouse)(_THIS);

    /* Create a YUV video surface (possibly overlay) of the given
       format.  The hardware should be able to perform at least 2x
       scaling on display.
     */
    SDL_Overlay *(*CreateYUVOverlay)(_THIS, int width, int height,
                                     Uint32 format, SDL_Surface *display);

        /* Sets the color entries { firstcolor .. (firstcolor+ncolors-1) }
       of the physical palette to those in 'colors'. If the device is
       using a software palette (SDL_HWPALETTE not set), then the
       changes are reflected in the logical palette of the screen
       as well.
       The return value is 1 if all entries could be set properly
       or 0 otherwise.
    */
    int (*SetColors)(_THIS, int firstcolor, int ncolors,
             SDL_Color *colors);

    /* This pointer should exist in the native video subsystem and should
       point to an appropriate update function for the current video mode
     */
    void (*UpdateRects)(_THIS, int numrects, SDL_Rect *rects);

    /* Reverse the effects VideoInit() -- called if VideoInit() fails
       or if the application is shutting down the video subsystem.
    */
    void (*VideoQuit)(_THIS);

    /* * * */
    /* Hardware acceleration functions */

    /* Information about the video hardware */
    SDL_VideoInfo info;

    /* The pixel format used when SDL_CreateRGBSurface creates SDL_HWSURFACEs with alpha */
    SDL_PixelFormat* displayformatalphapixel;
    
    /* Allocates a surface in video memory */
    int (*AllocHWSurface)(_THIS, SDL_Surface *surface);

    /* Sets the hardware accelerated blit function, if any, based
       on the current flags of the surface (colorkey, alpha, etc.)
     */
    int (*CheckHWBlit)(_THIS, SDL_Surface *src, SDL_Surface *dst);

    /* Fills a surface rectangle with the given color */
    int (*FillHWRect)(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);

    /* Sets video mem colorkey and accelerated blit function */
    int (*SetHWColorKey)(_THIS, SDL_Surface *surface, Uint32 key);

    /* Sets per surface hardware alpha value */
    int (*SetHWAlpha)(_THIS, SDL_Surface *surface, Uint8 value);

    /* Returns a readable/writable surface */
    int (*LockHWSurface)(_THIS, SDL_Surface *surface);
    void (*UnlockHWSurface)(_THIS, SDL_Surface *surface);

    /* Performs hardware flipping */
    int (*FlipHWSurface)(_THIS, SDL_Surface *surface);

    /* Frees a previously allocated video surface */
    void (*FreeHWSurface)(_THIS, SDL_Surface *surface);

    /* * * */
    /* Gamma support */

    Uint16 *gamma;

    /* Set the gamma correction directly (emulated with gamma ramps) */
    int (*SetGamma)(_THIS, float red, float green, float blue);

    /* Get the gamma correction directly (emulated with gamma ramps) */
    int (*GetGamma)(_THIS, float *red, float *green, float *blue);

    /* Set the gamma ramp */
    int (*SetGammaRamp)(_THIS, Uint16 *ramp);

    /* Get the gamma ramp */
    int (*GetGammaRamp)(_THIS, Uint16 *ramp);

    /* * * */
    /* OpenGL support */

    /* Sets the dll to use for OpenGL and loads it */
    int (*GL_LoadLibrary)(_THIS, const char *path);

    /* Retrieves the address of a function in the gl library */
    void* (*GL_GetProcAddress)(_THIS, const char *proc);

    /* Get attribute information from the windowing system. */
    int (*GL_GetAttribute)(_THIS, SDL_GLattr attrib, int* value);

    /* Make the context associated with this driver current */
    int (*GL_MakeCurrent)(_THIS);

    /* Swap the current buffers in double buffer mode. */
    void (*GL_SwapBuffers)(_THIS);

      /* OpenGL functions for SDL_OPENGLBLIT */
#if SDL_VIDEO_OPENGL
#if !defined(__WIN32__)
#define WINAPI
#endif
#define SDL_PROC(ret,func,params) ret (WINAPI *func) params;
#include "SDL_glfuncs.h"
#undef SDL_PROC

    /* Texture id */
    GLuint texture;
#endif
    int is_32bit;
 
    /* * * */
    /* Window manager functions */

    /* Set the title and icon text */
    void (*SetCaption)(_THIS, const char *title, const char *icon);

    /* Set the window icon image */
    void (*SetIcon)(_THIS, SDL_Surface *icon, Uint8 *mask);

    /* Iconify the window.
       This function returns 1 if there is a window manager and the
       window was actually iconified, it returns 0 otherwise.
    */
    int (*IconifyWindow)(_THIS);

    /* Grab or ungrab keyboard and mouse input */
    SDL_GrabMode (*GrabInput)(_THIS, SDL_GrabMode mode);

    /* Get some platform dependent window information */
    int (*GetWMInfo)(_THIS, SDL_SysWMinfo *info);

    /* * * */
    /* Cursor manager functions */

    /* Free a window manager cursor
       This function can be NULL if CreateWMCursor is also NULL.
     */
    void (*FreeWMCursor)(_THIS, WMcursor *cursor);

    /* If not NULL, create a black/white window manager cursor */
    WMcursor *(*CreateWMCursor)(_THIS,
        Uint8 *data, Uint8 *mask, int w, int h, int hot_x, int hot_y);

    /* Show the specified cursor, or hide if cursor is NULL */
    int (*ShowWMCursor)(_THIS, WMcursor *cursor);

    /* Warp the window manager cursor to (x,y)
       If NULL, a mouse motion event is posted internally.
     */
    void (*WarpWMCursor)(_THIS, Uint16 x, Uint16 y);

    /* If not NULL, this is called when a mouse motion event occurs */
    void (*MoveWMCursor)(_THIS, int x, int y);

    /* Determine whether the mouse should be in relative mode or not.
       This function is called when the input grab state or cursor
       visibility state changes.
       If the cursor is not visible, and the input is grabbed, the
       driver can place the mouse in relative mode, which may result
       in higher accuracy sampling of the pointer motion.
    */
    void (*CheckMouseMode)(_THIS);

    /* * * */
    /* Event manager functions */

    /* Initialize keyboard mapping for this driver */
    void (*InitOSKeymap)(_THIS);

    /* Handle any queued OS events */
    void (*PumpEvents)(_THIS);

    /* * * */
    /* Data common to all drivers */
    SDL_Surface *screen;  //SDL_VideoSurface, 等于在私有的XXX_SetVideoMode的返回值
    SDL_Surface *shadow;  //SDL_ShadowSurface
    SDL_Surface *visible; //SDL_PublicSurface 指向SDL_ShadowSurface或者SDL_VideoSurface
    
        SDL_Palette *physpal;    /* physical palette, if != logical palette */
        SDL_Color *gammacols;    /* gamma-corrected colours, or NULL */
    char *wm_title;
    char *wm_icon;
    int offset_x;
    int offset_y;
    SDL_GrabMode input_grab;

    /* Driver information flags */
    int handles_any_size;    /* Driver handles any size video mode */

    /* * * */
    /* Data used by the GL drivers */
    struct {
        int red_size;
        int green_size;
        int blue_size;
        int alpha_size;
        int depth_size;
        int buffer_size;
        int stencil_size;
        int double_buffer;
        int accum_red_size;
        int accum_green_size;
        int accum_blue_size;
        int accum_alpha_size;
        int stereo;
        int multisamplebuffers;
        int multisamplesamples;
        int accelerated;
        int swap_control;
        int driver_loaded;
        char driver_path[256];
        void* dll_handle;
    } gl_config;

    /* * * */
    /* Data private to this driver */
    struct SDL_PrivateVideoData *hidden;
    struct SDL_PrivateGLData *gl_data;

    /* * * */
    /* The function used to dispose of this structure */
    void (*free)(_THIS);
};
#undef _THIS

其中的Videoinfo

/** Useful for determining the video hardware capabilities */
typedef struct SDL_VideoInfo {
    Uint32 hw_available :1;    /**< Flag: Can you create hardware surfaces? */
    Uint32 wm_available :1;    /**< Flag: Can you talk to a window manager? */
    Uint32 UnusedBits1  :6;
    Uint32 UnusedBits2  :1;
    Uint32 blit_hw      :1;    /**< Flag: Accelerated blits HW --> HW */
    Uint32 blit_hw_CC   :1;    /**< Flag: Accelerated blits with Colorkey */
    Uint32 blit_hw_A    :1;    /**< Flag: Accelerated blits with Alpha */
    Uint32 blit_sw      :1;    /**< Flag: Accelerated blits SW --> HW */
    Uint32 blit_sw_CC   :1;    /**< Flag: Accelerated blits with Colorkey */
    Uint32 blit_sw_A    :1;    /**< Flag: Accelerated blits with Alpha */
    Uint32 blit_fill    :1;    /**< Flag: Accelerated color fill */
    Uint32 UnusedBits3  :16;
    Uint32 video_mem;    /**< The total amount of video memory (in K) */
    SDL_PixelFormat *vfmt;    /**< Value: The format of the video surface */
    
    int    current_w;    /**< Value: The current video mode width */
    int    current_h;    /**< Value: The current video mode height */
} SDL_VideoInfo;

2. 需要实现的接口

1).
/* Initialize the native video subsystem, filling 'vformat' with the
  "best" display pixel format, returning 0 or -1 if there's an error.
 */
int (*VideoInit)(_THIS, SDL_PixelFormat *vformat);
初始化哪些资源,将路径设置放在此处?
a). 能将路径配置放在此函数中吗?似乎不合适,仅仅被调用一次

/* Reverse the effects VideoInit() -- called if VideoInit() fails
   or if the application is shutting down the video subsystem.
*/
void (*VideoQuit)(_THIS);

2).
/* List the available video modes for the given pixel format, sorted
   from largest to smallest.
 */
SDL_Rect **(*ListModes)(_THIS, SDL_PixelFormat *format, Uint32 flags);
不用实现[FIXME]

3).
/* Set the requested video mode, returning a surface which will be
   set to the SDL_VideoSurface.  The width and height will already
   be verified by ListModes(), and the video subsystem is free to
   set the mode to a supported bit depth different from the one
   specified -- the desired bpp will be emulated with a shadow
   surface if necessary.  If a new mode is returned, this function
   should take care of cleaning up the current mode.
 */
SDL_Surface *(*SetVideoMode)(_THIS, SDL_Surface *current,
            int width, int height, int bpp, Uint32 flags);
基本可以保持不变
            
4).
/* Create a YUV video surface (possibly overlay) of the given
   format.  The hardware should be able to perform at least 2x
   scaling on display.
 */
SDL_Overlay *(*CreateYUVOverlay)(_THIS, int width, int height,
                                 Uint32 format, SDL_Surface *display);

创建一个Overlay,并分配私有数据,指定数据格式,在内存中的排布等

SDL_Overlay *SDL_CreateYUVOverlay(int width, int height, Uint32 format, SDL_Surface *display);
int SDL_LockYUVOverlay(SDL_Overlay *overlay);
void SDL_UnlockYUVOverlay(SDL_Overlay *overlay);
int SDL_DisplayYUVOverlay(SDL_Overlay *overlay, SDL_Rect *dstrect);
Blit overlay到Surface,dstrect指定目标矩形大小和位置,如果dstrect不等于Overlay大小,则会
使用缩放功能,内置2X的优化
void SDL_FreeYUVOverlay(SDL_Overlay *overlay);

/** @name Overlay Formats
 *  The most common video overlay formats.
 *  For an explanation of these pixel formats, see:
 *    
 *
 *  For information on the relationship between color spaces, see:
 *  ~aly/polygon/info/color-space-faq.html
 */
/*@{*/
#define SDL_YV12_OVERLAY  0x32315659    /**< Planar mode: Y + V + U  (3 planes) */
#define SDL_IYUV_OVERLAY  0x56555949    /**< Planar mode: Y + U + V  (3 planes) */
#define SDL_YUY2_OVERLAY  0x32595559    /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
#define SDL_UYVY_OVERLAY  0x59565955    /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
#define SDL_YVYU_OVERLAY  0x55595659    /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
/*@}*/

/** The YUV hardware video overlay */
typedef struct SDL_Overlay {
    Uint32 format;                /**< Read-only */
    int w, h;                /**< Read-only */
    int planes;                /**< Read-only *///表明是打包模式还是平面模式
    Uint16 *pitches;            /**< Read-only */
    Uint8 **pixels;                /**< Read-write */

    /** @name Hardware-specific surface info */
        /*@{*/
    struct private_yuvhwfuncs *hwfuncs; //函数指针
    struct private_yuvhwdata *hwdata;   //私有数据
        /*@{*/

    /** @name Special flags */
        /*@{*/
    Uint32 hw_overlay :1;    /**< Flag: This overlay hardware accelerated? */
    Uint32 UnusedBits :31;
        /*@}*/
} SDL_Overlay;

其中,需要实现的函数指针包括如下:
可以参考DirectFB的实现:
struct private_yuvhwfuncs {
    int (*Lock)(_THIS, SDL_Overlay *overlay);    // 可以忽略实现
    void (*Unlock)(_THIS, SDL_Overlay *overlay); // 可以忽略实现
    int (*Display)(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); //主要实现了Merge操作,为了显示
    void (*FreeHW)(_THIS, SDL_Overlay *overlay); // 非常简单
};

在文件SDL_nullvideo_yuv.c

5).
/* This pointer should exist in the native video subsystem and should
   point to an appropriate update function for the current video mode
 */
void (*UpdateRects)(_THIS, int numrects, SDL_Rect *rects);
关键函数

6).
/* Allocates a surface in video memory */
int (*AllocHWSurface)(_THIS, SDL_Surface *surface);
原来的代码中,新加入了两种标记:
SDL_PWSWSURFACE
SDL_PWHWSURFACE
考虑合并这2个标记

/* Frees a previously allocated video surface */
void (*FreeHWSurface)(_THIS, SDL_Surface *surface);
释放资源,实现起来也非常方便

7).
/* Sets the hardware accelerated blit function, if any, based
   on the current flags of the surface (colorkey, alpha, etc.)
 */
int (*CheckHWBlit)(_THIS, SDL_Surface *src, SDL_Surface *dst);
设置硬件加速Blit功能函数

其中的SDL_Surface的概念是核心
/** This structure should be treated as read-only, except for 'pixels',
 *  which, if not NULL, contains the raw pixel data for the surface.
 */
typedef struct SDL_Surface {
    Uint32 flags;                /**< Read-only */
    SDL_PixelFormat *format;        /**< Read-only */
    int w, h;                /**< Read-only */
    Uint16 pitch;                /**< Read-only */
    void *pixels;                /**< Read-write *///指向像素数据
    int offset;                /**< Private */

    /** Hardware-specific surface info */
    struct private_hwdata *hwdata; // 硬件特定信息,由底层driver来实现

    /** clipping information */
    SDL_Rect clip_rect;            /**< Read-only */
    Uint32 unused1;                /**< for binary compatibility */

    /** Allow recursive locks */
    Uint32 locked;                /**< Private */

    /** info for fast blit mapping to other surfaces */
    struct SDL_BlitMap *map;        /**< Private */

    /** format version, bumped at every change to invalidate blit maps */
    unsigned int format_version;        /**< Private */

    /** Reference count -- used when freeing surface */
    int refcount;                /**< Read-mostly */
} SDL_Surface;

/* Blit mapping definition */
typedef struct SDL_BlitMap {
    SDL_Surface *dst;
    int identity;
    Uint8 *table;
    SDL_blit hw_blit;        // 在CheckHWBlit函数中设置DUMMY_HWAccelBlit函数
    SDL_blit sw_blit;
    struct private_hwaccel *hw_data;
    struct private_swaccel *sw_data;

    /* the version count matches the destination; mismatch indicates
       an invalid mapping */
        unsigned int format_version;
} SDL_BlitMap;
设置好后,会在硬件加速Blit的时候使用

8).
/* Returns a readable/writable surface */
int (*LockHWSurface)(_THIS, SDL_Surface *surface);
void (*UnlockHWSurface)(_THIS, SDL_Surface *surface);
判断是否可以读写

9).
/* Performs hardware flipping */
int (*FlipHWSurface)(_THIS, SDL_Surface *surface);
在SDL_Flip()中被调用,如果支持SDL_DOUBLEBUF才会被使用,在SDL_Flip()中使用
SDL_UpdateRect()函数

10).
/* Initialize keyboard mapping for this driver */
void (*InitOSKeymap)(_THIS);
将driver的键盘事件映射到SDL支持的键盘事件[FIXME: 我们真的需要这个功能吗],
基本不用改变该函数的实现

11).
/* Handle any queued OS events */
void (*PumpEvents)(_THIS);
消息队列,这里是消息的源头,所有消息从这里开始排队,在SDL的内部其实是起了一个专门的线程
用于消息的接收,因此,用loop像消息队列里面塞消息即可
阅读(3138) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~