xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 (sksl) {
87             SkSL::String::appendf(&allShaders, "// Vertex SKSL\n%s\n"
88                                                "// Fragment SKSL\n%s\n",
89                                                sksl[kVertex_GrShaderType]->c_str(),
90                                                sksl[kFragment_GrShaderType]->c_str());
91         }
92         if (glsl) {
93             SkSL::String::appendf(&allShaders, "// Vertex GLSL\n%s\n"
94                                                "// Fragment GLSL\n%s\n",
95                                                glsl[kVertex_GrShaderType].c_str(),
96                                                glsl[kFragment_GrShaderType].c_str());
97         }
98         GrGLint infoLen = GR_GL_INIT_ZERO;
99         GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
100         SkAutoMalloc log(infoLen+1);
101         if (infoLen > 0) {
102             // retrieve length even though we don't need it to workaround
103             // bug in chrome cmd buffer param validation.
104             GrGLsizei length = GR_GL_INIT_ZERO;
105             GR_GL_CALL(gli, GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
106         }
107         const char* errorMsg = (infoLen > 0) ? (const char*)log.get()
108                                              : "link failed but did not provide an info log";
109         errorHandler->compileError(allShaders.c_str(), errorMsg, shaderWasCached);
110     }
111     return SkToBool(linked);
112 }
113