Ответ 1
OpenGL на самом деле не является библиотекой. Это спецификация. У вас в вашей системе opengl32.dll или libGL.so есть очень тонкие слои, которые взаимодействуют с драйвером GPU.
В соответствии с тем, что я слышал, c и С++ не предоставляют графических функций, встроенных в язык, и для создания графики требуются библиотеки. Как же эти библиотеки написаны в c?
Операционная система предлагает функции для общения с оборудованием. Драйвер использует эти средства для управления (отсюда и название) аппаратного обеспечения. Например, запись последовательности A, B, C, D может привести к тому, что некоторый определенный графический процессор нарисует треугольник в фреймбуфере.
Я объяснил те вещи, которые уже существуют в В Windows, как OpenGL отличается от DirectX? и здесь Как работает OpenGL самый низкий уровень? (я включаю в себя дословную цитату здесь):
Этот вопрос почти невозможно ответить, потому что OpenGL сам по себе является просто интерфейсом API, и пока реализации придерживаются спецификация и результат соответствуют этому, это может быть сделано любым как вам нравится.
Возможно, возник вопрос: как работает драйвер OpenGL на самый низкий уровень. Теперь это снова невозможно ответить в целом, поскольку драйвер тесно связан с некоторыми аппаратными средствами, что может снова что разработчик разработал.
Итак, вопрос должен был быть: "Как это выглядит в среднем позади сцены OpenGL и графической системы?". Посмотрите на это снизу вверх:
На самом низком уровне есть какое-то графическое устройство. В настоящее время это графические процессоры, которые предоставляют набор регистров, контролирующих их работу (которые точно регистрируются в зависимости от устройства) имеют некоторую программную память для шейдеров, объемной памяти для входных данных (вершин, текстур и т.д.) и канал ввода-вывода для остальной части системы, через которую он получает/отправляет данных и команд.
Графический драйвер отслеживает состояние GPU и все прикладные программы ресурсов, которые используют графический процессор. Также это ответственных за преобразование или любую другую обработку данных, отправленных приложений (преобразовать текстуры в пиксельный формат, поддерживаемый GPU, скомпилируйте шейдеры в машинный код графического процессора). Кроме того, предоставляет некоторый абстрактный, зависящий от драйвера интерфейс к приложению программы.
Затем есть драйверная библиотека/драйвер OpenGL, зависящая от драйвера. В Windows это загружается через proxy через opengl32.dll, в Unix систем, которые находятся в двух местах: * X11 GLX модуль и драйвер зависимый драйвер GLX * и /usr/lib/libGL.so может содержать некоторый драйвер зависимый материал для прямого рендеринга
В MacOS X это будет "OpenGL Framework".
Именно эта часть переводит вызовы OpenGL, как вы это делаете, в вызовы к конкретным функциям драйвера в описанной части драйвера в (2).
Наконец, фактическая библиотека API OpenGL, opengl32.dll в Windows и Unix/usr/lib/libGL.so; это в основном просто передает команды к собственно реализации OpenGL.
То, как происходит фактическое общение, не может быть обобщено:
В Unix соединение 3 ↔ 4 может происходить либо через сокеты (да, это может, и действительно перейдет через сеть, если вы хотите) или через Shared Память. В Windows интерфейсная библиотека и клиентский драйвер оба загружены в адресное пространство процесса, так что не так много но простые вызовы функций и передача переменных/указателей. В MacOS X это похоже на Windows, только что нет разделения между интерфейсом OpenGL и клиентом драйвера (причина MacOS X настолько медленно, что не отстает от новых версий OpenGL, это всегда требует полного обновления операционной системы для доставки нового рамки).
Связь betwen 3 ↔ 2 может проходить через ioctl, чтение/запись или путем отображения некоторой памяти в адресное пространство процесса и настройки MMU запускать некоторый код драйвера при каждом изменении этой памяти сделано. Это очень похоже на любую операционную систему, так как вы всегда приходится пересекать границу ядра/пользователя: в конечном итоге вы идете через некоторый syscall.
Связь между системой и графическим процессором происходит через перифиальную шину и методы доступа, которые он определяет, поэтому PCI, AGP, PCI-E и т.д., которые работают через порт-ввод-вывод, память с отображением ввода-вывода, DMA, IRQ.
Update
Чтобы ответить, как один интерфейс реального оборудования из программы C говорит о ядре ОС и/или драйвере, написанном на C:
Сам стандарт C трактует адреса как нечто чисто абстрактное. Вы можете наложить указатель на uintptr_t, но числовое значение, которое вы получаете, требуется только для привязки к арифметике указателя, если оно возвращается к указателю. В противном случае значение может быть не связано с адресным пространством. Единственный безопасный способ реализовать аппаратный доступ к C - это записать материал самого низкого уровня в сборке, следуя ABI используемой реализации C и системы.
То, как это делают все правильные ОС. Никогда не указываются адреса в указателях в C! Операционная система реализовала это в ассемблере, соответствующем компилятору C системы. Код, записанный в сборке, экспортируется как функции, вызываемые в C. Ядро предоставляет эти функции затем драйверу графического процессора. Таким образом, цепочка:
Прикладная программа → [Уровень API OpenGL → Реализация OpenGL поставщика] → Драйвер графического процессора → Ядро операционной системы → Оборудование.