функция обратного вызова PDD_SURFCB_LOCK (ddrawint.h)
Функция обратного вызова DdLock блокирует указанную область поверхностной памяти и предоставляет допустимый указатель на блок памяти, связанный с поверхностью.
Синтаксис
PDD_SURFCB_LOCK PddSurfcbLock;
DWORD PddSurfcbLock(
PDD_LOCKDATA unnamedParam1
)
{...}
Параметры
unnamedParam1
Указывает на структуру DD_LOCKDATA , содержащую сведения, необходимые для выполнения блокировки.
Возвращаемое значение
DdLock возвращает один из следующих кодов обратного вызова:
Комментарии
DdLock должен задать для элемента ddRVal структуры DD_LOCKDATA в lpLock значение DDERR_WASSTILLDRAWING и вернуть DDHAL_DRIVER_HANDLED, если выполняется перерез или пролистывание.
Если иное не указано членом dwFlags DD_LOCKDATA, драйвер может вернуть указатель памяти в верхнюю часть поверхности элемента lpSurfData DD_LOCKDATA. Если драйверу необходимо вычислить собственный адрес для поверхности, он может полагаться на указатель, переданный в элементе fpProcess DD_LOCKDATA как указатель на сопоставление в пользовательском режиме буфера кадров, доступного для DirectDraw.
Блокировка не обеспечивает монопольный доступ к запрошенным блокам памяти; то есть несколько потоков могут одновременно блокировать одну и ту же поверхность. Приложение отвечает за синхронизацию доступа к блоку памяти, указатель которого получается.
Драйвер, работающий в операционной системе на основе NT, не должен возвращать указатель на системную память из своей функции DdLock , если только функция DdCreateSurface этого драйвера ранее не выделила такую память с флагом PLEASE_ALLOC_USERMEM. Если PLEASE_ALLOC_USERMEM не используется, приложения могут получать ошибки при попытке получить доступ к такой памяти. Дополнительные сведения см. в разделе Реализация DDLOCK_NOSYSLOCK ядра NT .
DdLock можно вызвать с отключенным PDEV. PDEV отключается или включается путем вызова функции DrvAssertMode драйвера дисплея. Дополнительные сведения см. в разделе Управление PDEV .
Реализация DDLOCK_NOSYSLOCK в ядре NT
Приложения могут использовать API DirectDraw и Direct3D для получения длительных блокировок ресурсов видеопамять. Такие блокировки называются блокировками NOSYSLOCK. Эти блокировки работают иначе, чем обычные блокировки видеопамять, как описано в следующих абзацах.После того как среда выполнения DirectDraw вызывает функцию DdLock драйвера с флагом DDLOCK_NOSYSLOCK, указанным в элементе dwFlags DD_LOCKDATA, среда выполнения проверяет указатель на содержимое поверхности, возвращенное драйвером. Вместо передачи указателя, возвращаемого драйвером, непосредственно в приложение, среда выполнения создает второе сопоставление видеопамять в пользовательском режиме (локальной и нелокальной) и вычисляет эквивалентный виртуальный адрес в этом сопоставлении. Этот виртуальный адрес называется указателем псевдонима на блокировку памяти. Среда выполнения передает этому указателю блокировки псевдонима приложению. Приложение использует этот указатель блокировки псевдонима для чтения и записи непосредственно в видеопамять. Ни приложение, ни драйвер не знают, что он использует другой указатель заблокированной памяти.
Позже, во время переключения режима, среда выполнения DirectDraw замечает все незавершенные указатели блокировки псевдонимов. Вместо того, чтобы ждать завершения указателей блокировки псевдонимов( как это было бы для обычной блокировки видеопамяти), среда выполнения переназначает сопоставление пользовательского режима видеопамяти и позволяет продолжить переключение режима. Среда выполнения повторно сопоставляет сопоставления пользовательского режима с одной фиктивной страницей; приложение продолжает читать и записывать данные на эту фиктивную страницу, в противном случае не зная о каких-либо изменениях. Затем среда выполнения должна очистить указатели блокировки псевдонимов, вызвав функцию DdUnlock драйвера. Среда выполнения может очистить указатели блокировки псевдонимов, так как приложение больше не записывает данные в видеопамяти. Так как эта очистка происходит во время переключения режима, следующим шагом в последовательности является потеря поверхностей, что означает уничтожение объектов драйвера для каждой поверхности. Иными словами, среда выполнения вызывает функцию DdDebaseface драйвера для всех поверхностей, включая поверхности, которые приложение по-прежнему считает заблокированными. Фактически приложение продолжает считывать и записывать данные на фиктивную страницу системной памяти.
Весь этот процесс работает только в том случае, если указатель памяти, возвращаемый DdLock , является сопоставлением видеопамяти. Это сопоставление видеопамяти может быть сопоставлением нелокальной видеопамяти в пользовательском режиме, выполняемым средой выполнения DirectDraw в режиме ядра, или сопоставлением, предоставляемым функцией DdMapMemory драйвера. Если указатель памяти не может быть отнесен к одному из этих сопоставлений, среда выполнения не переназначает блокировку. Переключение режима продолжается, что означает, что поверхностный объект драйвера разблокируется и уничтожается с помощью вызовов функций DdUnlock и DdDesurface драйвера соответственно. Затем драйвер обычно освобождает любую системную память, выделенную драйвером во время блокировки. Так как приложение по-прежнему записывает данные в эту память, происходит нарушение доступа.
Следовательно, драйвер не должен пытаться вернуть указатели системной памяти из своей функции DdLock , если только функция DdCreateSurface этого драйвера ранее не выделила такую память с флагом PLEASE_ALLOC_USERMEM. Среда выполнения DirectDraw владеет памятью, выделенной таким образом, и может отложить выпуск этой памяти до тех пор, пока приложение не разблокирует память. Таким образом, функция DdLock драйвера может возвращать указатели на память, выделенную таким образом, без риска сбоя приложения.
Требования
Требование | Значение |
---|---|
Целевая платформа | Персональный компьютер |
Верхняя часть | ddrawint.h (включая Winddi.h) |