| Index: src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 
| diff --git a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 
| index d2e49a5cfb0b5716b988aa4d3aaec1d4a5451050..b26ce894f0246b35dbf6a0ecfcb266a89eedda43 100644 | 
| --- a/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 
| +++ b/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp | 
| @@ -9,6 +9,9 @@ | 
| #include "gl/GrGLGpu.h" | 
| #include "gl/GrGLSLPrettyPrint.h" | 
| #include "SkTraceEvent.h" | 
| +#include "SkSLCompiler.h" | 
| +#include "SkSLGLSLCodeGenerator.h" | 
| +#include "ir/SkSLProgram.h" | 
|  | 
| #define GL_CALL(X) GR_GL_CALL(gpu->glInterface(), X) | 
| #define GL_CALL_RET(R, X) GR_GL_CALL_RET(gpu->glInterface(), R, X) | 
| @@ -18,6 +21,90 @@ static const bool c_PrintShaders{false}; | 
|  | 
| static void print_shader_source(const char** strings, int* lengths, int count); | 
|  | 
| +SkSL::GLCaps GrGLSkSLCapsForContext(const GrGLContext& context) { | 
| +    GrGLStandard standard = context.standard(); | 
| +    const GrGLCaps* caps = context.caps(); | 
| +    const GrGLSLCaps* glslCaps = caps->glslCaps(); | 
| +    SkSL::GLCaps result; | 
| +    switch (standard) { | 
| +        case kGL_GrGLStandard: | 
| +            result.fStandard = SkSL::GLCaps::kGL_Standard; | 
| +            break; | 
| +        case kGLES_GrGLStandard: | 
| +            result.fStandard = SkSL::GLCaps::kGLES_Standard; | 
| +            break; | 
| +        default: | 
| +            SkASSERT(false); | 
| +            result.fStandard = SkSL::GLCaps::kGL_Standard; | 
| +    } | 
| + | 
| +    switch (glslCaps->generation()) { | 
| +        case k110_GrGLSLGeneration: | 
| +            if (kGLES_GrGLStandard == standard) { | 
| +                // ES2's shader language is based on GLSL 1.20 but is version 1.00 of the ES | 
| +                // language | 
| +                result.fVersion = 100; | 
| +            } else { | 
| +                SkASSERT(kGL_GrGLStandard == standard); | 
| +                result.fVersion = 110; | 
| +            } | 
| +            break; | 
| +        case k130_GrGLSLGeneration: | 
| +            SkASSERT(kGL_GrGLStandard == standard); | 
| +            result.fVersion = 130; | 
| +            break; | 
| +        case k140_GrGLSLGeneration: | 
| +            SkASSERT(kGL_GrGLStandard == standard); | 
| +            result.fVersion = 140; | 
| +            break; | 
| +        case k150_GrGLSLGeneration: | 
| +            SkASSERT(kGL_GrGLStandard == standard); | 
| +            result.fVersion = 150; | 
| +            break; | 
| +        case k330_GrGLSLGeneration: | 
| +            if (kGLES_GrGLStandard == standard) { | 
| +                result.fVersion = 300; | 
| +            } else { | 
| +                SkASSERT(kGL_GrGLStandard == standard); | 
| +                result.fVersion = 330; | 
| +            } | 
| +            break; | 
| +        case k400_GrGLSLGeneration: | 
| +            SkASSERT(kGL_GrGLStandard == standard); | 
| +            result.fVersion = 400; | 
| +            break; | 
| +        case k310es_GrGLSLGeneration: | 
| +            SkASSERT(kGLES_GrGLStandard == standard); | 
| +            result.fVersion = 310; | 
| +            break; | 
| +        case k320es_GrGLSLGeneration: | 
| +            SkASSERT(kGLES_GrGLStandard == standard); | 
| +            result.fVersion = 320; | 
| +            break; | 
| +    } | 
| +    result.fIsCoreProfile = caps->isCoreProfile(); | 
| +    result.fUsesPrecisionModifiers = glslCaps->usesPrecisionModifiers(); | 
| +    result.fMustDeclareFragmentShaderOutput = glslCaps->mustDeclareFragmentShaderOutput(); | 
| +    result.fCanUseMinAndAbsTogether = glslCaps->canUseMinAndAbsTogether(); | 
| +    return result; | 
| +} | 
| + | 
| +static void dump_string(std::string s) { | 
| +    // on Android, SkDebugf only displays the first 1K characters of output, which results in | 
| +    // incomplete shader source code. Print each line individually to avoid this problem. | 
| +    size_t index = 0; | 
| +    for (;;) { | 
| +        size_t next = s.find("\n", index); | 
| +        if (next == std::string::npos) { | 
| +            SkDebugf("%s", s.substr(index).c_str()); | 
| +            break; | 
| +        } else { | 
| +            SkDebugf("%s", s.substr(index, next - index + 1).c_str()); | 
| +            index = next + 1; | 
| +        } | 
| +    } | 
| +} | 
| + | 
| GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, | 
| GrGLuint programId, | 
| GrGLenum type, | 
| @@ -33,15 +120,40 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, | 
| return 0; | 
| } | 
|  | 
| +    std::string sksl; | 
| #ifdef SK_DEBUG | 
| SkString prettySource = GrGLSLPrettyPrint::PrettyPrintGLSL(strings, lengths, count, false); | 
| -    const GrGLchar* sourceStr = prettySource.c_str(); | 
| -    GrGLint sourceLength = static_cast<GrGLint>(prettySource.size()); | 
| -    GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); | 
| +    sksl = std::string(prettySource.c_str()); | 
| #else | 
| -    GR_GL_CALL(gli, ShaderSource(shaderId, count, strings, lengths)); | 
| +    for (int i = 0; i < count; i++) { | 
| +        sksl.append(strings[i], lengths[i]); | 
| +    } | 
| +#endif | 
| + | 
| +    std::string glsl; | 
| +    SkSL::Compiler& compiler = *glCtx.compiler(); | 
| +    SkSL::GLCaps caps = GrGLSkSLCapsForContext(glCtx); | 
| +    SkASSERT(type == GR_GL_VERTEX_SHADER || type == GR_GL_FRAGMENT_SHADER); | 
| +    SkDEBUGCODE(bool result = )compiler.toGLSL(type == GR_GL_VERTEX_SHADER | 
| +                                                                    ? SkSL::Program::kVertex_Kind | 
| +                                                                    : SkSL::Program::kFragment_Kind, | 
| +                                               std::string(sksl.c_str()), | 
| +                                               caps, | 
| +                                               &glsl); | 
| +#ifdef SK_DEBUG | 
| +    if (!result) { | 
| +        SkDebugf("SKSL compilation error\n----------------------\n"); | 
| +        SkDebugf("SKSL:\n"); | 
| +        dump_string(sksl); | 
| +        SkDebugf("\nErrors:\n%s\n", compiler.errorText().c_str()); | 
| +        SkDEBUGFAIL("SKSL compilation failed!\n"); | 
| +    } | 
| #endif | 
|  | 
| +    const char* glslChars = glsl.c_str(); | 
| +    GrGLint glslLength = (GrGLint) glsl.length(); | 
| +    GR_GL_CALL(gli, ShaderSource(shaderId, 1, &glslChars, &glslLength)); | 
| + | 
| // If tracing is enabled in chrome then we pretty print | 
| bool traceShader; | 
| TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), &traceShader); | 
| @@ -72,10 +184,14 @@ GrGLuint GrGLCompileAndAttachShader(const GrGLContext& glCtx, | 
| // buffer param validation. | 
| GrGLsizei length = GR_GL_INIT_ZERO; | 
| GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); | 
| -                print_shader_source(strings, lengths, count); | 
| -                SkDebugf("\n%s", (const char*)log.get()); | 
| +                SkDebugf("GLSL compilation error\n----------------------\n"); | 
| +                SkDebugf("SKSL:\n"); | 
| +                dump_string(sksl); | 
| +                SkDebugf("GLSL:\n"); | 
| +                dump_string(glsl); | 
| +                SkDebugf("Errors:\n%s\n", (const char*) log.get()); | 
| } | 
| -            SkDEBUGFAIL("Shader compilation failed!"); | 
| +            SkDEBUGFAIL("GLSL compilation failed!"); | 
| GR_GL_CALL(gli, DeleteShader(shaderId)); | 
| return 0; | 
| } | 
|  |