Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » Steam Client interference / OpenGL

This thread is locked; no one can reply to it. rss feed Print
Steam Client interference / OpenGL
thebignic
Member #14,419
July 2012

Allegro 5.2.5.1

I've been recommending to players to disable the Steam Overlay as it seems to be the source of an intermittent exception (specifically with al_load_bitmap()) with some OpenGL drivers (usually laptops, shared memory?)

but recently the Steam Client seems to interfere with my game even if the overlay is disabled for the game in specific, AND in the Steam Client global settings!

Bashing my head off the desk...

Game loads and runs fine if the Steam Client just isn't running, but since we're trying to use Steam for multiplayer, we need the client to run.

Has anyone experienced anything similar?

Chris Katko
Member #1,881
January 2002
avatar

Hello bignic, love your music.

Do you have the type of exception? Have you been able to replicate it on any of your home machines or a VM, or only from users? Or do you have reported/saved the exception data / call-stack from users? Does the exception only fire off in certain, specific al_load_bitmaps calls, or any of them?

I've definitely seen crashes when the Steam overlay activates. In one scenario, one screenshot, it'll crash--especially if it's a large screen (4K) into a slow hard drive. But not specifically with Allegro.

Q. Why is the Steam overlay crashing my app?
A. The Steam overlay is used in thousands of games and as such it has been very thoroughly tested and is rarely the cause of a crash. However, because of the way it injects itself into the game, it does often expose memory leaks or memory corruption in the usage of your rendering API that may not have impacted game play.

That's interesting.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

thebignic
Member #14,419
July 2012

I can replicate it fairly often with an HP EliteBook with Intel HD 3000 onboard gpu.

It usually crashes in 1-3 exact same spots so I'm not ruling out a memory leak in my own code.

Null reference - when I got PDB loaded, al_really_load_png() throws "lock was nullptr"

