]> git.tdb.fi Git - libs/gl.git/blob - source/backends/opengl/texture_backend.cpp
e8288045f4625fd5766e5b1048809717660ce204
[libs/gl.git] / source / backends / opengl / texture_backend.cpp
1 #include <msp/gl/extensions/arb_direct_state_access.h>
2 #include <msp/gl/extensions/arb_texture_swizzle.h>
3 #include <msp/gl/extensions/ext_framebuffer_object.h>
4 #include <msp/gl/extensions/khr_debug.h>
5 #include "gl.h"
6 #include "error.h"
7 #include "texture.h"
8 #include "texture_backend.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GL {
14
15 int OpenGLTexture::swizzle_orders[] =
16 {
17         GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA,
18         GL_RED, GL_RED, GL_RED, GL_ONE,
19         GL_RED, GL_RED, GL_RED, GL_GREEN,
20         GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA
21 };
22
23 OpenGLTexture *OpenGLTexture::scratch_binding = 0;
24
25 OpenGLTexture::OpenGLTexture(unsigned t):
26         id(0),
27         target(t)
28 {
29         static bool alignment_init = false;
30         if(!alignment_init)
31         {
32                 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
33                 alignment_init = true;
34         }
35 }
36
37 OpenGLTexture::~OpenGLTexture()
38 {
39         if(this==scratch_binding)
40                 unbind_scratch();
41         if(id)
42                 glDeleteTextures(1, &id);
43 }
44
45 void OpenGLTexture::create()
46 {
47         if(id)
48                 throw invalid_operation("OpenGLTexture::create");
49         if(ARB_direct_state_access)
50                 glCreateTextures(target, 1, &id);
51         else
52                 glGenTextures(1, &id);
53
54 #ifdef DEBUG
55         if(!debug_name.empty() && KHR_debug)
56                 glObjectLabel(GL_TEXTURE, id, debug_name.size(), debug_name.c_str());
57 #endif
58 }
59
60 void OpenGLTexture::require_swizzle()
61 {
62         static Require _req(ARB_texture_swizzle);
63 }
64
65 void OpenGLTexture::apply_swizzle()
66 {
67         Texture::FormatSwizzle swizzle = static_cast<const Texture *>(this)->swizzle;
68         if(swizzle==Texture::NO_SWIZZLE)
69                 return;
70
71         if(get_backend_api()==OPENGL_ES)
72         {
73                 set_parameter_i(GL_TEXTURE_SWIZZLE_R, swizzle_orders[swizzle*4]);
74                 set_parameter_i(GL_TEXTURE_SWIZZLE_G, swizzle_orders[swizzle*4+1]);
75                 set_parameter_i(GL_TEXTURE_SWIZZLE_B, swizzle_orders[swizzle*4+2]);
76                 set_parameter_i(GL_TEXTURE_SWIZZLE_A, swizzle_orders[swizzle*4+3]);
77         }
78         else
79         {
80                 if(ARB_direct_state_access)
81                         glTextureParameteriv(id, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
82                 else
83                         glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, swizzle_orders+swizzle*4);
84         }
85 }
86
87 void OpenGLTexture::set_parameter_i(unsigned param, int value) const
88 {
89         if(ARB_direct_state_access)
90                 glTextureParameteri(id, param, value);
91         else
92                 glTexParameteri(target, param, value);
93 }
94
95 void OpenGLTexture::generate_mipmap()
96 {
97         // glGenerateMipmap is defined here
98         static Require _req(EXT_framebuffer_object);
99
100         if(ARB_direct_state_access)
101                 glGenerateTextureMipmap(id);
102         else
103         {
104                 bind_scratch();
105                 glGenerateMipmap(target);
106         }
107 }
108
109 void OpenGLTexture::set_debug_name(const string &name)
110 {
111 #ifdef DEBUG
112         debug_name = name;
113         if(id && KHR_debug)
114                 glObjectLabel(GL_TEXTURE, id, name.size(), name.c_str());
115 #else
116         (void)name;
117 #endif
118 }
119
120 void OpenGLTexture::bind_scratch()
121 {
122         if(!scratch_binding)
123                 glActiveTexture(GL_TEXTURE0);
124         if(scratch_binding!=this)
125         {
126                 if(scratch_binding && scratch_binding->target!=target)
127                         glBindTexture(scratch_binding->target, 0);
128                 glBindTexture(target, id);
129                 scratch_binding = this;
130         }
131 }
132
133 void OpenGLTexture::unbind_scratch()
134 {
135         if(scratch_binding)
136         {
137                 glBindTexture(scratch_binding->target, 0);
138                 scratch_binding = 0;
139         }
140 }
141
142 } // namespace GL
143 } // namespace Msp