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 #include "src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.h"
8
9 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
10 #include "include/gpu/ganesh/gl/GrGLInterface.h"
11 #include "include/private/base/SkTo.h"
12 #include "src/base/SkAutoMalloc.h"
13 #include "src/core/SkTraceEvent.h"
14 #include "src/gpu/ganesh/gl/GrGLDefines.h"
15 #include "src/gpu/ganesh/gl/GrGLGpu.h"
16 #include "src/gpu/ganesh/gl/GrGLUtil.h"
17 #include "src/sksl/SkSLString.h"
18
19 #include <cstdint>
20
GrGLCompileAndAttachShader(const GrGLContext & glCtx,GrGLuint programId,GrGLenum type,const std::string & glsl,bool shaderWasCached,GrThreadSafePipelineBuilder::Stats * stats,GrContextOptions::ShaderErrorHandler * errorHandler)21 GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
22 GrGLuint programId,
23 GrGLenum type,
24 const std::string& glsl,
25 bool shaderWasCached,
26 GrThreadSafePipelineBuilder::Stats* stats,
27 GrContextOptions::ShaderErrorHandler* errorHandler) {
28 TRACE_EVENT0_ALWAYS("skia.shaders", "driver_compile_shader");
29 const GrGLInterface* gli = glCtx.glInterface();
30
31 // Specify GLSL source to the driver.
32 GrGLuint shaderId;
33 GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
34 if (0 == shaderId) {
35 return 0;
36 }
37 const GrGLchar* source = glsl.c_str();
38 GrGLint sourceLength = SkToInt(glsl.size());
39 GR_GL_CALL(gli, ShaderSource(shaderId, 1, &source, &sourceLength));
40
41 stats->incShaderCompilations();
42 GR_GL_CALL(gli, CompileShader(shaderId));
43
44 {
45 ATRACE_ANDROID_FRAMEWORK("checkCompiled");
46 GrGLint compiled = GR_GL_INIT_ZERO;
47 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
48
49 if (!compiled) {
50 GrGLint infoLen = GR_GL_INIT_ZERO;
51 GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
52 SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
53 if (infoLen > 0) {
54 // retrieve length even though we don't need it to workaround bug in Chromium cmd
55 // buffer param validation.
56 GrGLsizei length = GR_GL_INIT_ZERO;
57 GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
58 }
59 errorHandler->compileError(
60 glsl.c_str(), infoLen > 0 ? (const char*)log.get() : "", shaderWasCached);
61 GR_GL_CALL(gli, DeleteShader(shaderId));
62 return 0;
63 }
64 }
65
66 // Attach the shader, but defer deletion until after we have linked the program.
67 // This works around a bug in the Android emulator's GLES2 wrapper which
68 // will immediately delete the shader object and free its memory even though it's
69 // attached to a program, which then causes glLinkProgram to fail.
70 GR_GL_CALL(gli, AttachShader(programId, shaderId));
71 return shaderId;
72 }
73
GrGLCheckLinkStatus(const GrGLGpu * gpu,GrGLuint programID,bool shaderWasCached,GrContextOptions::ShaderErrorHandler * errorHandler,const std::string * sksl[kGrShaderTypeCount],const std::string glsl[kGrShaderTypeCount])74 bool GrGLCheckLinkStatus(const GrGLGpu* gpu,
75 GrGLuint programID,
76 bool shaderWasCached,
77 GrContextOptions::ShaderErrorHandler* errorHandler,
78 const std::string* sksl[kGrShaderTypeCount],
79 const std::string glsl[kGrShaderTypeCount]) {
80 const GrGLInterface* gli = gpu->glInterface();
81
82 GrGLint linked = GR_GL_INIT_ZERO;
83 GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
84 if (!linked && errorHandler) {
85 std::string allShaders;
86 #if defined(SK_DEBUG)
87 #define SKSL_FORMAT "// Vertex SKSL\n%s\n// Fragment SKSL\n%s\n"
88 #else
89 #define SKSL_FORMAT "%s\n%s\n"
90 #endif
91 if (sksl) {
92 SkSL::String::appendf(&allShaders, SKSL_FORMAT,
93 sksl[kVertex_GrShaderType]->c_str(),
94 sksl[kFragment_GrShaderType]->c_str());
95 }
96 if (glsl) {
97 SkSL::String::appendf(&allShaders, SKSL_FORMAT,
98 glsl[kVertex_GrShaderType].c_str(),
99 glsl[kFragment_GrShaderType].c_str());
100 }
101 #undef SKSL_FORMAT
102 GrGLint infoLen = GR_GL_INIT_ZERO;
103 GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
104 SkAutoMalloc log(infoLen+1);
105 if (infoLen > 0) {
106 // retrieve length even though we don't need it to workaround
107 // bug in chrome cmd buffer param validation.
108 GrGLsizei length = GR_GL_INIT_ZERO;
109 GR_GL_CALL(gli, GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
110 }
111 const char* errorMsg = (infoLen > 0) ? (const char*)log.get()
112 : "link failed but did not provide an info log";
113 errorHandler->compileError(allShaders.c_str(), errorMsg, shaderWasCached);
114 }
115 return SkToBool(linked);
116 }
117