• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/core/SkAutoMalloc.h"
9 #include "src/gpu/GrShaderUtils.h"
10 #include "src/gpu/gl/GrGLGpu.h"
11 #include "src/gpu/gl/builders/GrGLShaderStringBuilder.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLGLSLCodeGenerator.h"
14 #include "src/sksl/ir/SkSLProgram.h"
15 
16 // Print the source code for all shaders generated.
17 static const bool gPrintSKSL = false;
18 static const bool gPrintGLSL = false;
19 
print_shader_banner(SkSL::Program::Kind programKind)20 void print_shader_banner(SkSL::Program::Kind programKind) {
21     const char* typeName = "Unknown";
22     switch (programKind) {
23         case SkSL::Program::kVertex_Kind:   typeName = "Vertex";   break;
24         case SkSL::Program::kGeometry_Kind: typeName = "Geometry"; break;
25         case SkSL::Program::kFragment_Kind: typeName = "Fragment"; break;
26         default: break;
27     }
28     SkDebugf("---- %s shader ----------------------------------------------------\n", typeName);
29 }
30 
GrSkSLtoGLSL(const GrGLContext & context,SkSL::Program::Kind programKind,const SkSL::String & sksl,const SkSL::Program::Settings & settings,SkSL::String * glsl,GrContextOptions::ShaderErrorHandler * errorHandler)31 std::unique_ptr<SkSL::Program> GrSkSLtoGLSL(const GrGLContext& context,
32                                             SkSL::Program::Kind programKind,
33                                             const SkSL::String& sksl,
34                                             const SkSL::Program::Settings& settings,
35                                             SkSL::String* glsl,
36                                             GrContextOptions::ShaderErrorHandler* errorHandler) {
37     SkSL::Compiler* compiler = context.compiler();
38     std::unique_ptr<SkSL::Program> program;
39 #ifdef SK_DEBUG
40     SkSL::String src = GrShaderUtils::PrettyPrint(sksl);
41 #else
42     const SkSL::String& src = sksl;
43 #endif
44     program = compiler->convertProgram(programKind, src, settings);
45     if (!program || !compiler->toGLSL(*program, glsl)) {
46         errorHandler->compileError(src.c_str(), compiler->errorText().c_str());
47         return nullptr;
48     }
49 
50     if (gPrintSKSL || gPrintGLSL) {
51         print_shader_banner(programKind);
52         if (gPrintSKSL) {
53             GrShaderUtils::PrintLineByLine("SKSL:", GrShaderUtils::PrettyPrint(sksl));
54         }
55         if (gPrintGLSL) {
56             GrShaderUtils::PrintLineByLine("GLSL:", GrShaderUtils::PrettyPrint(*glsl));
57         }
58     }
59 
60     return program;
61 }
62 
GrGLCompileAndAttachShader(const GrGLContext & glCtx,GrGLuint programId,GrGLenum type,const SkSL::String & glsl,GrGpu::Stats * stats,GrContextOptions::ShaderErrorHandler * errorHandler)63 GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
64                                     GrGLuint programId,
65                                     GrGLenum type,
66                                     const SkSL::String& glsl,
67                                     GrGpu::Stats* stats,
68                                     GrContextOptions::ShaderErrorHandler* errorHandler) {
69     const GrGLInterface* gli = glCtx.interface();
70 
71     // Specify GLSL source to the driver.
72     GrGLuint shaderId;
73     GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
74     if (0 == shaderId) {
75         return 0;
76     }
77     const GrGLchar* source = glsl.c_str();
78     GrGLint sourceLength = glsl.size();
79     GR_GL_CALL(gli, ShaderSource(shaderId, 1, &source, &sourceLength));
80 
81     stats->incShaderCompilations();
82     GR_GL_CALL(gli, CompileShader(shaderId));
83 
84     // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds.
85     bool checkCompiled = kChromium_GrGLDriver != glCtx.driver();
86 #ifdef SK_DEBUG
87     checkCompiled = true;
88 #endif
89     if (checkCompiled) {
90         GrGLint compiled = GR_GL_INIT_ZERO;
91         GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
92 
93         if (!compiled) {
94             GrGLint infoLen = GR_GL_INIT_ZERO;
95             GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
96             SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
97             if (infoLen > 0) {
98                 // retrieve length even though we don't need it to workaround bug in Chromium cmd
99                 // buffer param validation.
100                 GrGLsizei length = GR_GL_INIT_ZERO;
101                 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
102             }
103             errorHandler->compileError(glsl.c_str(), infoLen > 0 ? (const char*)log.get() : "");
104             GR_GL_CALL(gli, DeleteShader(shaderId));
105             return 0;
106         }
107     }
108 
109     // Attach the shader, but defer deletion until after we have linked the program.
110     // This works around a bug in the Android emulator's GLES2 wrapper which
111     // will immediately delete the shader object and free its memory even though it's
112     // attached to a program, which then causes glLinkProgram to fail.
113     GR_GL_CALL(gli, AttachShader(programId, shaderId));
114     return shaderId;
115 }
116