Chcę napisać proste opakowanie RAII dla obiektów OpenGL (tekstury, bufory ramek itp.) Zauważyłem, że wszystkie funkcje glGen*
i glDelete*
mają tę samą sygnaturę, więc moja pierwsza próba była taka :Otoczka RAII dla obiektów OpenGL
typedef void (__stdcall *GLGenFunction)(GLsizei, GLuint *);
typedef void (__stdcall *GLDelFunction)(GLsizei, const GLuint *);
template <GLGenFunction glGenFunction, GLDelFunction glDelFunction>
class GLObject
{
GLuint m_name;
public:
GLObject()
{
glGenFunction(1, &m_name);
}
~GLObject()
{
glDelFunction(1, &m_name);
}
GLuint getName() {return m_name;}
};
typedef GLObject<glGenTextures, glDeleteTextures> GLTexture;
To działa dobrze dla tekstur, ale nie dla buforów ramki: glGenFramebuffers
i glDeleteFramebuffers
adresy funkcyjne nie są znane w czasie kompilacji i nie mogą być używane jako argumenty szablonów. Więc zrobiłem drugą wersję:
class GLObjectBase
{
GLuint m_name;
GLDelFunction m_delFunction;
public:
GLObjectBase(GLGenFunction genFunc, GLDelFunction delFunction)
: m_delFunction(delFunction)
{
genFunc(1, &m_name);
}
GLuint getName()
{
return m_name;
}
protected:
~GLObjectBase()
{
m_delFunction(1, &m_name);
}
};
class GLFrameBuffer : public GLObjectBase
{
public:
GLFrameBuffer() : GLObjectBase(glGenFramebuffers, glDeleteFramebuffers) {}
};
Ale nie podoba mi się to, ponieważ mam do przechowywania del wskaźnik funkcji w każdym przypadku, że nie ulegnie zmianie w czasie wykonywania.
Jak utworzyć klasę opakowania, w której zapisuje się tylko nazwę obiektu w każdym wystąpieniu bez konieczności tworzenia grupy prawie skopiowanych przez kopiowanie klas?
mógłby zrobić coś takiego:
template <int N>
class GLObject2
{
GLuint m_name;
static GLDelFunction glDelFunction;
public:
GLObject2(GLGenFunction genFunction, GLDelFunction delFunc)
{
genFunction(1, &m_name);
if (glDelFunction == nullptr)
glDelFunction = delFunc;
ASSERT(glDelFunction == delFunc);
}
GLuint getName() {return m_name;}
protected:
~GLObject2()
{
glDelFunction(1, &m_name);
}
};
template <int N>
GLDelFunction GLObject2<N>::glDelFunction = nullptr;
class GLTexture: public GLObject2<1>
{
public:
GLTexture(): GLObject2<1>(glGenTextures, glDeleteTextures) {}
};
class GLRenderBuffer: public GLObject2<2>
{
public:
GLRenderBuffer(): GLObject2<2>(glGenRenderbuffers, glDeleteRenderbuffers) {}
};
Czy ktoś może sugerować bardziej eleganckie rozwiązanie?
IMHO, interfejsy API OpenGL prawdopodobnie nie są wystarczająco zunifikowane, aby tego rodzaju ogólne podejście było bardzo udane. Różne generacje funkcji wykorzystują różne podejścia do projektowania interfejsu API. – Trillian
@Trillian: Nonsens. Z 12 typów obiektów OpenGL [tylko 3 używają niestandardowych metadologii tworzenia/niszczenia] (http://www.opengl.org/wiki/OpenGL_Object#Non-standardowe_obiekty). To zły pomysł z innych powodów, ale nie z tego powodu. –
@NicolBolas: Z ciekawości: Co sprawia, że ten pomysł jest zły? I czy odpowiadasz jako część tej złej decyzji, czy poleciłbyś ją? – Skalli