1 module ecs_utils.gfx.texture;
2 
3 import bindbc.sdl;
4 
5 import bubel.ecs.std;
6 
7 import ecs_utils.math.vector;
8 
9 version(WebAssembly)import glad.gl.gles2;
10 else version(Android)import glad.gl.gles2;
11 else import glad.gl.gl;
12 
13 extern(C):
14 
15 struct Texture
16 {
17 
18     void create()
19     {
20         data = Mallocator.make!Data;
21     }
22 
23     bool load(const char[] path)
24     {
25         char[] cpath = (cast(char*)alloca(path.length+1))[0..path.length+1];
26         cpath[0..$-1] = path[0..$];
27         cpath[$-1] = 0;
28 
29         return __load(this, cpath);
30     }
31 
32     /*static bool __load_sdl(ref Texture this_, const char[] path)
33     {
34         import ecs_utils.gfx.renderer;
35         SDL_Surface* surf = IMG_Load(path.ptr);
36         if(!surf)return false;
37 
38         this_.data.size = ivec2(surf.w,surf.h);
39 
40         this_.data.texture = SDL_CreateTextureFromSurface(Renderer.main_sdl_renderer,surf);
41         if(!this_.data.texture)return false;
42         //this_.data.texture = surf;
43 
44         return true;
45     }*/
46 
47     static bool __load_gl(ref Texture this_, const char[] path)
48     {
49         SDL_Surface* surf = IMG_Load(path.ptr);
50         if(!surf)return false;
51 
52         with(this_)
53         {
54             data.size = ivec2(surf.w,surf.h);
55             data.bpp = surf.format.BytesPerPixel;
56             data.data = Mallocator.makeArray!ubyte(surf.w*surf.h*surf.format.BytesPerPixel);
57             data.data[0..$] = (cast(ubyte*)surf.pixels)[0..data.data.length];
58             data.size = ivec2(surf.w, surf.h);
59 
60             SDL_FreeSurface(surf);
61 
62             glGenTextures(1, &data.gl_handle);
63             glActiveTexture(GL_TEXTURE0);
64             glBindTexture(GL_TEXTURE_2D,data.gl_handle);
65 
66             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
67             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
68             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
69             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
70 
71             if(data.bpp == 3)glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,data.size.x,data.size.y,0,GL_RGB,GL_UNSIGNED_BYTE,data.data.ptr);
72             else if(data.bpp == 4)glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,data.size.x,data.size.y,0,GL_RGBA,GL_UNSIGNED_BYTE,data.data.ptr);
73             else return false;
74         }
75 
76 
77         return true;
78     }
79 
80     void bind()
81     {
82         glActiveTexture(GL_TEXTURE0);
83         glBindTexture(GL_TEXTURE_2D, data.gl_handle);
84     }
85 
86     void destroy() @nogc nothrow
87     {
88         if(data)
89         {
90             glDeleteTextures(1, &data.gl_handle);
91             if(data.data)Mallocator.dispose(data.data);
92             Mallocator.dispose(data);
93             data = null;
94         }
95     }
96 
97     __gshared bool function(ref Texture this_, const char[] path) __load;
98 
99     struct Data
100     {
101         ubyte[] data;
102 
103         ivec2 size; 
104         uint bpp;
105 
106         union
107         {
108             SDL_Texture* texture;
109             uint gl_handle;
110         }
111     }
112 
113     static void __loadBackend()
114     {
115         __load = &__load_gl;
116         /*switch(backend)
117         {
118             case Backend.opengl:__load = &__load_gl;break;
119             case Backend.sdl:__load = &__load_sdl;break;
120             default:goto case(Backend.opengl);
121         }*/
122     }
123     
124     Data* data;
125 }