public void Add(MGLTexture texture) { if (_values.Count > Maximum) { // Evict last entry MGLTexture dead = _values.Tail; _values.Remove(_values.TailEntry); Gl.glDeleteTextures(1, ref dead.TextureID); } _values.InsertAtHead(texture); }
private void SetTextures() { MGLTextureInfo info = _ctx.Textures[0]; if (info.Address == 0) { if (_currentTextureId != 0) { Gl.glBindTexture(Gl.GL_TEXTURE_2D, 0); } _currentTextureId = 0; return; } // Check valid bool valid = !((info.Address == 0x0) || (info.LineWidth == 0x0) || (info.Width == 0) || (info.Height == 0)); // TODO: from framebuffer? - make sure this check is still valid! valid = valid && !((info.Address == 0x0400000) && (info.LineWidth == 0x4) && (info.Width == 0x2) && (info.Height == 0x2)); // Check cache uint checksum; MGLTexture texture = _ctx.TextureCache.Find(info, out checksum); // If found in cache, set and return if (texture != null) { if (_currentTextureId != texture.TextureID) { Gl.glBindTexture(Gl.GL_TEXTURE_2D, texture.TextureID); _currentTextureId = texture.TextureID; // HACK: required to get textures to work right - does something after the binding so that things show up Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, _ctx.TextureMinFilter); //Gl.glTexParameteri( Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_NEAREST ); // TODO: set all _defaultProgram.IsDirty = true; } return; } // Not found - create texture = MGLTexture.LoadTexture(this, _ctx, info, checksum); _currentTextureId = texture.TextureID; _ctx.TextureCache.Add(texture); // TODO: set all _defaultProgram.IsDirty = true; }
public MGLTexture Find(MGLTextureInfo info, out uint checksum) { checksum = 0; LinkedListEntry <MGLTexture> e = _values.HeadEntry; while (e != null) { if (e.Value.Address == info.Address) { // Check to make sure it's right bool match = (e.Value.Width == info.Width) && (e.Value.Height == info.Height) && (e.Value.LineWidth == info.LineWidth) && (e.Value.PixelStorage == info.PixelStorage) && (((( int )e.Value.PixelStorage & 0x4) == 0x4) ? (e.Value.ClutChecksum == _ctx.Clut.Checksum) : true); if (match == true) { // Cookie check //uint cookie = *((uint*) if (match == true) { byte *textureAddress = _driver.MemorySystem.Translate(info.Address); checksum = MGLTexture.CalculateChecksum(textureAddress, info.Width, info.Height, info.PixelStorage); match = (checksum == e.Value.Checksum); } } if (match == true) { // Match - move to head _values.MoveToHead(e); return(e.Value); } else { // Mismatch - free Gl.glDeleteTextures(1, ref e.Value.TextureID); _driver.InvalidateCurrentTexture(); _values.Remove(e); return(null); } } e = e.Next; } return(null); }
public static MGLTexture LoadTexture(MGLDriver driver, MGLContext ctx, MGLTextureInfo info, uint checksum) { uint width = info.Width; uint lineWidth = info.LineWidth; uint height = info.Height; MGLTexture texture = new MGLTexture(); texture.PixelStorage = info.PixelStorage; texture.Address = info.Address; texture.LineWidth = lineWidth; texture.Width = width; texture.Height = height; texture.Checksum = checksum; texture.ClutPointer = ctx.Clut.Pointer; texture.ClutChecksum = ctx.Clut.Checksum; int textureId; Gl.glGenTextures(1, out textureId); Gl.glBindTexture(Gl.GL_TEXTURE_2D, textureId); texture.TextureID = textureId; byte * address = driver.MemorySystem.Translate(info.Address); TextureFormat format = TextureFormats[( int )info.PixelStorage]; uint size = lineWidth * height * format.Size; fixed(byte *unswizzleBuffer = &_unswizzleBuffer[0]) fixed(byte *decodeBuffer = &_decodeBuffer[0]) { bool needRowLength = false; byte *buffer = address; if (ctx.TexturesSwizzled == true) { buffer = Unswizzle(format, buffer, unswizzleBuffer, lineWidth, height); } switch (texture.PixelStorage) { case TexturePixelStorage.BGR5650: texture.Checksum = ColorOperations.DecodeBGR5650(buffer, decodeBuffer, lineWidth * height); buffer = decodeBuffer; break; case TexturePixelStorage.ABGR5551: texture.Checksum = ColorOperations.DecodeABGR5551(buffer, decodeBuffer, lineWidth * height); buffer = decodeBuffer; break; case TexturePixelStorage.ABGR4444: texture.Checksum = ColorOperations.DecodeABGR4444(buffer, decodeBuffer, lineWidth * height); buffer = decodeBuffer; break; case TexturePixelStorage.ABGR8888: // Pass through needRowLength = true; break; case TexturePixelStorage.Indexed4: ctx.Clut.Decode4(buffer, decodeBuffer, width, height, lineWidth); buffer = decodeBuffer; break; case TexturePixelStorage.Indexed8: ctx.Clut.Decode8(buffer, decodeBuffer, width, height, lineWidth); buffer = decodeBuffer; break; case TexturePixelStorage.Indexed16: ctx.Clut.Decode16(buffer, decodeBuffer, width, height, lineWidth); buffer = decodeBuffer; break; case TexturePixelStorage.Indexed32: ctx.Clut.Decode32(buffer, decodeBuffer, width, height, lineWidth); buffer = decodeBuffer; break; case TexturePixelStorage.DXT1: case TexturePixelStorage.DXT3: case TexturePixelStorage.DXT5: // Not yet implemented Debug.Assert(false); break; } // TODO: eliminate these //Gl.glPixelStorei( Gl.GL_UNPACK_ALIGNMENT, 4 ); //if( needRowLength == true ) // Gl.glPixelStorei( Gl.GL_UNPACK_ROW_LENGTH, ( int )lineWidth ); //else // Gl.glPixelStorei( Gl.GL_UNPACK_ROW_LENGTH, ( int )width ); Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA8, ( int )width, ( int )height, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, ( IntPtr )buffer); // Set cookie //texture.CookieOriginal = *( ( uint* )address ); //texture.Cookie = ( uint )textureId; //*( ( uint* )address ) = ( uint )textureId; // Calculate checksum if needed if (texture.Checksum == 0) { texture.Checksum = MGLTexture.CalculateChecksum(address, width, height, texture.PixelStorage); } } return(texture); }