diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 02a32957a2b940ac15490c0e83fb57658da24c5e..2008beb0007f098b1a2b2b9432bf942e00f40d68 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -1486,6 +1486,114 @@ static void AllocTextureBuffer(GLMipmap_t *pTexInfo)
 	}
 }
 
+#define PADDING_CHECK(offset, alphaCheck) { from = to + (offset); if ((alphaCheck)) from = NULL; else goto foundFrom; }
+
+static void PadRGBABitmap(RGBA_t *tex, UINT16 w, UINT16 h)
+{
+	INT32 i;
+	boolean notLeft, notRight, notTop, notBottom;
+	RGBA_t *to = tex - 1, *from;
+
+	for (i = 0; i < w * h; i++)
+	{
+		to++;
+		if (to->rgba != 0)
+			continue;
+		from = NULL;
+
+		notLeft = i % w != 0;
+		notRight = i % w != w - 1;
+		notTop = i / w != 0;
+		notBottom = i / w != h - 1;
+
+		if (notRight) PADDING_CHECK(1, from->s.alpha == 0) // Check +X
+		if (notBottom) PADDING_CHECK(w, from->s.alpha == 0) // Check +Y
+		if (notLeft) PADDING_CHECK(-1, from->s.alpha == 0) // Check -X
+		if (notTop) PADDING_CHECK(-w, from->s.alpha == 0) // Check -Y
+		if (notRight && notBottom) PADDING_CHECK(1 + w, from->s.alpha == 0) // Check +X+Y
+		if (notLeft && notBottom) PADDING_CHECK(-1 + w, from->s.alpha == 0) // Check -X+Y
+		if (notLeft && notTop) PADDING_CHECK(-1 - w, from->s.alpha == 0) // Check -X-Y
+		if (notRight && notTop) PADDING_CHECK(1 - w, from->s.alpha == 0) // Check +X-Y
+
+foundFrom:
+		if (from != NULL)
+		{
+			*to = *from;
+			to->s.alpha = 0;
+		}
+	}
+}
+
+#undef PADDING_CHECK
+
+static void GenerateMipmaps(INT32 w, INT32 h, RGBA_t *tex, INT32 maxLOD)
+{
+	if (tex == NULL)
+	{
+		GL_MSG_Warning("GenerateMipmaps: attempted to generate mipmaps without texture data");
+		return;
+	}
+
+	RGBA_t samplePoint[4];
+	boolean padTexture;
+	INT32 pointsSampled = 0;
+	INT32 m, j, i, p;
+	UINT16 sumR, sumG, sumB, sumA;
+
+	for (m = 0; m < maxLOD; m++)
+	{
+		if (w <= 1 || h <= 1)
+			return;
+
+		padTexture = false;
+
+		for (j = 0; j < h / 2; j++)
+		{
+			for (i = 0; i < w / 2; i++)
+			{
+				samplePoint[0] = tex[w*j*2 + i*2];
+				samplePoint[1] = tex[w*j*2 + i*2+1];
+				samplePoint[2] = tex[w*(j*2+1) + i*2];
+				samplePoint[3] = tex[w*(j*2+1) + i*2+1];
+
+				pointsSampled = sumR = sumG = sumB = sumA = 0;
+
+				for (p = 0; p < 4; p++)
+				{
+					if (samplePoint[p].s.alpha == 0)
+						continue;
+					sumR += samplePoint[p].s.red;
+					sumG += samplePoint[p].s.green;
+					sumB += samplePoint[p].s.blue;
+					sumA += samplePoint[p].s.alpha;
+					pointsSampled++;
+				}
+
+				if (pointsSampled > 0)
+				{
+					tex[(w/2)*j+i].s.red   = sumR / pointsSampled;
+					tex[(w/2)*j+i].s.green = sumG / pointsSampled;
+					tex[(w/2)*j+i].s.blue  = sumB / pointsSampled;
+					tex[(w/2)*j+i].s.alpha = sumA / pointsSampled;
+				}
+				else
+				{
+					tex[(w/2)*j+i].rgba = 0;
+					padTexture = true;
+				}
+			}
+		}
+
+		w /= 2;
+		h /= 2;
+
+		if (padTexture)
+			PadRGBABitmap(tex, w, h);
+
+		pglTexSubImage2D(GL_TEXTURE_2D, m + 1, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex);
+	}
+}
+
 // -----------------+
 // UpdateTexture    : Updates texture data.
 // -----------------+
@@ -1494,6 +1602,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
 	// Upload a texture
 	GLuint num = pTexInfo->downloaded;
 	boolean update = true;
+	const boolean applyPadding = mag_filter == GL_LINEAR || min_filter == GL_LINEAR;
 
 	INT32 w = pTexInfo->width, h = pTexInfo->height;
 	INT32 i, j;
@@ -1548,11 +1657,26 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
 				}
 			}
 		}
+
+		if (applyPadding)
+			PadRGBABitmap(tex, w, h);
 	}
 	else if (pTexInfo->format == GL_TEXFMT_RGBA)
 	{
 		// Directly upload the texture data without any kind of conversion.
 		ptex = pImgData;
+
+		// However, it does need to be copied to a buffer for generating mipmaps and padding
+		if (MipMap || applyPadding)
+		{
+			AllocTextureBuffer(pTexInfo);
+			tex = textureBuffer;
+			memcpy(tex, ptex, w * h * 4);
+			ptex = tex;
+
+			if (applyPadding)
+				PadRGBABitmap(tex, w, h);
+		}
 	}
 	else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88)
 	{
@@ -1616,9 +1740,14 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
 			pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
 			pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
 			if (pTexInfo->flags & TF_TRANSPARENT)
+			{
 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
+			}
 			else
+			{
 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
+				GenerateMipmaps(w, h, tex, 4);
+			}
 			//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
 		}
 		else
@@ -1638,9 +1767,14 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
 			pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
 			pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
 			if (pTexInfo->flags & TF_TRANSPARENT)
+			{
 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
+			}
 			else
+			{
 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
+				GenerateMipmaps(w, h, tex, 4);
+			}
 			//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
 		}
 		else
@@ -1660,9 +1794,14 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo)
 			// Control the mipmap level of detail
 			pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail
 			if (pTexInfo->flags & TF_TRANSPARENT)
+			{
 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
+			}
 			else
+			{
 				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
+				GenerateMipmaps(w, h, tex, 5);
+			}
 		}
 		else
 		{