#include "ASW_Graphics_OGL_W32.h" extern PFNGLMULTIDRAWARRAYSEXTPROC glMultiDrawArrays; extern PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements; extern PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements; extern PFNGLACTIVETEXTUREPROC glActiveTexture; extern PFNGLACTIVESTENCILFACEEXTPROC glActiveStencilFaceEXT; extern PFNGLBUFFERDATAARBPROC glBufferDataARB; extern PFNGLBINDBUFFERARBPROC glBindBufferARB; extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB; extern PFNGLGENBUFFERSARBPROC glGenBuffersARB; extern PFNGLMAPBUFFERARBPROC glMapBufferARB; extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB; extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB; bool InitGLS() { glActiveTexture = (PFNGLACTIVETEXTUREPROC)(wglGetProcAddress("glActiveTexture")); glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSEXTPROC)(wglGetProcAddress("glMultiDrawArrays")); glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)(wglGetProcAddress("glDrawRangeElements")); glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)(wglGetProcAddress("glMultiDrawElements")); glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)(wglGetProcAddress("glActiveStencilFaceEXT")); return ( glActiveTexture != NULL && glMultiDrawArrays != NULL && glDrawRangeElements != NULL && glMultiDrawElements != NULL && glActiveStencilFaceEXT != NULL ); } bool InitGLX() { glBufferDataARB = (PFNGLBUFFERDATAARBPROC)(wglGetProcAddress("glBufferDataARB")); glBindBufferARB = (PFNGLBINDBUFFERARBPROC)(wglGetProcAddress("glBindBufferARB")); glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)(wglGetProcAddress("glDeleteBuffersARB")); glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)(wglGetProcAddress("glGenBuffersARB")); glMapBufferARB = (PFNGLMAPBUFFERARBPROC)(wglGetProcAddress("glMapBufferARB")); glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)(wglGetProcAddress("glUnmapBufferARB")); glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)(wglGetProcAddress("glBufferSubDataARB")); glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)(wglGetProcAddress("glGetBufferSubDataARB")); return ( glBufferDataARB != NULL && glBindBufferARB != NULL && glDeleteBuffersARB != NULL && glGenBuffersARB != NULL && glMapBufferARB != NULL && glUnmapBufferARB != NULL && glBufferSubDataARB != NULL && glGetBufferSubDataARB != NULL ); } /////////////////////////////////////////////////////////////////// // OpenGLW32 /////////////////////////////////////////////////////////////////// OpenGLW32:: OpenGLW32(WindowW32 & p_clsWindow, const ASW::GraphicsApi::Settings & p_stuSettings) : m_ptrWindow(&p_clsWindow) { typedef bool (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int); PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT"); if ( wglSwapIntervalEXT ) CALL_WIN32(wglSwapIntervalEXT(( p_stuSettings.m_blnVsync ) ? 1 : 0), ==, TRUE); } void OpenGLW32:: DrawEnd() { CALL_WIN32(SwapBuffers(m_ptrWindow->GetContext()), ==, TRUE); } bool OpenGLW32:: Load(ASW::Font & p_stuFont) { int intWeight[] = { FW_DONTCARE, FW_THIN, FW_EXTRALIGHT, FW_LIGHT, FW_NORMAL, FW_MEDIUM, FW_SEMIBOLD, FW_BOLD, FW_EXTRABOLD, FW_HEAVY, }; DWORD dwdQuality[] = { DEFAULT_QUALITY, DRAFT_QUALITY, ANTIALIASED_QUALITY, }; // // Create the font object // HFONT hndFont = CreateFont(p_stuFont.m_intSize, // Height 0, // Width 0, // Escapement 0, // Orientation intWeight[p_stuFont.m_uchrWeight], // Weight ( p_stuFont.m_blnItalic ) ? TRUE : FALSE, // Italic ( p_stuFont.m_blnUnderlined ) ? TRUE : FALSE, // Underlined ( p_stuFont.m_blnStruckout ) ? TRUE : FALSE, // Strikeout ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, dwdQuality[p_stuFont.m_uchrQuality], FF_DONTCARE | DEFAULT_PITCH, p_stuFont.m_ptrFace); if ( hndFont == NULL ) return false; // // Make the new font object the current font // HDC hndDc = m_ptrWindow->GetContext(); HFONT hndCurrentFont = (HFONT)(SelectObject(hndDc, hndFont)); if ( hndCurrentFont == NULL ) { DeleteObject(hndFont); return false; } // // Generate bitmaps for the font // unsigned int uintBase = glGenLists(ASW_FONT_AMOUNT); if ( uintBase == 0 ) { SelectObject(hndDc, hndCurrentFont); DeleteObject(hndFont); return false; } else if ( wglUseFontBitmaps(hndDc, ASW_FONT_FIRST_CHARACTER, (ASW_FONT_AMOUNT), uintBase) == 0 ) { glDeleteLists(uintBase, ASW_FONT_AMOUNT); SelectObject(hndDc, hndCurrentFont); DeleteObject(hndFont); return false; } p_stuFont.m_ptrData[0] = (void *)(uintBase); p_stuFont.m_ptrData[1] = (void *)(hndFont); p_stuFont.m_blnLoaded = true; return true; } void OpenGLW32:: PrivateDestroy() { m_ptrWindow = NULL; } ASW::Point2f OpenGLW32:: Size(const ASW::Font & p_stuFont, const char * p_ptrString) { ASW_ASSERT(p_stuFont.m_blnLoaded, "Font is not loaded"); SIZE stuSize; HDC hndContext = m_ptrWindow->GetContext(); HFONT hndCurrentFont = (HFONT)(SelectObject(hndContext, (HFONT)(p_stuFont.m_ptrData[1]))); BOOL blnResult = GetTextExtentPoint32(hndContext, p_ptrString, (int)(strlen(p_ptrString)), &stuSize); SelectObject(hndContext, hndCurrentFont); ASW_ASSERT_WIN32(blnResult == TRUE); return ASW::Point2f((float)(stuSize.cx), (float)(stuSize.cy)); } void OpenGLW32:: Unload(ASW::Font & p_stuFont) { ASW_ASSERT(p_stuFont.m_blnLoaded, "Font is not loaded"); if ( (int)(p_stuFont.m_ptrData[0]) != 0 ) { glDeleteLists((unsigned int)(p_stuFont.m_ptrData[0]), ASW_FONT_AMOUNT); p_stuFont.m_ptrData[0] = (void *)(0); } if ( (int)(p_stuFont.m_ptrData[1]) != 0 ) { DeleteObject((HFONT)(p_stuFont.m_ptrData[1])); p_stuFont.m_ptrData[1] = (void *)(0); } p_stuFont.m_blnLoaded = false; } /////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////// OpenGLSW32:: OpenGLSW32(WindowW32 & p_clsWindow, const ASW::GraphicsApi::Settings & p_stuSettings) : OpenGLW32(p_clsWindow, p_stuSettings) { if ( InitGLS() == false ) throw ASW::Exception(__FILE__, __LINE__, __FUNCTION__, "One or more OpenGL procedures could not be found"); } OpenGLXW32:: OpenGLXW32(WindowW32 & p_clsWindow, const ASW::GraphicsApi::Settings & p_stuSettings) : OpenGLW32(p_clsWindow, p_stuSettings) { if ( InitGLS() == false || InitGLX() == false ) throw ASW::Exception(__FILE__, __LINE__, __FUNCTION__, "One or more OpenGL procedures could not be found"); } /////////////////////////////////////////////////////////////////// // OpenGLSW32lite (stripped-down version of OpenGL) /////////////////////////////////////////////////////////////////// OpenGLSW32lite:: OpenGLSW32lite(WindowW32 & p_clsWindow, const ASW::GraphicsApi::Settings & p_stuSettings) : OpenGLW32(p_clsWindow, p_stuSettings) {} void OpenGLSW32lite:: Bind(const ASW::Texture * p_ptrTexture, const unsigned int p_uintStage) { ASW_ASSERT(p_ptrTexture == NULL || p_ptrTexture->m_blnLoaded, "Cannot bind an unloaded texture"); ASW_ASSERT(p_uintStage == 0, "Multi-texturing not supported"); if ( p_ptrTexture != NULL ) { GLenum enmAddressMode[] = {GL_REPEAT, GL_CLAMP}; GLenum enmTargets[] = {0, GL_TEXTURE_1D, GL_TEXTURE_2D}; OGL_RUN(glMatrixMode(GL_TEXTURE)); OGL_RUN(glLoadMatrixf(p_ptrTexture->m_stuMatrix)); OGL_RUN(glBindTexture(enmTargets[p_ptrTexture->m_uchrDimensions], (unsigned int)(p_ptrTexture->m_ptrObject))); OGL_RUN(glTexParameteri(enmTargets[p_ptrTexture->m_uchrDimensions], GL_TEXTURE_WRAP_S, enmAddressMode[p_ptrTexture->m_enmAddressMode[0]])); OGL_RUN(glTexParameteri(enmTargets[p_ptrTexture->m_uchrDimensions], GL_TEXTURE_WRAP_T, enmAddressMode[p_ptrTexture->m_enmAddressMode[1]])); } else OGL_RUN(glBindTexture(GL_TEXTURE_2D, 0)); } void OpenGLSW32lite:: Draw(const ASW::Type::Primitive p_enmType, const ASW::BufferIndex::Index & p_clsIndex) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL && m_ptrActiveBufferIndex != NULL, "No vertex and/or index buffers bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_LINES || ((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_TRIANGLES || ((p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]) % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); OGL_RUN(glDrawElements(OpenGLS::m_enmPrimitiveTypes[p_enmType - 1], (GLsizei)(p_clsIndex.m_stuIndices[1] - p_clsIndex.m_stuIndices[0]), OpenGLS::m_enmDataTypes[m_ptrActiveBufferIndex->m_enmDataType], ((const char *)(m_ptrActiveBufferIndex->m_ptrData)) + (p_clsIndex.m_stuIndices[0] * m_ptrActiveBufferIndex->m_uchrElementSize))); } void OpenGLSW32lite:: DrawIndices(const ASW::Type::Primitive p_enmType, const ASW::CompositeIndex ** p_ptrIndices, const unsigned int p_uintAmount) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL && m_ptrActiveBufferIndex != NULL, "OpenGLS::Draw"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); for (unsigned int i=0; im_stuIndices[1] - ptrIndex->m_stuIndices[0]) % 2) == 0, "Incorrect number of vertices for PRIMITIVE_LINES"); ASW_ASSERT(p_enmType != ASW::Type::PRIMITIVE_TRIANGLES || ((ptrIndex->m_stuIndices[1] - ptrIndex->m_stuIndices[0]) % 3) == 0, "Incorrect number of vertices for PRIMITIVE_TRIANGLES"); OGL_RUN(glDrawElements(OpenGLS::m_enmPrimitiveTypes[p_enmType - 1], (GLsizei)(ptrIndex->m_stuIndices[1] - ptrIndex->m_stuIndices[0]), OpenGLS::m_enmDataTypes[m_ptrActiveBufferIndex->m_enmDataType], ((const char *)(m_ptrActiveBufferIndex->m_ptrData)) + (ptrIndex->m_stuIndices[0] * m_ptrActiveBufferIndex->m_uchrElementSize))); } } void OpenGLSW32lite:: DrawVertices(const ASW::Type::Primitive p_enmType, const ASW::CompositeIndex ** p_ptrIndices, const unsigned int p_uintAmount) { ASW_ASSERT(m_ptrActiveBufferVertex != NULL, "No vertex buffer bound"); ASW_ASSERT((int)(p_enmType) > (int)(ASW::Type::PRIMITIVE_UNKNOWN) && (int)(p_enmType) <= (int)(ASW::Type::PRIMITIVE_COUNT), "Invalid primitive type"); for (unsigned int i=0; im_stuIndices[0]), (GLsizei)(ptrIndex->m_stuIndices[1] - ptrIndex->m_stuIndices[0]))); } } void OpenGLSW32lite:: SetStencilTest(const ASW::GraphicsApi::Test p_enmTest, const int p_intReference, const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT(p_blnFront, "Two-sided stencil testing unsupported"); ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); OGL_RUN(glStencilFunc(OpenGLS::m_enmTests[p_enmTest - 1], (GLint)(p_intReference), (GLuint)(p_uintMask))); } void OpenGLSW32lite:: SetStencilWriteMask(const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT(p_blnFront, "Two-sided stencil testing unsupported"); OGL_RUN(glStencilMask((GLuint)(p_uintMask))); } void OpenGLSW32lite:: SetStencilOp(const ASW::GraphicsApi::StencilOp p_enmTestFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthPass, const bool p_blnFront) { ASW_ASSERT(p_blnFront, "Two-sided stencil testing unsupported"); ASW_ASSERT((int)(p_enmTestFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthPass) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthPass) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); OGL_RUN(glStencilOp(OpenGLS::m_enmStencilOps[p_enmTestFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthPass - 1])); } void OpenGLSW32lite:: SetStencilParams(const unsigned int p_uintWriteMask, const ASW::GraphicsApi::Test p_enmTest, const ASW::GraphicsApi::StencilOp p_enmTestFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthFail, const ASW::GraphicsApi::StencilOp p_enmTestPassDepthPass, const int p_intReference, const unsigned int p_uintMask, const bool p_blnFront) { ASW_ASSERT(p_blnFront, "Two-sided stencil testing unsupported"); ASW_ASSERT((int)(p_enmTest) > (int)(ASW::GraphicsApi::TEST_UNKNOWN) && (int)(p_enmTest) <= (int)(ASW::GraphicsApi::TEST_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthFail) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthFail) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); ASW_ASSERT((int)(p_enmTestPassDepthPass) > (int)(ASW::GraphicsApi::STENCILOP_UNKNOWN) && (int)(p_enmTestPassDepthPass) <= (int)(ASW::GraphicsApi::STENCILOP_COUNT), "Invalid parameter"); OGL_RUN(glStencilMask((GLuint)(p_uintWriteMask))); OGL_RUN(glStencilOp(OpenGLS::m_enmStencilOps[p_enmTestFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthFail - 1], OpenGLS::m_enmStencilOps[p_enmTestPassDepthPass - 1])); OGL_RUN(glStencilFunc(OpenGLS::m_enmTests[p_enmTest - 1], (GLint)(p_intReference), (GLuint)(p_uintMask))); }