(I probably shouldn't have started two threads here, but the other thread was specifically about loading the PDBs which seems to be fine now, just not that helpful after all.)

Chris Katko
Member #1,881
January 2002
avatar

https://github.com/liballeg/allegro5/blob/50460b7fc48d6bafff2db309fe3cd5def80e3863/addons/image/png.c

#SelectExpand
1 2/* really_load_png: 3 * Worker routine, used by load_png and load_memory_png. 4 */ 5static ALLEGRO_BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr, 6 int flags) 7{ 8 ALLEGRO_BITMAP *bmp; 9 png_uint_32 width, height, rowbytes, real_rowbytes; 10 int bit_depth, color_type, interlace_type; 11 double image_gamma, screen_gamma; 12 int intent; 13 int bpp; 14 int number_passes, pass; 15 int num_trans = 0; 16 PalEntry pal[256]; 17 png_bytep trans; 18 ALLEGRO_LOCKED_REGION *lock; 19 unsigned char *buf; 20 unsigned char *dest; 21 bool premul = !(flags & ALLEGRO_NO_PREMULTIPLIED_ALPHA); 22 bool index_only; 23 24 ALLEGRO_ASSERT(png_ptr && info_ptr); 25 26 /* The call to png_read_info() gives us all of the information from the 27 * PNG file before the first IDAT (image data chunk). 28 */ 29 png_read_info(png_ptr, info_ptr); 30 31 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 32 &color_type, &interlace_type, NULL, NULL); 33 34 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single 35 * byte into separate bytes (useful for paletted and grayscale images). 36 */ 37 png_set_packing(png_ptr); 38 39 /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ 40 if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) 41 png_set_expand(png_ptr); 42 43 /* Adds a full alpha channel if there is transparency information 44 * in a tRNS chunk. 45 */ 46 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { 47 if (!(color_type & PNG_COLOR_MASK_PALETTE)) 48 png_set_tRNS_to_alpha(png_ptr); 49 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); 50 } 51 52 /* Convert 16-bits per colour component to 8-bits per colour component. */ 53 if (bit_depth == 16) 54 png_set_strip_16(png_ptr); 55 56 /* Convert grayscale to RGB triplets */ 57 if ((color_type == PNG_COLOR_TYPE_GRAY) || 58 (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) 59 png_set_gray_to_rgb(png_ptr); 60 61 /* Optionally, tell libpng to handle the gamma correction for us. */ 62 screen_gamma = get_gamma(); 63 if (screen_gamma != 0.0) { 64 if (png_get_sRGB(png_ptr, info_ptr, &intent)) 65 png_set_gamma(png_ptr, screen_gamma, 0.45455); 66 else { 67 if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) 68 png_set_gamma(png_ptr, screen_gamma, image_gamma); 69 else 70 png_set_gamma(png_ptr, screen_gamma, 0.45455); 71 } 72 } 73 74 /* Turn on interlace handling. */ 75 number_passes = png_set_interlace_handling(png_ptr); 76 77 /* Call to gamma correct and add the background to the palette 78 * and update info structure. 79 */ 80 png_read_update_info(png_ptr, info_ptr); 81 82 /* Palettes. */ 83 if (color_type & PNG_COLOR_MASK_PALETTE) { 84 int num_palette, i; 85 png_colorp palette; 86 87 if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) { 88 /* We don't actually dither, we just copy the palette. */ 89 for (i = 0; ((i < num_palette) && (i < 256)); i++) { 90 pal[i].r = palette[i].red; 91 pal[i].g = palette[i].green; 92 pal[i].b = palette[i].blue; 93 } 94 95 for (; i < 256; i++) 96 pal[i].r = pal[i].g = pal[i].b = 0; 97 } 98 } 99 100 rowbytes = png_get_rowbytes(png_ptr, info_ptr); 101 102 /* Allocate the memory to hold the image using the fields of info_ptr. */ 103 bpp = rowbytes * 8 / width; 104 105 /* Allegro cannot handle less than 8 bpp. */ 106 if (bpp < 8) 107 bpp = 8; 108 109 110 if ((bpp == 24) || (bpp == 32)) { 111#ifdef ALLEGRO_BIG_ENDIAN 112 png_set_bgr(png_ptr); 113 png_set_swap_alpha(png_ptr); 114#endif 115 } 116 117 bmp = al_create_bitmap(width, height); 118 if (!bmp) { 119 ALLEGRO_ERROR("al_create_bitmap failed while loading PNG.\n"); 120 return NULL; 121 } 122 123 // TODO: can this be different from rowbytes? 124 real_rowbytes = ((bpp + 7) / 8) * width; 125 if (interlace_type == PNG_INTERLACE_ADAM7) 126 buf = al_malloc(real_rowbytes * height); 127 else 128 buf = al_malloc(real_rowbytes); 129 130 if (bpp == 8 && (color_type & PNG_COLOR_MASK_PALETTE) && 131 (flags & ALLEGRO_KEEP_INDEX)) 132 { 133 lock = al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8, 134 ALLEGRO_LOCK_WRITEONLY); 135 index_only = true; 136 } 137 else { 138 lock = al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE, 139 ALLEGRO_LOCK_WRITEONLY); 140 index_only = false; 141 } 142 143 /* Read the image, one line at a time (easier to debug!) */ 144 for (pass = 0; pass < number_passes; pass++) { 145 png_uint_32 y; 146 unsigned int i; 147 unsigned char *ptr; 148 dest = lock->data; 149 150 for (y = 0; y < height; y++) { 151 unsigned char *dest_row_start = dest; 152 /* For interlaced pictures, the row needs to be initialized with 153 * the contents of the previous pass. 154 */ 155 if (interlace_type == PNG_INTERLACE_ADAM7) 156 ptr = buf + y * real_rowbytes; 157 else 158 ptr = buf; 159 png_read_row(png_ptr, NULL, ptr); 160 161 switch (bpp) { 162 case 8: 163 if (index_only) { 164 for (i = 0; i < width; i++) { 165 *(dest++) = *(ptr++); 166 } 167 } 168 else if (color_type & PNG_COLOR_MASK_PALETTE) { 169 for (i = 0; i < width; i++) { 170 int pix = ptr[0]; 171 ptr++; 172 dest[0] = pal[pix].r; 173 dest[1] = pal[pix].g; 174 dest[2] = pal[pix].b; 175 if (pix < num_trans) { 176 int a = trans[pix]; 177 dest[3] = a; 178 if (premul) { 179 dest[0] = dest[0] * a / 255; 180 dest[1] = dest[1] * a / 255; 181 dest[2] = dest[2] * a / 255; 182 } 183 } else { 184 dest[3] = 255; 185 } 186 dest += 4; 187 } 188 } 189 else { 190 for (i = 0; i < width; i++) { 191 int pix = ptr[0]; 192 ptr++; 193 *(dest++) = pix; 194 *(dest++) = pix; 195 *(dest++) = pix; 196 *(dest++) = 255; 197 } 198 } 199 break; 200 201 case 24: 202 for (i = 0; i < width; i++) { 203 uint32_t pix = _AL_READ3BYTES(ptr); 204 ptr += 3; 205 *(dest++) = pix & 0xff; 206 *(dest++) = (pix >> 8) & 0xff; 207 *(dest++) = (pix >> 16) & 0xff; 208 *(dest++) = 255; 209 } 210 break; 211 212 case 32: 213 for (i = 0; i < width; i++) { 214 uint32_t pix = *(uint32_t*)ptr; 215 int r = pix & 0xff; 216 int g = (pix >> 8) & 0xff; 217 int b = (pix >> 16) & 0xff; 218 int a = (pix >> 24) & 0xff; 219 ptr += 4; 220 221 if (premul) { 222 r = r * a / 255; 223 g = g * a / 255; 224 b = b * a / 255; 225 } 226 227 *(dest++) = r; 228 *(dest++) = g; 229 *(dest++) = b; 230 *(dest++) = a; 231 } 232 break; 233 234 default: 235 ALLEGRO_ASSERT(bpp == 8 || bpp == 24 || bpp == 32); 236 break; 237 } 238 dest = dest_row_start + lock->pitch; 239 } 240 } 241 242 al_unlock_bitmap(bmp); 243 244 al_free(buf); 245 246 /* Read rest of file, and get additional chunks in info_ptr. */ 247 png_read_end(png_ptr, info_ptr); 248 249 return bmp; 250}

- I wonder if steam overlay does some kind of weird file locking / freezes threads as it loads the overlay.

Also, bignic, I've not used it but the Valgrind people recommend "Deleaker" for Windows equivalent of finding memory leaks. It might be helpful. The fact you can semi-consistently trigger it will definitely help.

I wonder if this can be triggered on any of the included Allegro 5 example programs by forcing Steam to attach the overlay to it. (IIRC, you can start anything with steam overlay attached if you add the shortcut to Steam manually under Steam->Games->"Add Non-Steam Game to my Library".)

Also, there are ALLEGRO_ERROR lines in here. So if compiled in debug mode (also release?) Allegro should dump to an error file if it catches it.

I'd do more searching but apparently Github decided I'm a Russian bot. Great job github. Apparently scrolling through pages of hits for "ALLEGRO_ERROR" means you're a bot. (And no, I'm not on a VPN either.)

{"name":"B1NDVaI.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/7\/072821ef61fdf27881457f8e42193f91.png","w":454,"h":334,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/7\/072821ef61fdf27881457f8e42193f91"}B1NDVaI.png

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

thebignic
Member #14,419
July 2012

Thank you kindly for the suggestions - Some new paths to investigate, for sure.

I'll have to work up some courage to press on!

Go to: