PDD_SURFCB_LOCK 콜백 함수(ddrawint.h)
DdLock 콜백 함수는 지정된 표면 메모리 영역을 잠그고 표면과 연결된 메모리 블록에 대한 유효한 포인터를 제공합니다.
구문
PDD_SURFCB_LOCK PddSurfcbLock;
DWORD PddSurfcbLock(
PDD_LOCKDATA unnamedParam1
)
{...}
매개 변수
unnamedParam1
잠금을 수행하는 데 필요한 정보가 포함된 DD_LOCKDATA 구조를 가리킵니다.
반환 값
DdLock은 다음 콜백 코드 중 하나를 반환합니다.
설명
DdLock은 lpLock에서 DD_LOCKDATA 구조체의 ddRVal 멤버를 DDERR_WASSTILLDRAWING 설정하고 블릿 또는 대칭 이동이 진행 중인 경우 DDHAL_DRIVER_HANDLED 반환해야 합니다.
DD_LOCKDATA dwFlags 멤버가 달리 지정하지 않는 한 드라이버는 DD_LOCKDATA lpSurfData 멤버의 표면 맨 위에 메모리 포인터를 반환할 수 있습니다. 드라이버가 표면에 대한 자체 주소를 계산해야 하는 경우 DD_LOCKDATA fpProcess 멤버에 전달된 포인터를 DirectDraw 액세스 가능한 프레임 버퍼의 사용자 모드 매핑에 대한 프로세스별 포인터로 사용할 수 있습니다.
잠금은 요청된 메모리 블록에 대한 단독 액세스를 제공하지 않습니다. 즉, 여러 스레드가 동시에 동일한 표면을 잠글 수 있습니다. 포인터를 가져오는 메모리 블록에 대한 액세스를 동기화하는 것은 애플리케이션의 책임입니다.
NT 기반 운영 체제에서 실행되는 드라이버는 해당 드라이버의 DdCreateSurface 함수가 이전에 PLEASE_ALLOC_USERMEM 플래그를 사용하여 이러한 메모리를 할당하지 않는 한 DdLock 함수에서 시스템 메모리에 대한 포인터를 반환해서는 안 됩니다. PLEASE_ALLOC_USERMEM 사용하지 않은 경우 애플리케이션은 이러한 메모리에 액세스하려고 할 때마다 오류를 수신할 수 있습니다. 자세한 내용은 NT 커널의 DDLOCK_NOSYSLOCK 구현 을 참조하세요.
사용하지 않도록 설정된 PDEV를 사용하여 DdLock을 호출할 수 있습니다. 디스플레이 드라이버의 DrvAssertMode 함수를 호출하여 PDEV를 사용하지 않도록 설정하거나 사용할 수 있습니다. 자세한 내용은 PDEV 관리를 참조하세요.
NT 커널의 DDLOCK_NOSYSLOCK 구현
애플리케이션은 DirectDraw 및 Direct3D의 API(애플리케이션 프로그래밍 인터페이스)를 사용하여 비디오 메모리 리소스에 대한 장기 잠금을 가져올 수 있습니다. 이러한 잠금을 "NOSYSLOCK" 잠금이라고 합니다. 이러한 잠금은 다음 단락에 설명된 대로 일반적인 비디오 메모리 잠금과 다르게 작동합니다.DirectDraw 런타임이 DD_LOCKDATA dwFlags 멤버에 지정된 DDLOCK_NOSYSLOCK 플래그를 사용하여 드라이버의 DdLock 함수를 호출한 후 런타임은 드라이버가 반환한 표면 내용에 대한 포인터를 검사합니다. 런타임은 드라이버 반환 포인터를 애플리케이션에 직접 전달하는 대신 비디오 메모리(로컬 및 비로컬)의 두 번째 사용자 모드 매핑을 만들고 해당 매핑 내에서 동등한 가상 주소를 계산합니다. 이 가상 주소를 메모리 잠금에 대한 별칭 포인터라고 합니다. 런타임은 이 별칭 잠금 포인터를 애플리케이션에 전달합니다. 애플리케이션은 이 별칭 잠금 포인터를 사용하여 비디오 메모리를 직접 읽고 씁니다. 애플리케이션과 드라이버 모두 다른 잠긴 메모리 포인터를 사용한다는 사실을 인식하지 않습니다.
나중에 모드 전환 시 DirectDraw 런타임은 미해결 별칭 잠금 포인터를 기록합니다. 일반적인 비디오 메모리 잠금과 마찬가지로 별칭 잠금 포인터가 완료될 때까지 기다리는 대신 런타임은 비디오 메모리의 사용자 모드 매핑을 다시 매핑하고 모드 전환을 계속할 수 있도록 합니다. 런타임은 사용자 모드 매핑을 단일 더미 페이지에 다시 매핑합니다. 애플리케이션은 해당 더미 페이지를 계속 읽고 씁니다. 그렇지 않으면 변경 내용을 인식하지 못합니다. 그런 다음 런타임은 드라이버의 DdUnlock 함수를 호출하여 별칭 잠금 포인터를 클린 합니다. 애플리케이션이 더 이상 비디오 메모리에 기록되지 않으므로 런타임은 별칭 잠금 포인터를 클린 수 있습니다. 이 클린 모드 전환 시 발생하기 때문에 시퀀스의 다음 단계는 표면을 잃어버리는 것입니다. 즉, 드라이버의 표면별 개체가 파괴됩니다. 즉, 런타임은 애플리케이션이 계속 잠긴 것으로 간주하는 표면을 포함하여 모든 표면에 대해 드라이버의 DdDestroySurface 함수를 호출합니다. 실제로 애플리케이션은 시스템 메모리의 더미 페이지에 계속 읽고 씁니다.
이 전체 프로세스는 DdLock 에서 반환된 메모리 포인터가 비디오 메모리의 일부 매핑인 경우에만 작동합니다. 이 비디오 메모리 매핑은 DirectDraw 커널 모드 런타임에서 수행하는 비로컬 비디오 메모리의 사용자 모드 매핑 또는 드라이버의 DdMapMemory 함수에서 제공하는 매핑일 수 있습니다. 메모리 포인터가 이러한 매핑 중 하나에 기인할 수 없는 경우 런타임은 잠금을 다시 매핑하지 않습니다. 모드 스위치는 계속되며, 이는 드라이버의 표면 개체가 각각 드라이버의 DdUnlock 및 DdDestroySurface 함수를 호출하여 잠금 해제되고 제거됨을 의미합니다. 그런 다음 드라이버는 일반적으로 드라이버가 잠금 시간에 할당한 시스템 메모리를 해제합니다. 애플리케이션이 여전히 이 메모리에 쓰고 있기 때문에 액세스 위반이 발생합니다.
따라서 드라이버의 DdCreateSurface 함수가 이전에 PLEASE_ALLOC_USERMEM 플래그와 함께 이러한 메모리를 할당하지 않는 한 드라이버는 DdLock 함수에서 시스템 메모리 포인터를 반환하려고 시도해서는 안 됩니다. DirectDraw 런타임은 이러한 방식으로 할당된 메모리를 소유하며 애플리케이션이 메모리를 잠금 해제할 때까지 이 메모리의 릴리스를 연기할 수 있습니다. 따라서 드라이버의 DdLock 함수는 애플리케이션이 충돌할 위험 없이 이러한 방식으로 할당된 메모리에 대한 포인터를 반환할 수 있습니다.
요구 사항
요구 사항 | 값 |
---|---|
대상 플랫폼 | 데스크톱 |
머리글 | ddrawint.h(Winddi.h 포함) |