Doç. Dr. Ahmet Oğuz Akyüz

Hızla gelişmekte olan OpenGL ve kullandığı profilleme sistemi kafa karıştırıcı olabilir. Bu yazımızda, OpenGL profillerinin arkasında yatan mantığı ve OpenGL'in sahip olduğu kullanımdan kaldırma modelini açıklayacağız. Bazı kod parçaları paylaşarak istenilen bir OpenGL profilinin nasıl seçilebileceğini de örneklendireceğiz.

Öncelikle, OpenGL'in başlangıçtan 3.0 versiyonuna kadar geçmiş sürümlerle uyumlu olduğunu hatırlatalım. Yani yeni bir OpenGL versiyonunu destekleyen bir sistem aynı zamanda eski OpenGL versiyonları için yazılmış olan programları da çalıştırmak zorunda idi. Bu durum uygulama geliştiricileri için her ne kadar kolaylık sağlasa da, OpenGL sürücüsü yazan ekipler açısından oldukça ciddi bir yük teşkil ediyordu. Bu hem OpenGL sürücülerinin Direct3D gibi geriye dönüş desteği sağlamayan API'lere göre daha yavaş olmasına yol açıyor hem de sürücülerin çok büyümesinden dolayı daha fazla böcek oluşmasına sebebiyet veriyordu.

OpenGL 3.0 ilk defa kullanımdan kaldırma (deprecation) modelini hayata geçirdi. Buna göre OpenGL'in artık pek kullanılmayan bazı özellikleri kullanımdan kaldırılmak üzere işaretlendi. Bu işaretleme bu özelliklerin daha sonraki bir OpenGL versiyonunda desteklenmeyebileceği anlamına geliyordu.

OpenGL 3.0 hiçbir özelliği kaldırmasa da (sadece işaretlemekle yetindi), ileriye dönük profiller seçme olanağını sağladı. Bu tür profiller seçildiği taktirde kullanımdan kaldırılacak olarak işaretlenen özellikler API'den çıkarılmış oluyordu. Bunun amacı uygulama geliştiricilerin uygulamalarını ileriye dönük OpenGL versiyonları için test etmelerine olanak tanımaktı. Ancak bu mod varsayılan olarak değil programcı tarafından özel olarak istenirse destekleniyordu.

İleriye dönük profilleri seçebilmek için programcıya bazı yeni API'lar sunmak gerekiyordu. Bu amaçla yeni WGL (Windows) ve GLX (Linux) uzantıları yaratıldı (WGL_ARB_create_context, WGL_ARB_create_context_profile ve bunların GLX karşılıkları). Bu uzantıların kullanımları yazımızın devamında örneklendirilecektir.

OpenGL 3.1 ile birlikte, 3.0'da işaretlenen bütün özellikler kaldırıldı. Bu OpenGL'in geçmişe dönük desteği ilk olarak kırdığı versiyondur. Fakat, sürücü geliştiriciler için kaldırılan özelliklerin halen desteklenmesine yönelik açık bir kapı bırakıldı. Eğer bir sürücü GL_ARB_compatibility uzantısını destekliyorsa kaldırılan bütün özellikler o sürücü tarafından destekleniyor demekti. Bütün büyük üreticilerin (NVIDIA, AMD gibi) sürücüleri bu uzantıyı destekledi. OpenGL 3.1 hiçbir özelliği kullanımdan kaldırılmış olarak işaretlemedi.

OpenGL 3.2 ile birlikte bu konu daha büyük bir resmiyet kazanmaya başladı. İlk defa bu versiyonda birden çok profil arasından istenilen bir profilin seçilmesine olanak tanındı. OpenGL 3.2'de çekirdek ve uyumluluk profilleri olmak üzere iki profil tanımlandı. Çekirdek profil seçildiğinde kullanımdan kaldılacak olarak işaretlenmiş bütün özellikler kullanım dışı bırakılıyordu. Uyumluluk profili sayesinde ise geçmiş desteği veren bir versiyon seçilmiş oluyordu. 3.2'de sunulan bu profilleme sistemi 3.1'de önerilen GL_ARB_compatibility uzantısı metodunun yerine geçmiş oldu. OpenGL 3.2 ek olarak sadece bir tek özelliği kullanımdan kaldırılacak olarak işaretledi (MAX_VARYING_COMPONENTS ve MAX_VARYING_FLOATS sorguları). OpenGL'in daha yeni versiyonları (3.3, 4.0, ve 4.1) 3.2'nin getirmiş olduğu profil seçme sisteminde bir değişikliğe gitmedi ve yeni özellikleri kaldırılacak olarak işaretlemedi.

Bu kısa tarihçeden sonra şimdi de bir programcının istediği OpenGL versiyon ve profilini nasıl seçebileceğini inceleyelim. Öncelikle varsayılan bir OpenGL içeriği yaratmak için standart wglCreateContext fonksiyonunu çağırmamız gerektiğini hatırlayalım (bu yazıda Windows örnekleri verilecektir, Linux için wgl ifadelerinin glx ile değiştirilmesi yeterli olacaktır). Bu varsayılan içeriği yukarıda bahsedilen yeni tanımlanmış olan fonksiyonların adresini almak için kullanacağız. Örnekte görüldüğü gibi ilgili fonksiyonun (wglCreateContextAttribsARB) adresini aldıktan sonra bu varsayılan içeriği silebiliriz.

#include <windows.h>
#include <GL/gl.h>
#include "wglext.h"

PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;

void InitWGLFuncPtrs(HDC hDC)
{
    HGLRC hTempRC = wglCreateContext(hDC);

    wglMakeCurrent(hDC, hTempRC);

    wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");

    wglMakeCurrent(hDC, NULL);
    wglDeleteContext(hTempRC);
}

Örneğin OpenGL 3.3 versiyonuna sahip ileriye dönük bir çekirdek profili istediğimizi varsayalım (Çekirdek profil o versiyona kadar olan kaldırılmış bütün özelliklerin çıkarıldığı bir profildir. İleriye dönük ise kullanımdan kaldırılacak olan özelliklerin de çıkarıldığı profili belirtir). Bu isteğimizi aşağıdaki kod ile yapabiliriz:

void CreateOpenGLContext(HDC hDC)
{
    int attribList[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
        WGL_CONTEXT_MINOR_VERSION_ARB, 3,
        WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
        WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0, 0
    };

    HGLRC hRC = wglCreateContextAttribsARB(hDC, 0, attribList);
    wglMakeCurrent(hDC, hRC);
}

Görülebileceği üzere wglCreateContextAttribsARB çift 0 ile sonlanan bir özellik dizisi almaktadır. Bu özelliklerden istediğimiz kadarını belirtebiliriz; belirtmediğimiz özellikler WGL_ARB_create_context_profile uzantısı dökümanında açıklanan varsayılan değerlere atanacaktır. Eğer sistemde yüklü olan OpenGL sürücüsü istenilen profili desteklemiyorsa wglCreateContextAttribsARB fonksiyonu NULL dönecektir. Bu yüzden bu fonksiyonun döndüğü değeri kontrol etmek yerinde olacaktır. Son olarak istenilen profilin gerçekten seçilip seçilmediği glGetString(GL_VERSION) fonksiyonundan dönen karakter dizisine bakılarak da doğrulanabilir.

Bu kısa yazımızda istenilen OpenGL versiyon ve profilinin nasıl seçileceğini açıklamaya çalıştık. Daha ayrıntılı bilgi için www.opengl.org adresindeki OpenGL dökümanlarına ve WGL_ARB_create_context_profile uzantısının metnine bakmak faydalı olabilir.