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.
17static const bool gPrintSKSL = false;
18static const bool gPrintGLSL = false;
19
20void 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
31std::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 SkDebugf("SKSL:\n");
54 GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(sksl));
55 }
56 if (gPrintGLSL) {
57 SkDebugf("GLSL:\n");
58 GrShaderUtils::PrintLineByLine(GrShaderUtils::PrettyPrint(*glsl));
59 }
60 }
61
62 return program;
63}
64
65GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
66 GrGLuint programId,
67 GrGLenum type,
68 const SkSL::String& glsl,
69 GrGpu::Stats* stats,
70 GrContextOptions::ShaderErrorHandler* errorHandler) {
71 const GrGLInterface* gli = glCtx.glInterface();
72
73 // Specify GLSL source to the driver.
74 GrGLuint shaderId;
75 GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
76 if (0 == shaderId) {
77 return 0;
78 }
79 const GrGLchar* source = glsl.c_str();
80 GrGLint sourceLength = glsl.size();
81 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &source, &sourceLength));
82
83 stats->incShaderCompilations();
84 GR_GL_CALL(gli, CompileShader(shaderId));
85
86 bool checkCompiled = !glCtx.caps()->skipErrorChecks();
87
88 if (checkCompiled) {
89 GrGLint compiled = GR_GL_INIT_ZERO;
90 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
91
92 if (!compiled) {
93 GrGLint infoLen = GR_GL_INIT_ZERO;
94 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
95 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
96 if (infoLen > 0) {
97 // retrieve length even though we don't need it to workaround bug in Chromium cmd
98 // buffer param validation.
99 GrGLsizei length = GR_GL_INIT_ZERO;
100 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
101 }
102 errorHandler->compileError(glsl.c_str(), infoLen > 0 ? (const char*)log.get() : "");
103 GR_GL_CALL(gli, DeleteShader(shaderId));
104 return 0;
105 }
106 }
107
108 // Attach the shader, but defer deletion until after we have linked the program.
109 // This works around a bug in the Android emulator's GLES2 wrapper which
110 // will immediately delete the shader object and free its memory even though it's
111 // attached to a program, which then causes glLinkProgram to fail.
112 GR_GL_CALL(gli, AttachShader(programId, shaderId));
113 return shaderId;
114}
115