1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "ShaderStage.h"
22
23namespace love
24{
25namespace graphics
26{
27namespace opengl
28{
29
30ShaderStage::ShaderStage(love::graphics::Graphics *gfx, StageType stage, const std::string &source, bool gles, const std::string &cachekey)
31 : love::graphics::ShaderStage(gfx, stage, source, gles, cachekey)
32 , glShader(0)
33{
34 loadVolatile();
35}
36
37ShaderStage::~ShaderStage()
38{
39 unloadVolatile();
40}
41
42bool ShaderStage::loadVolatile()
43{
44 if (glShader != 0)
45 return true;
46
47 StageType stage = getStageType();
48 const char *typestr = "unknown";
49 getConstant(stage, typestr);
50
51 GLenum glstage = 0;
52 if (stage == STAGE_VERTEX)
53 glstage = GL_VERTEX_SHADER;
54 else if (stage == STAGE_PIXEL)
55 glstage = GL_FRAGMENT_SHADER;
56 else
57 throw love::Exception("%s shader stage is not handled in OpenGL backend code.", typestr);
58
59 glShader = glCreateShader(glstage);
60
61 if (glShader == 0)
62 throw love::Exception("Cannot create OpenGL %s shader object.", typestr);
63
64 const std::string &sourcestring = getSource();
65 const char *src = sourcestring.c_str();
66 GLint srclen = (GLint) sourcestring.length();
67
68 glShaderSource(glShader, 1, (const GLchar **)&src, &srclen);
69 glCompileShader(glShader);
70
71 GLint infologlen;
72 glGetShaderiv(glShader, GL_INFO_LOG_LENGTH, &infologlen);
73
74 if (infologlen > 0)
75 {
76 GLchar *infolog = new GLchar[infologlen];
77 glGetShaderInfoLog(glShader, infologlen, nullptr, infolog);
78
79 warnings = infolog;
80 delete[] infolog;
81 }
82
83 GLint status = GL_FALSE;
84 glGetShaderiv(glShader, GL_COMPILE_STATUS, &status);
85
86 if (status == GL_FALSE)
87 {
88 glDeleteShader(glShader);
89 throw love::Exception("Cannot compile %s shader code:\n%s", typestr, warnings.c_str());
90 }
91
92 return true;
93}
94
95void ShaderStage::unloadVolatile()
96{
97 if (glShader != 0)
98 glDeleteShader(glShader);
99
100 glShader = 0;
101}
102
103} // opengl
104} // graphics
105} // love
106