GrGLuint SkANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
    GrGLClearErr(this->gl());
    if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
        return 0;
    }
    GrGLEGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
        (GrGLEGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
    if (!glEGLImageTargetTexture2D) {
        return 0;
    }
    GrGLuint texID;
    GR_GL_CALL(this->gl(), GenTextures(1, &texID));
    if (!texID) {
        return 0;
    }
    GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
    if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
        GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
        return 0;
    }
    glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
    if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
        GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
        return 0;
    }
    return texID;
}
Example #2
0
void GrGLCheckErr(const GrGLInterface* gl,
                  const char* location,
                  const char* call) {
    uint32_t err = GR_GL_GET_ERROR(gl);
    if (GR_GL_NO_ERROR != err) {
        GrPrintf("---- glGetError 0x%x(%s)", err, get_error_string(err));
        if (NULL != location) {
            GrPrintf(" at\n\t%s", location);
        }
        if (NULL != call) {
            GrPrintf("\n\t\t%s", call);
        }
        GrPrintf("\n");
    }
}
Example #3
0
GrGLProgram* GrGLProgramBuilder::finalize() {
    TRACE_EVENT0("skia", TRACE_FUNC);

    // verify we can get a program id
    GrGLuint programID;
    GL_CALL_RET(programID, CreateProgram());
    if (0 == programID) {
        this->cleanupFragmentProcessors();
        return nullptr;
    }

    if (this->gpu()->glCaps().programBinarySupport() &&
        this->gpu()->getContext()->contextPriv().getPersistentCache()) {
        GL_CALL(ProgramParameteri(programID, GR_GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GR_GL_TRUE));
    }

    this->finalizeShaders();

    // compile shaders and bind attributes / uniforms
    const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
    SkSL::Program::Settings settings;
    settings.fCaps = this->gpu()->glCaps().shaderCaps();
    settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
    settings.fSharpenTextures = this->gpu()->getContext()->contextPriv().sharpenMipmappedTextures();
    SkSL::Program::Inputs inputs;
    SkTDArray<GrGLuint> shadersToDelete;
    bool cached = fGpu->glCaps().programBinarySupport() && nullptr != fCached.get();
    if (cached) {
        this->bindProgramResourceLocations(programID);
        // cache hit, just hand the binary to GL
        const uint8_t* bytes = fCached->bytes();
        size_t offset = 0;
        memcpy(&inputs, bytes + offset, sizeof(inputs));
        offset += sizeof(inputs);
        int binaryFormat;
        memcpy(&binaryFormat, bytes + offset, sizeof(binaryFormat));
        offset += sizeof(binaryFormat);
        GrGLClearErr(this->gpu()->glInterface());
        GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
                              ProgramBinary(programID, binaryFormat, (void*) (bytes + offset),
                                            fCached->size() - offset));
        if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
            if (inputs.fRTHeight) {
                this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
            }
            cached = this->checkLinkStatus(programID);
        } else {
            cached = false;
        }
    }
    if (!cached) {
        // cache miss, compile shaders
        if (fFS.fForceHighPrecision) {
            settings.fForceHighPrecision = true;
        }
        SkSL::String glsl;
        std::unique_ptr<SkSL::Program> fs = GrSkSLtoGLSL(gpu()->glContext(),
                                                         GR_GL_FRAGMENT_SHADER,
                                                         fFS.fCompilerStrings.begin(),
                                                         fFS.fCompilerStringLengths.begin(),
                                                         fFS.fCompilerStrings.count(),
                                                         settings,
                                                         &glsl);
        inputs = fs->fInputs;
        if (inputs.fRTHeight) {
            this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
        }
        if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                           GR_GL_FRAGMENT_SHADER, &shadersToDelete, settings,
                                           inputs)) {
            this->cleanupProgram(programID, shadersToDelete);
            return nullptr;
        }

        std::unique_ptr<SkSL::Program> vs = GrSkSLtoGLSL(gpu()->glContext(),
                                                         GR_GL_VERTEX_SHADER,
                                                         fVS.fCompilerStrings.begin(),
                                                         fVS.fCompilerStringLengths.begin(),
                                                         fVS.fCompilerStrings.count(),
                                                         settings,
                                                         &glsl);
        if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                           GR_GL_VERTEX_SHADER, &shadersToDelete, settings,
                                           inputs)) {
            this->cleanupProgram(programID, shadersToDelete);
            return nullptr;
        }

        // NVPR actually requires a vertex shader to compile
        bool useNvpr = primProc.isPathRendering();
        if (!useNvpr) {
            int vaCount = primProc.numAttribs();
            for (int i = 0; i < vaCount; i++) {
                GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName));
            }
        }

        if (primProc.willUseGeoShader()) {
            std::unique_ptr<SkSL::Program> gs;
            gs = GrSkSLtoGLSL(gpu()->glContext(),
                              GR_GL_GEOMETRY_SHADER,
                              fGS.fCompilerStrings.begin(),
                              fGS.fCompilerStringLengths.begin(),
                              fGS.fCompilerStrings.count(),
                              settings,
                              &glsl);
            if (!this->compileAndAttachShaders(glsl.c_str(), glsl.size(), programID,
                                               GR_GL_GEOMETRY_SHADER, &shadersToDelete, settings,
                                               inputs)) {
                this->cleanupProgram(programID, shadersToDelete);
                return nullptr;
            }

        }
        this->bindProgramResourceLocations(programID);

        GL_CALL(LinkProgram(programID));
    }
    // Calling GetProgramiv is expensive in Chromium. Assume success in release builds.
    bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver();
