1 /*
2  *  BSD 3-Clause License
3  *  
4  *  Copyright (c) 2016, Mango-Engine Team
5  *  All rights reserved.
6  *  
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions are met:
9  *  
10  *  * Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *  
13  *  * Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *  
17  *  * Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from
19  *    this software without specific prior written permission.
20  *  
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 module mango_engine.graphics.opengl.gl_texture;
33 
34 import mango_engine.graphics.texture;
35 import mango_engine.graphics.opengl.gl_backend;
36 
37 import derelict.opengl3.gl3;
38 import derelict.freeimage.freeimage;
39 
40 class GLTexture : Texture {
41     private GLuint textureId;
42 
43     /// Use Texture.textureFactory()
44     this(in string filename, in bool useAlpha = true) @safe {
45         super(filename, useAlpha);
46 
47         gl_check();
48 
49         load();
50     }
51 
52     /// Binds the texture for OpenGL use
53     void bind() @system nothrow {
54         glBindTexture(GL_TEXTURE_2D, textureId);
55     }
56 
57     private void load() @trusted {
58         FIBITMAP* bitmap = loadBitMap(filename);
59         if(!bitmap) {
60             throw new Exception("Failed to load texture \"" ~ filename ~ "\": null");
61         }
62 
63         _width = FreeImage_GetWidth(bitmap);
64         _height = FreeImage_GetHeight(bitmap);
65 
66         glGenTextures(1, &textureId);
67         bind();
68 
69         setOptions();
70 
71         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, useAlpha ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, FreeImage_GetBits(bitmap));
72         glGenerateMipmap(GL_TEXTURE_2D);
73 
74         FreeImage_Unload(bitmap);
75     }
76 
77     private void setOptions() @system {
78         // TODO: adjustable
79         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
80         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
81 
82         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
83         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
84     }
85 
86     private FIBITMAP* loadBitMap(in string filename) @system {
87         import blocksound.util : toCString;
88 
89         FIBITMAP* bitmap;
90         FREE_IMAGE_FORMAT format;
91 
92         format = FreeImage_GetFileType(toCString(filename), 0);
93         if(format == FIF_UNKNOWN) {
94             throw new Exception("Invalid format!");
95         }
96         if(!FreeImage_FIFSupportsReading(format)) {
97             throw new Exception("FreeImage does not support reading file \"" ~ filename ~ "\"");
98         }
99         
100         bitmap = FreeImage_Load(format, toCString(filename));
101         return bitmap;
102     }
103 
104     override void cleanup() @system nothrow {
105         glDeleteTextures(1, &textureId);
106     }
107 }