void Gui_Render() { const text_shader_description *shader = renderer.shaderManager->getTextShader(); screenSize[0] = screen_info.w; screenSize[1] = screen_info.h; qglUseProgramObjectARB(shader->program); qglUniform1iARB(shader->sampler, 0); qglUniform2fvARB(shader->screenSize, 1, screenSize); qglUniform1fARB(shader->colorReplace, 0.0f); qglPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT); qglPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT | GL_CLIENT_VERTEX_ARRAY_BIT); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglPolygonMode(GL_FRONT, GL_FILL); qglFrontFace(GL_CCW); qglEnable(GL_BLEND); qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qglDisable(GL_ALPHA_TEST); if(World_GetPlayer() && main_inventory_manager) { Gui_DrawInventory(engine_frame_time); } Gui_DrawNotifier(engine_frame_time); qglUseProgramObjectARB(shader->program); qglDepthMask(GL_FALSE); qglPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); qglPixelStorei(GL_UNPACK_ALIGNMENT, 1); if(screen_info.crosshair != 0) { Gui_DrawCrosshair(); } Gui_DrawBars(); qglUniform1fARB(shader->colorReplace, 1.0f); GLText_RenderStrings(); Con_Draw(engine_frame_time); qglUniform1fARB(shader->colorReplace, 0.0f); qglDepthMask(GL_TRUE); qglPopClientAttrib(); qglPopAttrib(); }
void Gui_DrawLoadScreen(int value) { qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); qglPushAttrib(GL_ENABLE_BIT | GL_PIXEL_MODE_BIT | GL_COLOR_BUFFER_BIT); qglPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); qglPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); qglPixelStorei(GL_UNPACK_ALIGNMENT, 1); qglEnableClientState(GL_VERTEX_ARRAY); qglEnableClientState(GL_TEXTURE_COORD_ARRAY); qglEnableClientState(GL_COLOR_ARRAY); qglDisableClientState(GL_NORMAL_ARRAY); qglEnable(GL_BLEND); qglEnable(GL_TEXTURE_2D); qglDisable(GL_ALPHA_TEST); qglDepthMask(GL_FALSE); qglPolygonMode(GL_FRONT, GL_FILL); qglFrontFace(GL_CCW); const GLfloat color_w[4] = {1.0f, 1.0f, 1.0f, 1.0f}; const text_shader_description *shader = renderer.shaderManager->getTextShader(); screenSize[0] = screen_info.w; screenSize[1] = screen_info.h; qglUseProgramObjectARB(shader->program); qglUniform1iARB(shader->sampler, 0); qglUniform2fvARB(shader->screenSize, 1, screenSize); Gui_DrawRect(0.0, 0.0, screen_info.w, screen_info.h, color_w, color_w, color_w, color_w, BM_OPAQUE, load_screen_tex); if(value >= 0) { Bar[BAR_LOADING].Show(value); } qglDepthMask(GL_TRUE); qglPopClientAttrib(); qglPopAttrib(); Engine_GLSwapWindow(); }
static int setupScreenKeyboardButton( int buttonID, Uint8 * charBuf ) { // TODO: softstretch with antialiasing int w, h, format; GLTexture_t * data = NULL; int texture_w, texture_h; if( buttonID < 1 ) data = &arrowImages; else data = &(buttonImages[buttonID-1]); memcpy(&w, charBuf, sizeof(int)); memcpy(&h, charBuf + sizeof(int), sizeof(int)); memcpy(&format, charBuf + 2*sizeof(int), sizeof(int)); w = ntohl(w); h = ntohl(h); format = ntohl(format); texture_w = power_of_2(w); texture_h = power_of_2(h); data->w = texture_w; data->h = texture_h; LOGI("data w:%d, h:%d\n", w, h); qglEnable(GL_TEXTURE_2D); qglGenTextures(1, &data->id); qglBindTexture(GL_TEXTURE_2D, data->id); LOGI("On-screen keyboard generated OpenGL texture ID %x", data->id); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_w, texture_h, 0, GL_RGBA, format ? GL_UNSIGNED_SHORT_4_4_4_4 : GL_UNSIGNED_SHORT_5_5_5_1, NULL); qglPixelStorei(GL_UNPACK_ALIGNMENT, 1); qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, format ? GL_UNSIGNED_SHORT_4_4_4_4 : GL_UNSIGNED_SHORT_5_5_5_1, charBuf + 3*sizeof(int) ); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglDisable(GL_TEXTURE_2D); return 3*sizeof(int) + w * h * 2; }
/* ======================== idImage::SubImageUpload ======================== */ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void * pic, int pixelPitch ) const { assert( x >= 0 && y >= 0 && mipLevel >= 0 && width >= 0 && height >= 0 && mipLevel < opts.numLevels ); int compressedSize = 0; if ( IsCompressed() ) { assert( !(x&3) && !(y&3) ); // compressed size may be larger than the dimensions due to padding to quads int quadW = ( width + 3 ) & ~3; int quadH = ( height + 3 ) & ~3; compressedSize = quadW * quadH * BitsForFormat( opts.format ) / 8; int padW = ( opts.width + 3 ) & ~3; int padH = ( opts.height + 3 ) & ~3; (void)padH; (void)padW; assert( x + width <= padW && y + height <= padH ); // upload the non-aligned value, OpenGL understands that there // will be padding if ( x + width > opts.width ) { width = opts.width - x; } if ( y + height > opts.height ) { height = opts.height - x; } } else { assert( x + width <= opts.width && y + height <= opts.height ); } int target; int uploadTarget; if ( opts.textureType == TT_2D ) { target = GL_TEXTURE_2D; uploadTarget = GL_TEXTURE_2D; } else if ( opts.textureType == TT_CUBIC ) { target = GL_TEXTURE_CUBE_MAP_EXT; uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT + z; } else { assert( !"invalid opts.textureType" ); target = GL_TEXTURE_2D; uploadTarget = GL_TEXTURE_2D; } qglBindTexture( target, texnum ); if ( pixelPitch != 0 ) { qglPixelStorei( GL_UNPACK_ROW_LENGTH, pixelPitch ); } if ( opts.format == FMT_RGB565 ) { glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_TRUE ); } #ifdef DEBUG GL_CheckErrors(); #endif if ( IsCompressed() ) { qglCompressedTexSubImage2DARB( uploadTarget, mipLevel, x, y, width, height, internalFormat, compressedSize, pic ); } else { // make sure the pixel store alignment is correct so that lower mips get created // properly for odd shaped textures - this fixes the mip mapping issues with // fonts int unpackAlignment = width * BitsForFormat( (textureFormat_t)opts.format ) / 8; if ( ( unpackAlignment & 3 ) == 0 ) { qglPixelStorei( GL_UNPACK_ALIGNMENT, 4 ); } else { qglPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); } qglTexSubImage2D( uploadTarget, mipLevel, x, y, width, height, dataFormat, dataType, pic ); } #ifdef DEBUG GL_CheckErrors(); #endif if ( opts.format == FMT_RGB565 ) { glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE ); } if ( pixelPitch != 0 ) { qglPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); } }
// Renders the input text at the current location with the current color. // The X position of the current location is used to place the left edge of the text image, // where the text image bounds are defined as the logical extents of the line of text. // The Y position of the current location is used to place the bottom of the text image. // You should offset the Y position by the amount returned by gtk_glwidget_font_descent() // if you want to place the baseline of the text image at the current Y position. // Note: A problem with this function is that if the lower left corner of the text falls // just a hair outside of the viewport (meaning the current raster position is invalid), // then no text will be rendered. The solution to this is a very hacky one. You can search // Google for "glDrawPixels clipping". void gtk_glwidget_print_string( const char *s ){ // The idea for this code initially came from the font-pangoft2.c example that comes with GtkGLExt. PangoLayout *layout; PangoRectangle log_rect; FT_Bitmap bitmap; unsigned char *begin_bitmap_buffer; GLfloat color[4]; GLint previous_unpack_alignment; GLboolean previous_blend_enabled; GLint previous_blend_func_src; GLint previous_blend_func_dst; GLfloat previous_red_bias; GLfloat previous_green_bias; GLfloat previous_blue_bias; GLfloat previous_alpha_scale; if ( !_debug_font_created ) { Error( "Programming error: gtk_glwidget_print_string() called but font does not exist; " "you should have called gtk_glwidget_create_font() first" ); } layout = pango_layout_new( ft2_context ); pango_layout_set_width( layout, -1 ); // -1 no wrapping. All text on one line. pango_layout_set_text( layout, s, -1 ); // -1 null-terminated string. pango_layout_get_extents( layout, NULL, &log_rect ); if ( log_rect.width > 0 && log_rect.height > 0 ) { bitmap.rows = font_ascent + font_descent; bitmap.width = PANGO_PIXELS_CEIL( log_rect.width ); bitmap.pitch = -bitmap.width; // Rendering it "upside down" for OpenGL. begin_bitmap_buffer = (unsigned char *) g_malloc( bitmap.rows * bitmap.width ); memset( begin_bitmap_buffer, 0, bitmap.rows * bitmap.width ); bitmap.buffer = begin_bitmap_buffer + ( bitmap.rows - 1 ) * bitmap.width; // See pitch above. bitmap.num_grays = 0xff; bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; pango_ft2_render_layout_subpixel( &bitmap, layout, -log_rect.x, y_offset_bitmap_render_pango_units ); qglGetFloatv( GL_CURRENT_COLOR, color ); // Save state. I didn't see any OpenGL push/pop operations for these. // Question: Is saving/restoring this state necessary? Being safe. qglGetIntegerv( GL_UNPACK_ALIGNMENT, &previous_unpack_alignment ); previous_blend_enabled = qglIsEnabled( GL_BLEND ); qglGetIntegerv( GL_BLEND_SRC, &previous_blend_func_src ); qglGetIntegerv( GL_BLEND_DST, &previous_blend_func_dst ); qglGetFloatv( GL_RED_BIAS, &previous_red_bias ); qglGetFloatv( GL_GREEN_BIAS, &previous_green_bias ); qglGetFloatv( GL_BLUE_BIAS, &previous_blue_bias ); qglGetFloatv( GL_ALPHA_SCALE, &previous_alpha_scale ); qglPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); qglEnable( GL_BLEND ); qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); qglPixelTransferf( GL_RED_BIAS, color[0] ); qglPixelTransferf( GL_GREEN_BIAS, color[1] ); qglPixelTransferf( GL_BLUE_BIAS, color[2] ); qglPixelTransferf( GL_ALPHA_SCALE, color[3] ); qglDrawPixels( bitmap.width, bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, begin_bitmap_buffer ); g_free( begin_bitmap_buffer ); // Restore state in reverse order of how we set it. qglPixelTransferf( GL_ALPHA_SCALE, previous_alpha_scale ); qglPixelTransferf( GL_BLUE_BIAS, previous_blue_bias ); qglPixelTransferf( GL_GREEN_BIAS, previous_green_bias ); qglPixelTransferf( GL_RED_BIAS, previous_red_bias ); qglBlendFunc( previous_blend_func_src, previous_blend_func_dst ); if ( !previous_blend_enabled ) { qglDisable( GL_BLEND ); } qglPixelStorei( GL_UNPACK_ALIGNMENT, previous_unpack_alignment ); } g_object_unref( G_OBJECT( layout ) ); }