blob: 8eb9a1424bb8cf9c3f223149a3356c983853d5e7 [file] [log] [blame]
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ganesh/gl/builders/GrGLShaderStringBuilder.h"
#include "include/gpu/ganesh/gl/GrGLFunctions.h"
#include "include/gpu/ganesh/gl/GrGLInterface.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkAutoMalloc.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/ganesh/gl/GrGLDefines.h"
#include "src/gpu/ganesh/gl/GrGLGpu.h"
#include "src/gpu/ganesh/gl/GrGLUtil.h"
#include "src/sksl/SkSLString.h"
#include "src/sksl/codegen/SkSLNativeShader.h"
#include <cstdint>
GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx,
GrGLuint programId,
GrGLenum type,
const SkSL::NativeShader& glsl,
bool shaderWasCached,
GrThreadSafePipelineBuilder::Stats* stats,
GrContextOptions::ShaderErrorHandler* errorHandler) {
TRACE_EVENT0_ALWAYS("skia.shaders", "driver_compile_shader");
const GrGLInterface* gli = glCtx.glInterface();
// Specify GLSL source to the driver.
GrGLuint shaderId;
GR_GL_CALL_RET(gli, shaderId, CreateShader(type));
if (0 == shaderId) {
return 0;
}
const GrGLchar* source = glsl.fText.c_str();
GrGLint sourceLength = SkToInt(glsl.fText.size());
GR_GL_CALL(gli, ShaderSource(shaderId, 1, &source, &sourceLength));
stats->incShaderCompilations();
GR_GL_CALL(gli, CompileShader(shaderId));
{
ATRACE_ANDROID_FRAMEWORK("checkCompiled");
GrGLint compiled = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled));
if (!compiled) {
GrGLint infoLen = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger
if (infoLen > 0) {
// retrieve length even though we don't need it to workaround bug in Chromium cmd
// buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get()));
}
errorHandler->compileError(
glsl.fText.c_str(), infoLen > 0 ? (const char*)log.get() : "", shaderWasCached);
GR_GL_CALL(gli, DeleteShader(shaderId));
return 0;
}
}
// Attach the shader, but defer deletion until after we have linked the program.
// This works around a bug in the Android emulator's GLES2 wrapper which
// will immediately delete the shader object and free its memory even though it's
// attached to a program, which then causes glLinkProgram to fail.
GR_GL_CALL(gli, AttachShader(programId, shaderId));
return shaderId;
}
bool GrGLCheckLinkStatus(const GrGLGpu* gpu,
GrGLuint programID,
bool shaderWasCached,
GrContextOptions::ShaderErrorHandler* errorHandler,
const std::string* sksl[kGrShaderTypeCount],
const SkSL::NativeShader glsl[kGrShaderTypeCount]) {
const GrGLInterface* gli = gpu->glInterface();
GrGLint linked = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_LINK_STATUS, &linked));
if (!linked && errorHandler) {
std::string allShaders;
#if defined(SK_DEBUG)
#define SKSL_FORMAT "// Vertex SKSL\n%s\n// Fragment SKSL\n%s\n"
#else
#define SKSL_FORMAT "%s\n%s\n"
#endif
if (sksl) {
SkSL::String::appendf(&allShaders, SKSL_FORMAT,
sksl[kVertex_GrShaderType]->c_str(),
sksl[kFragment_GrShaderType]->c_str());
}
if (glsl) {
SkSL::String::appendf(&allShaders,
SKSL_FORMAT,
glsl[kVertex_GrShaderType].fText.c_str(),
glsl[kFragment_GrShaderType].fText.c_str());
}
#undef SKSL_FORMAT
GrGLint infoLen = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetProgramiv(programID, GR_GL_INFO_LOG_LENGTH, &infoLen));
SkAutoMalloc log(infoLen+1);
if (infoLen > 0) {
// retrieve length even though we don't need it to workaround
// bug in chrome cmd buffer param validation.
GrGLsizei length = GR_GL_INIT_ZERO;
GR_GL_CALL(gli, GetProgramInfoLog(programID, infoLen+1, &length, (char*)log.get()));
}
const char* errorMsg = (infoLen > 0) ? (const char*)log.get()
: "link failed but did not provide an info log";
errorHandler->compileError(allShaders.c_str(), errorMsg, shaderWasCached);
}
return SkToBool(linked);
}