#ifdef SK_DEBUG
    checkLinked = true;
#endif
    if (checkLinked) {
        if (!this->checkLinkStatus(programID)) {
            SkDebugf("VS:\n");
            GrGLPrintShader(fGpu->glContext(), GR_GL_VERTEX_SHADER, fVS.fCompilerStrings.begin(),
                            fVS.fCompilerStringLengths.begin(), fVS.fCompilerStrings.count(),
                            settings);
            if (primProc.willUseGeoShader()) {
                SkDebugf("\nGS:\n");
                GrGLPrintShader(fGpu->glContext(), GR_GL_GEOMETRY_SHADER,
                                fGS.fCompilerStrings.begin(), fGS.fCompilerStringLengths.begin(),
                                fGS.fCompilerStrings.count(), settings);
            }
            SkDebugf("\nFS:\n");
            GrGLPrintShader(fGpu->glContext(), GR_GL_FRAGMENT_SHADER, fFS.fCompilerStrings.begin(),
                            fFS.fCompilerStringLengths.begin(), fFS.fCompilerStrings.count(),
                            settings);
            SkDEBUGFAIL("");
            return nullptr;
        }
    }
    this->resolveProgramResourceLocations(programID);

    this->cleanupShaders(shadersToDelete);
    if (!cached && this->gpu()->getContext()->contextPriv().getPersistentCache() &&
        fGpu->glCaps().programBinarySupport()) {
        GrGLsizei length = 0;
        GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
        if (length > 0) {
            // store shader in cache
            sk_sp<SkData> key = SkData::MakeWithoutCopy(desc()->asKey(), desc()->keyLength());
            GrGLenum binaryFormat;
            std::unique_ptr<char[]> binary(new char[length]);
            GL_CALL(GetProgramBinary(programID, length, &length, &binaryFormat, binary.get()));
            size_t dataLength = sizeof(inputs) + sizeof(binaryFormat) + length;
            std::unique_ptr<uint8_t[]> data(new uint8_t[dataLength]);
            size_t offset = 0;
            memcpy(data.get() + offset, &inputs, sizeof(inputs));
            offset += sizeof(inputs);
            memcpy(data.get() + offset, &binaryFormat, sizeof(binaryFormat));
            offset += sizeof(binaryFormat);
            memcpy(data.get() + offset, binary.get(), length);
            this->gpu()->getContext()->contextPriv().getPersistentCache()->store(
                                            *key, *SkData::MakeWithoutCopy(data.get(), dataLength));
        }
    }
    return this->createProgram(programID);
}