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