функция обратного вызова PDD_CREATESURFACEEX (ddrawint.h)
Функция D3dCreateSurfaceEx уведомляет о связи поверхности Microsoft DirectDraw и значения дескриптора Microsoft Direct3D, чтобы включить настройку поверхности для отрисовки Direct3D.
Синтаксис
PDD_CREATESURFACEEX PddCreatesurfaceex;
DWORD PddCreatesurfaceex(
PDD_CREATESURFACEEXDATA unnamedParam1
)
{...}
Параметры
unnamedParam1
Указывает на структуру DD_CREATESURFACEEXDATA , содержащую сведения, необходимые драйверу для создания поверхности.
Возвращаемое значение
D3dCreateSurfaceEx возвращает один из следующих кодов обратного вызова:
Комментарии
Все драйверы Direct3D должны поддерживать D3dCreateSurfaceEx.
D3dCreateSurfaceEx создает связь между поверхностью DirectDraw и небольшим целым дескриптором поверхности. Создавая эти связи между дескриптором и поверхностью DirectDraw, D3dCreateSurfaceEx позволяет внедрить дескриптор поверхности в поток команд Direct3D. Например, когда маркер команды D3DDP2OP_TEXBLT отправляется в функцию D3dDrawPrimitives2 драйвера для загрузки карты текстуры, он использует дескриптор источника и дескриптор назначения, которые были связаны с поверхностью DirectDraw через D3dCreateSurfaceEx.
Для каждой поверхности DirectDraw, созданной в локальном объекте DirectDraw, среда выполнения создает допустимый дескриптор, который однозначно идентифицирует поверхность и помещает дескриптор в элемент dwSurfaceHandleструктуры DD_SURFACE_MORE . Элемент lpDDSLcl структуры DD_CREATESURFACEEXDATA в pcsxd указывает на структуру DD_SURFACE_LOCAL , содержащую элемент lpSurfMore , указывающий на этот DD_SURFACE_MORE. Это значение дескриптора также используется с состоянием D3DRENDERSTATE_TEXTUREHANDLE отрисовки для включения форматирования, а также с командами D3DDP2OP_SETRENDERTARGET и D3DDP2OP_CLEAR для задания и очистки новых буферов отрисовки и глубины. Драйвер должен завершить вызов и вернуть DDHAL_DRIVER_HANDLED, если ему не удается создать поверхность Direct3D.
Для поверхности системной памяти или области видеопамяти при вызове D3dCreateSurfaceEx для уведомления об ассоциации dwSurfaceHandle с DD_SURFACE_GLOBAL и DD_SURFACE_LOCAL структурами поверхности драйвер дисплея может хранить любые данные (например, указатель на выделенную в частном порядке память) в членах dwReserved1 DD_SURFACE_GLOBAL и DD_SURFACE_LOCAL, так как эти элементы зарезервированы драйвером дисплея для частного использования.
Чтобы уведомить драйвер дисплея о том, что поверхность системной памяти должна быть освобождена, среда выполнения задает элемент указателя fpVidMem структуры DD_SURFACE_GLOBAL поверхности системной памяти равным нулю и вызывает обратный вызов D3dCreateSurfaceEx драйвера дисплея. Помимо освобождения всех ресурсов, связанных с этой поверхностью, драйвер дисплея должен очистить данные, которые ранее хранились в элементах dwReserved1 . Обратите внимание, что поскольку элемент указателя fpVidMem для поверхности видеопамяти может быть равен нулю, драйвер дисплея должен проверить, находится ли поверхность в видео или системной памяти, чтобы определить, предназначен ли вызов D3dCreateSurfaceEx для уведомления о связи поверхности видеопамяти с dwSurfaceHandle или уведомления об отмене связи поверхности системной памяти с dwSurfaceHandle.
D3dCreateSurfaceEx не вызывается для уведомления об отмене связи поверхности видеопамяти с dwSurfaceHandle; обратный вызов DdDeтяжеяSurface драйвера дисплея должен обрабатывать удаление локальной и нелокальной поверхности видеопамяти и очищать данные, которые ранее хранились в членах dwReserved1 .
Драйвер также должен хранить все сведения, связанные с поверхностью, необходимые при использовании поверхности. Драйвер должен создать новую таблицу поверхностей для каждого нового lpDDLcl и неявно увеличить таблицу, когда это необходимо для размещения большего размера поверхностей. Как правило, это делается с помощью алгоритма экспоненциального роста, чтобы не увеличивать таблицу слишком часто. Дополнительные сведения о реализации см. в примере драйвера Perm3 , который входит в состав пакета средств разработки драйверов Microsoft Windows (DDK). (DDK предшествовал комплекту драйверов Windows [WDK].)
D3dCreateSurfaceEx можно вызвать только с отключенным PDEV для поверхности системной памяти. PDEV отключается или включается путем вызова функции DrvAssertMode драйвера дисплея. Дополнительные сведения см. в разделе Управление PDEV .
Пример реализации D3dCreateSurfaceEx
LPDDRAWI_DDRAWSURFACE_LCL GetAttachedSurface(
LPDDRAWI_DDRAWSURFACE_LCL pLcl,
DDSCAPS2 * pddsCaps2)
{
LPATTACHLIST pAl;
pAl = pLcl->lpAttachList;
while (pAl) {
LPDDRAWI_DDRAWSURFACE_LCL pLclAttached = pAl->lpAttached;
LPATTACHLIST pAlAttached = pLclAttached->lpAttachList;
if ((pLclAttached->lpSurfMore->ddsCapsEx.dwCaps2 & pddsCaps2->dwCaps2) ||
(pLclAttached->lpSurfMore->ddsCapsEx.dwCaps3 & pddsCaps2->dwCaps3) ||
(pLclAttached->lpSurfMore->ddsCapsEx.dwCaps4 & pddsCaps2->dwCaps4) ||
(pLclAttached->ddsCaps.dwCaps & pddsCaps2->dwCaps)
)
{
return pLclAttached;
}
pAl = pAl->lpLink;
}
return NULL;
}
void CSExProcessPossibleMipmap(LPDDRAWI_DDRAWSURFACE_LCL pLcl)
{
//
// A more likely scenario would be to build a list of surfaces
// so that the driver can create one structure that represents the
// entire mipmap, rather than creating an object to represent each
// level as depicted here.
//
DDSCAPS2 ddsCaps2 = {0,DDSCAPS2_MIPMAPSUBLEVEL,0,0};
while (pLcl) {
//Call the private driver routine that creates a driver-side surface structure
CreateMyRepresentation(pLcl);
pLcl = GetAttachedSurface(pLcl,&ddsCaps2);
}
}
//
// The actual return type should reflect the fact that the only
// way this routine should fail is with DDERR_OUTOFMEMORY
//
void MyCreateSurfaceExHelper(LPDDRAWI_DDRAWSURFACE_LCL pLcl)
{
LPATTACHLIST pAl;
DDSCAPS2 ddsCaps2 = {0,0,0,0};
LPDDRAWI_DDRAWSURFACE_LCL pLclAttached;
LPDDRAWI_DDRAWSURFACE_LCL pLclStart;
if (pLcl->lpGbl->fpVidMem == 0) {
//A required check against bad surfaces
if (pLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
return;
//Else, this is a system memory surface, so we are being informed of
// its destruction
DestroyMyRepresentation(pLcl->lpSurfMore->dwSurfaceHandle);
return;
}
CSExProcessPossibleMipmap(pLcl);
if (pLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP) {
int i;
//
// The root surface is always positive X, so we check for the
// other five face types.
//
DWORD dw[5] = {
DDSCAPS2_CUBEMAP_NEGATIVEX,
DDSCAPS2_CUBEMAP_POSITIVEY,
DDSCAPS2_CUBEMAP_NEGATIVEY,
DDSCAPS2_CUBEMAP_POSITIVEZ,
DDSCAPS2_CUBEMAP_NEGATIVEZ};
for(i=0;i< sizeof(dw)/sizeof(dw[0]);i++) {
ddsCaps2.dwCaps2 = dw[i];
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
if (pLclAttached)
CSExProcessPossibleMipmap(pLclAttached);
}
//
// Once we know it's a cube map, we know there cannot be any other
// attachments.
//
return;
}
//
// At this point:
// If it's a cubemap, we returned above.
// If it's a mipmap, we handled all cases above.
// The only other complex surface possibility is a primary flipping chain.
// Because a primary flipping chain cannot be mipmapped, we will simply return
// here if this surface is a mipmap.
//
if (pLcl->ddsCaps.dwCaps & DDSCAPS_MIPMAP)
return;
//
// The only system memory surfaces we'll ever be interested in are textures (mipmaps)
// and cube maps. We do not propagate an error code for system memory
// surfaces whose format we do not understand. This could cause an error code to
// be propagated to the application when it was trying to use system memory surfaces
// of a format we do not understand, but is valid for the reference rasterizer, for example.
//
if (pLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
return;
//
// Now walk around a flipping chain. A flipping chain is a ring of
// surfaces attached to each other (each surface is attached to the next
// and to the previous surface in the ring, but not to any other surface
// in the ring).
// We need to watch out for this circular ring and make sure we exit appropriately.
// There is also the possibility of a z buffer attached to one of the surfaces
// in the ring, which may or may not have been CreateSurfaceEx'ed already.
//
pLclStart = pLcl;
while (pLcl && pLcl != pLclStart) {
//Check for Z buffer attached to this surface in the ring.
ddsCaps2.dwCaps = DDSCAPS_ZBUFFER;
ddsCaps2.dwCaps2 = 0;
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
if (pLclAttached)
CreateMyRepresentation(pLclAttached);
//Check for stereo left surface attached to this surface in the ring
ddsCaps2.dwCaps = 0;
ddsCaps2.dwCaps2 = DDSCAPS2_STEREOSURFACELEFT;
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
if (pLclAttached)
CreateMyRepresentation(pLclAttached);
// Move to next surface in the primary flipping ring. The next surface is
// definitely in video memory (all surfaces in an attachment structure have
// to be in the same memory type, and we excluded system memory above).
// The next surface in the ring is thus the attached video memory surface
// that is NOT a z buffer NOR a stereo left surface.
ddsCaps2.dwCaps = DDSCAPS_VIDEOMEMORY;
ddsCaps2.dwCaps2 = 0;
do {
pLclAttached = GetAttachedSurface(pLcl, &ddsCaps2);
}
while (
pLclAttached->ddsCaps.dwCaps & DDSCAPS_ZBUFFER ||
pLclAttached->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT
);
pLcl = pLclAttached;
if (pLcl != pLclStart)
CreateMyRepresentation(pLcl);
}
}
Требования
Целевая платформа | Персональный компьютер |
Верхняя часть | ddrawint.h (включая Winddi.h) |