//-------------------------------------------------------------- // constructor mgGL33Services::~mgGL33Services() { CHECK_THREAD(); // free all the textures const void* value; mgString key; int posn = m_textureImages.getStartPosition(); while (posn != -1) { m_textureImages.getNextAssoc(posn, key, value); mgGL33TextureImage* texture = (mgGL33TextureImage*) value; delete texture; } m_textureImages.removeAll(); // free all the texture arrays for (int i = 0; i < m_textureArrays.length(); i++) { mgGL33TextureArray* texture = (mgGL33TextureArray*) m_textureArrays[i]; delete texture; } m_textureArrays.removeAll(); // free all the texture arrays for (int i = 0; i < m_textureCubes.length(); i++) { mgGL33TextureCube* texture = (mgGL33TextureCube*) m_textureCubes[i]; delete texture; } m_textureCubes.removeAll(); }
//-------------------------------------------------------------- // draw from separate vertex and index buffers void mgGL33Services::draw( int primType, mgVertexBuffer* vertexes, mgIndexBuffer* indexes, int startIndex, int endIndex) { CHECK_THREAD(); if (m_updateShaderVars) setShaderStdUniforms(m_shader); mgGL33VertexBuffer* ourVertexes = (mgGL33VertexBuffer*) vertexes; mgGL33IndexBuffer* ourIndexes = (mgGL33IndexBuffer*) indexes; ourVertexes->loadDisplay(); ourIndexes->loadDisplay(); int indexType = ourIndexes->m_longIndexes ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; int indexSize = ourIndexes->m_longIndexes ? sizeof(unsigned int) : sizeof(unsigned short); glBindVertexArray(ourVertexes->m_array); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ourIndexes->m_buffer); int startOffset = startIndex*indexSize; glDrawElements(mgGL33primType(primType), endIndex-startIndex, indexType, (const GLvoid*) startOffset); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mgNullHandle); glBindBuffer(GL_ARRAY_BUFFER, mgNullHandle); glBindVertexArray(mgNullHandle); }
//----------------------------------------------------------------------------- // set shader uniform value to array of Point3 void mgGL33Services::setShaderUniform( const char* shaderName, // name of shader const char* varName, // variable name int count, // array size const mgPoint3* points) // point array { DWORD value; if (!m_shaders.lookup(shaderName, value)) throw new mgErrorMsg("glShader", "shaderName", "%s", (const char*) shaderName); CHECK_THREAD(); mgShaderHandle shader = (mgShaderHandle) value; GLint index = glGetUniformLocation(shader, (const GLchar*) varName); if (index == -1) return; // throw new mgException("setShaderUniform %s.%s not found", (const char*) shaderName, (const char*) varName); GLfloat* values = new GLfloat[count*3]; for (int i = 0; i < count; i++) { values[i*3] = (GLfloat) points[i].x; values[i*3+1] = (GLfloat) points[i].y; values[i*3+2] = (GLfloat) points[i].z; } glUniform3fv(index, count, values); delete values; }
//-------------------------------------------------------------- // restore device resources void mgGL33Services::reloadTextures() { CHECK_THREAD(); // restore textures from source file const void* value; mgString key; int posn = m_textureImages.getStartPosition(); while (posn != -1) { m_textureImages.getNextAssoc(posn, key, value); mgGL33TextureImage* texture = (mgGL33TextureImage*) value; reloadTextureImage(texture); } // reload texture arrays for (int i = 0; i < m_textureArrays.length(); i++) { mgGL33TextureArray* texture = (mgGL33TextureArray*) m_textureArrays[i]; reloadTextureArray(texture); } // reload texture cubes for (int i = 0; i < m_textureCubes.length(); i++) { mgGL33TextureCube* texture = (mgGL33TextureCube*) m_textureCubes[i]; reloadTextureCube(texture); } }
//-------------------------------------------------------------- // draw from separate vertex and index buffers void mgGL33Services::draw( int primType, mgVertexBuffer* vertexes, mgIndexBuffer* indexes) { CHECK_THREAD(); if (m_updateShaderVars) setShaderStdUniforms(m_shader); mgGL33VertexBuffer* ourVertexes = (mgGL33VertexBuffer*) vertexes; mgGL33IndexBuffer* ourIndexes = (mgGL33IndexBuffer*) indexes; ourVertexes->loadDisplay(); ourIndexes->loadDisplay(); int indexSize = ourIndexes->m_longIndexes ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; glBindVertexArray(ourVertexes->m_array); glBindBuffer(GL_ARRAY_BUFFER, ourVertexes->m_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ourIndexes->m_buffer); glDrawElements(mgGL33primType(primType), ourIndexes->m_count, indexSize, (const GLvoid*) 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mgNullHandle); glBindBuffer(GL_ARRAY_BUFFER, mgNullHandle); glBindVertexArray(mgNullHandle); }
//-------------------------------------------------------------- // release device resources void mgGL33Services::unloadTextures() { CHECK_THREAD(); // release texture data const void* value; mgString key; int posn = m_textureImages.getStartPosition(); while (posn != -1) { m_textureImages.getNextAssoc(posn, key, value); mgGL33TextureImage* texture = (mgGL33TextureImage*) value; if (texture->m_handle != mgNullHandle) { glDeleteTextures(1, &texture->m_handle); texture->m_handle = mgNullHandle; } } for (int i = 0; i < m_textureArrays.length(); i++) { mgGL33TextureArray* texture = (mgGL33TextureArray*) m_textureArrays[i]; glDeleteTextures(1, &texture->m_handle); texture->m_handle = mgNullHandle; } for (int i = 0; i < m_textureCubes.length(); i++) { mgGL33TextureCube* texture = (mgGL33TextureCube*) m_textureCubes[i]; glDeleteTextures(1, &texture->m_handle); texture->m_handle = mgNullHandle; } }
//-------------------------------------------------------------- // create texture to be updated from memory mgTextureImage* mgGL33Services::createTextureMemory( int width, int height, int format, BOOL mipmap) { CHECK_THREAD(); GLuint handle; glGenTextures(1, &handle); glBindTexture(GL_TEXTURE_2D, handle); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // turn off mipmapping if not requested if (!mipmap) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); GLint texFormat = (format == MG_MEMORY_FORMAT_RGBA) ? GL_RGBA : GL_BGRA; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, texFormat, GL_UNSIGNED_BYTE, NULL); mgGL33TextureImage* texture = new mgGL33TextureImage(); texture->m_width = width; texture->m_height = height; texture->m_format = format; texture->m_mipmap = mipmap; texture->m_handle = handle; return texture; }
//-------------------------------------------------------------- // reload texture image from file void mgGL33Services::reloadTextureImage( mgGL33TextureImage* texture) { CHECK_THREAD(); glGenTextures(1, &texture->m_handle); glBindTexture(GL_TEXTURE_2D, texture->m_handle); if (texture->m_filter == MG_TEXTURE_QUALITY) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mgGL33TextureWrap(texture->m_xWrap)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mgGL33TextureWrap(texture->m_yWrap)); int imgWidth, imgHeight; BYTE* data; mgLoadRGBAImage(texture->m_fileName, imgWidth, imgHeight, texture->m_transparent, data); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgWidth, imgHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); delete data; texture->m_width = imgWidth; texture->m_height = imgHeight; glGenerateMipmap(GL_TEXTURE_2D); }
//-------------------------------------------------------------- // end decals void mgGL33Services::decalEnd() { CHECK_THREAD(); // restore old state glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); }
//-------------------------------------------------------------- // copy buffer to display void mgGL33IndexBuffer::loadDisplay() { CHECK_THREAD(); if (m_buffer != mgNullHandle && !m_updateBuffer) return; // nothing to do if (m_data == NULL) throw new mgErrorMsg("glNullIndex", "", ""); if (m_buffer == mgNullHandle) glGenBuffers(1, &m_buffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); int indexSize = m_longIndexes ? sizeof(UINT32) : sizeof(UINT16); glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_count * indexSize, m_data, m_dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); if (!m_dynamic) { // gcc complains about delete of void* delete (char*) m_data; m_data = NULL; m_size = 0; // leave count, since caller may use it } m_updateBuffer = false; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mgNullHandle); }
/* start things running. */ int thread_queue_run(struct thread_queue *tq) { unsigned t; int rc; for (t = 0; t != tq->n_threads; ++t) { rc = pthread_create(&tq->threads[t], NULL, worker_func, &tq->input[t]); CHECK_THREAD(rc); } for (t = 0; t != tq->n_threads; ++t) { rc = pthread_join(tq->threads[t], NULL); CHECK_THREAD(rc); } return 0; }
//-------------------------------------------------------------- // set transparent void mgGL33Services::setTransparent( BOOL enable) { CHECK_THREAD(); if (enable) glEnable(GL_BLEND); else glDisable(GL_BLEND); }
//-------------------------------------------------------------- // set front face clockwise void mgGL33Services::setFrontCW( BOOL enable) { CHECK_THREAD(); if (enable) glFrontFace(GL_CW); else glFrontFace(GL_CCW); }
//-------------------------------------------------------------- // set culling void mgGL33Services::setCulling( BOOL enable) { CHECK_THREAD(); if (enable) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); }
//-------------------------------------------------------------- // set zenable void mgGL33Services::setZEnable( BOOL enable) { CHECK_THREAD(); if (enable) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); }
//-------------------------------------------------------------- // delete buffer from display void mgGL33IndexBuffer::unloadDisplay() { CHECK_THREAD(); if (m_buffer != mgNullHandle) { glDeleteBuffers(1, &m_buffer); m_buffer = mgNullHandle; } }
//-------------------------------------------------------------- // start drawing decals void mgGL33Services::decalStart() { CHECK_THREAD(); glDepthFunc(GL_LESS); glColorMask(true, true, true, true); // draw the decals masked by the stencil buffer glStencilFunc(GL_EQUAL, 1, 1); glDisable(GL_DEPTH_TEST); }
//-------------------------------------------------------------- // set the texture to use void mgGL33Services::setTexture( const mgTextureArray* textureArray, int unit) { CHECK_THREAD(); mgGL33TextureArray* ourTextureArray = (mgGL33TextureArray*) textureArray; glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D_ARRAY, ourTextureArray->m_handle); glActiveTexture(GL_TEXTURE0); }
//----------------------------------------------------------------------------- // delete shader void mgGL33Services::deleteShader( const char* shaderName) // name of shader { DWORD value; if (!m_shaders.lookup(shaderName, value)) throw new mgErrorMsg("glShader", "shaderName", "%s", (const char*) shaderName); CHECK_THREAD(); mgShaderHandle shader = (mgShaderHandle) value; glDeleteProgram(shader); }
//-------------------------------------------------------------- // set the texture to use void mgGL33Services::setTexture( const mgTextureCube* textureCube, int unit) { CHECK_THREAD(); mgGL33TextureCube* ourTextureCube = (mgGL33TextureCube*) textureCube; glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_CUBE_MAP, ourTextureCube->m_handle); glActiveTexture(GL_TEXTURE0); }
//-------------------------------------------------------------- // set the texture to use void mgGL33Services::setTexture( const mgTextureImage* texture, int unit) { CHECK_THREAD(); mgGL33TextureImage* ourTexture = (mgGL33TextureImage*) texture; glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, ourTexture->m_handle); glActiveTexture(GL_TEXTURE0); }
//-------------------------------------------------------------- // clear the view void mgGL33Services::clearView() { CHECK_THREAD(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFrontFace(GL_CW); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glDisable(GL_BLEND); }
//-------------------------------------------------------------- // set texture wrap mode in x and y void mgGL33TextureArray::setWrap( int xWrap, int yWrap) { CHECK_THREAD(); m_xWrap = xWrap; m_yWrap = yWrap; glBindTexture(GL_TEXTURE_2D_ARRAY, m_handle); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, mgGL33TextureWrap(m_xWrap)); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, mgGL33TextureWrap(m_yWrap)); }
//-------------------------------------------------------------- // set texture wrap mode in x and y void mgGL33TextureCube::setWrap( int xWrap, int yWrap) { CHECK_THREAD(); m_xWrap = xWrap; m_yWrap = yWrap; glBindTexture(GL_TEXTURE_CUBE_MAP, m_handle); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, mgGL33TextureWrap(m_xWrap)); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, mgGL33TextureWrap(m_yWrap)); }
//-------------------------------------------------------------- // draw a texture to the overlay void mgGL33Services::drawOverlayTexture( const mgTextureImage* texture, int x, int y, int width, int height) { CHECK_THREAD(); mgGL33TextureImage* ourTexture = (mgGL33TextureImage*) texture; mgPlatform->drawOverlayTexture(ourTexture->m_handle, x, y, width, height); m_updateShaderVars = true; }
//----------------------------------------------------------------------------- // set current shader void mgGL33Services::setShader( const char* shaderName) // name of shader { DWORD value; if (!m_shaders.lookup(shaderName, value)) throw new mgErrorMsg("glShader", "shaderName", "%s", (const char*) shaderName); CHECK_THREAD(); m_shader = (mgShaderHandle) value; glUseProgram(m_shader); m_updateShaderVars = true; }
//-------------------------------------------------------------- // draw the view void mgGL33Services::clearBuffer( int flags) { CHECK_THREAD(); GLbitfield mask = 0; if ((flags & MG_COLOR_BUFFER) != 0) mask |= GL_COLOR_BUFFER_BIT; if ((flags & MG_DEPTH_BUFFER) != 0) mask |= GL_DEPTH_BUFFER_BIT; glClear(mask); }
//-------------------------------------------------------------- // update memory texture void mgGL33TextureImage::updateMemory( int x, int y, int width, int height, const BYTE* data) { CHECK_THREAD(); glBindTexture(GL_TEXTURE_2D, m_handle); GLint texFormat = (m_format == MG_MEMORY_FORMAT_RGBA) ? GL_RGBA : GL_BGRA; glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, texFormat, GL_UNSIGNED_BYTE, data); if (m_mipmap) glGenerateMipmap(GL_TEXTURE_2D); }
//-------------------------------------------------------------- // start drawing decal background. draw=false just sets depth void mgGL33Services::decalBackground( BOOL draw) { CHECK_THREAD(); // set the stencil buffer based on depth test glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_ZERO, GL_REPLACE); glStencilOpSeparate(GL_BACK, GL_ZERO, GL_ZERO, GL_ZERO); // if we shouldn't draw the background, turn off write of color if (!draw) { glDepthFunc(GL_LEQUAL); glColorMask(false, false, false, false); } }
//----------------------------------------------------------------------------- // set shader uniform value to float void mgGL33Services::setShaderUniform( const char* shaderName, // name of shader const char* varName, // variable name float floatvalue) // value { DWORD value; if (!m_shaders.lookup(shaderName, value)) throw new mgErrorMsg("glShader", "shaderName", "%s", (const char*) shaderName); CHECK_THREAD(); mgShaderHandle shader = (mgShaderHandle) value; GLint index = glGetUniformLocation(shader, (const GLchar*) varName); if (index == -1) return; // throw new mgException("setShaderUniform %s.%s not found", (const char*) shaderName, (const char*) varName); glUniform1f(index, (GLfloat) floatvalue); }