浅析CreateCompatibleDC如何仅仅malloc一块含有lcd有效信息的纯内存区作为surface->pixels的
m_hdc = CreateCompatibleDC(HDC_SCREEN);
HDC_SCREEN只是表示创建的pdc对应的surface将含有有效lcd信息数值,而不是自己传入的depth等数值.
即:
surface->video = current_video;
surface->format = GAL_AllocFormat(screen->format->BitsPerPixel,
screen->format->Rmask,
screen->format->Gmask,
screen->format->Bmask,
screen->format->Amask);
surface->pixels = malloc(surface->h*surface->pitch);
通过malloc从pc或arm的DDR中申请的一块纯内存空间.
所以CreateCompatibleDC(HDC_SCREEN);
仅仅是malloc一块含有lcd有效信息的纯内存区作为surface->pixels内存数据区地址[luther.gliethttp]
#define CreateCompatibleDC(hdc) CreateCompatibleDCEx(hdc, 0, 0);
HDC GUIAPI CreateCompatibleDCEx (HDC hdc, int width, int height)
{
PDC pdc;
PDC pmem_dc = NULL;
GAL_Surface* surface;
DWORD flags;
/*
static inline PDC dc_HDC2PDC (HDC hdc)
{
if (hdc == HDC_SCREEN) return &__mg_screen_dc;
return (PDC) hdc;
} */
pdc = dc_HDC2PDC (hdc); // 返回__mg_screen_dc,
if (!(pmem_dc = malloc (sizeof(DC))))
return HDC_INVALID;
if (width <= 0 || height <= 0) {
//dc_InitScreenDC函数中做了如下初始化[luther.gliethttp]
// pdc->DevRC.left = 0; // 左上角
// pdc->DevRC.top = 0;
// pdc->DevRC.right = surface->w;
// 右下角,这样该pdc对应矩形surface,即__gal_screen的w和h,就是整个lcd屏幕的framebuffer内存区[luther.gliethttp]
// pdc->DevRC.bottom = surface->h;
width = RECTW (pdc->DevRC);
height = RECTH (pdc->DevRC); // lcd屏幕的宽和高
}
// __gal_screen->flags = (GAL_FULLSCREEN|GAL_HWSURFACE);
// __mg_screen_dc->surface 等于 __gal_screen[luther.gliethttp]
if ((pdc->surface->flags & GAL_HWSURFACE) == GAL_HWSURFACE)
flags = GAL_HWSURFACE; // 我们这里flags将等于GAL_HWSURFACE
else
flags = GAL_SWSURFACE;
LOCK (&__mg_gdilock);
surface = GAL_CreateRGBSurface (flags,
width, height,
pdc->surface->format->BitsPerPixel,
pdc->surface->format->Rmask,
pdc->surface->format->Gmask,
pdc->surface->format->Bmask,
pdc->surface->format->Amask);
UNLOCK (&__mg_gdilock);
if (!surface) {
free (pmem_dc);
return HDC_INVALID;
}
/* Set surface attributes */
if (pdc->surface->format->BitsPerPixel <= 8) {
GAL_SetPalette (surface, GAL_LOGPAL,
(GAL_Color*) pdc->surface->format->palette->colors,
0, 1<
surface->format->BitsPerPixel);
}
if (pdc->surface->flags & GAL_SRCALPHA) {
GAL_SetAlpha (surface, GAL_SRCALPHA,
pdc->surface->format->alpha);
}
if (pdc->surface->flags & GAL_SRCCOLORKEY) {
GAL_SetColorKey (surface, GAL_SRCCOLORKEY,
pdc->surface->format->colorkey);
}
pmem_dc->DataType = TYPE_HDC; // 数据类型
pmem_dc->DCType = TYPE_MEMDC; // 类型
pmem_dc->inuse = TRUE;
pmem_dc->surface = surface;
pmem_dc->DevRC.left = 0;
pmem_dc->DevRC.top = 0;
pmem_dc->DevRC.right = width;
pmem_dc->DevRC.bottom = height; // 该dc使用malloc申请到的内存对应的矩形.
// 这里就是整个LCD屏幕
dc_InitMemDCFrom (pmem_dc, pdc);
/* clip region info */
pmem_dc->pGCRInfo = NULL;
pmem_dc->oldage = 0;
InitClipRgn (&pmem_dc->ecrgn, &__mg_FreeClipRectList);
SetClipRgn (&pmem_dc->ecrgn, &pmem_dc->DevRC);
return (HDC)pmem_dc;
}
/*
* Create an empty RGB surface of the appropriate depth
*/
GAL_Surface * GAL_CreateRGBSurface (Uint32 flags,
int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
{
GAL_VideoDevice *video = current_video;
GAL_VideoDevice *this = current_video;
GAL_Surface *screen;
GAL_Surface *surface;
/* Check to see if we desire the surface in video memory */
if ( video ) {
screen = GAL_PublicSurface; // 这时screen = __gal_screen;
} else {
screen = NULL;
}
if ( screen && ((screen->flags&GAL_HWSURFACE) == GAL_HWSURFACE) ) {
if ( (flags&(GAL_SRCCOLORKEY|GAL_SRCALPHA)) != 0 ) { // pass
flags |= GAL_HWSURFACE;
}
if ( (flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) { // pass
if ( ! current_video->info.blit_hw_CC ) {
flags &= ~GAL_HWSURFACE;
}
}
if ( (flags & GAL_SRCALPHA) == GAL_SRCALPHA ) { // pass
if ( ! current_video->info.blit_hw_A ) {
flags &= ~GAL_HWSURFACE;
}
}
} else {
flags &= ~GAL_HWSURFACE;
}
/* Allocate the surface */
surface = (GAL_Surface *)malloc(sizeof(*surface));
if ( surface == NULL ) {
GAL_OutOfMemory();
return(NULL);
}
if ((flags & GAL_HWSURFACE) == GAL_HWSURFACE)
surface->video = current_video; // 该surface有物理video[luther.gliethttp]
else
surface->video = NULL;
surface->flags = GAL_SWSURFACE; // 将需要建立的surface->flags强制变为GAL_SWSURFACE软surface区块
if ( (flags & GAL_HWSURFACE) == GAL_HWSURFACE ) {
// 该surface的format中含有有效的lcd物理信息,那么使用lcd有效物理数据,而非用户
// 传入的depth等数据[luther.gliethttp]
depth = screen->format->BitsPerPixel;
Rmask = screen->format->Rmask;
Gmask = screen->format->Gmask;
Bmask = screen->format->Bmask;
Amask = screen->format->Amask;
}
surface->format = GAL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);
if ( surface->format == NULL ) {
free(surface);
return(NULL);
}
if ( Amask ) {
surface->flags |= GAL_SRCALPHA;
}
surface->w = width;
surface->h = height;
surface->pitch = GAL_CalculatePitch(surface);
surface->pixels = NULL;
surface->offset = 0;
surface->hwdata = NULL;
surface->map = NULL;
surface->format_version = 0;
GAL_SetClipRect(surface, NULL);
/* Get the pixels */
if ( ((flags&GAL_HWSURFACE) == GAL_SWSURFACE) ||
// 如果flags为GAL_HWSURFACE,即申请一个纯内存区,那么直接执行下面的malloc
(video->AllocHWSurface(this, surface) < 0) ) {
// 如果flags为GAL_HWSURFACE,那么首先尝试从lcd驱动程序中获取一块可能有加速功能的内存块
// 如果申请失败,比如QVFB_AllocHWSurface()就直接返回-1,那么[luther.gliethttp]
// 就使用malloc从pc机或者arm的DDR中申请一块内存,作为该surface区块数据操作的
// 目的mem内存[luther.gliethttp]
if ( surface->w && surface->h ) {
surface->pixels = malloc(surface->h*surface->pitch);
if ( surface->pixels == NULL ) {
GAL_FreeSurface(surface);
GAL_OutOfMemory();
return(NULL);
}
/* This is important for bitmaps */
memset(surface->pixels, 0, surface->h*surface->pitch);
surface->flags &= ~GAL_HWSURFACE; // 那标识该surface的pixels是使用malloc获取的本机内存,而非lcd驱动器中物理内存.
}
}
/* Allocate an empty mapping */
surface->map = GAL_AllocBlitMap();
if ( surface->map == NULL ) {
GAL_FreeSurface(surface);
return(NULL);
}
/* The surface is ready to go */
surface->refcount = 1;
#ifdef CHECK_LEAKS
++surfaces_allocated;
#endif
return(surface);
}
阅读(4042) | 评论(0) | 转发(0) |