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; }
static void doDraw() { if (NULL == gContext) { gContext = make_context(); } State* state = get_state(); SkBitmap viewport; viewport.setConfig(SkBitmap::kARGB_8888_Config, state->getWidth(), state->getHeight()); SkGpuCanvas canvas(gContext); canvas.setBitmapDevice(viewport); state->applyMatrix(&canvas); drawIntoCanvas(state, &canvas); GrGLCheckErr(); GrGLClearErr(); // gContext->checkError(); // gContext->clearError(); if (true) { static const int FRAME_COUNT = 32; static SkMSec gDuration; static SkMSec gNow; static int gFrameCounter; if (++gFrameCounter == FRAME_COUNT) { gFrameCounter = 0; SkMSec now = SkTime::GetMSecs(); gDuration = now - gNow; gNow = now; } int fps = (FRAME_COUNT * 1000) / gDuration; SkString str; str.printf("FPS=%3d MS=%3d", fps, gDuration / FRAME_COUNT); SkGpuCanvas c(gContext); c.setBitmapDevice(viewport); SkPaint p; p.setAntiAlias(true); SkRect r = { 0, 0, 110, 16 }; p.setColor(SK_ColorWHITE); c.drawRect(r, p); p.setColor(SK_ColorBLACK); c.drawText(str.c_str(), str.size(), 4, 12, p); } }
void GrGpuGLFixed::resetContext() { INHERITED::resetContext(); GR_GL(Disable(GR_GL_TEXTURE_2D)); for (int s = 0; s < kNumStages; ++s) { setTextureUnit(s); GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_TEXTURE_ENV_MODE, GR_GL_COMBINE)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_RGB, GR_GL_MODULATE)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_RGB, GR_GL_TEXTURE0+s)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_RGB, GR_GL_PREVIOUS)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_RGB, GR_GL_SRC_COLOR)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_COMBINE_ALPHA, GR_GL_MODULATE)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC0_ALPHA, GR_GL_TEXTURE0+s)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND0_ALPHA, GR_GL_SRC_ALPHA)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_SRC1_ALPHA, GR_GL_PREVIOUS)); GR_GL(TexEnvi(GR_GL_TEXTURE_ENV, GR_GL_OPERAND1_ALPHA, GR_GL_SRC_ALPHA)); // color oprand0 changes between GL_SRC_COLR and GL_SRC_ALPHA depending // upon whether we have a (premultiplied) RGBA texture or just an ALPHA // texture, e.g.: //glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); fHWRGBOperand0[s] = (TextureEnvRGBOperands) -1; } fHWGeometryState.fVertexLayout = 0; fHWGeometryState.fVertexOffset = ~0; GR_GL(EnableClientState(GR_GL_VERTEX_ARRAY)); GR_GL(DisableClientState(GR_GL_TEXTURE_COORD_ARRAY)); GR_GL(ShadeModel(GR_GL_FLAT)); GR_GL(DisableClientState(GR_GL_COLOR_ARRAY)); GR_GL(PointSize(1.f)); GrGLClearErr(); fTextVerts = false; fBaseVertex = 0xffffffff; }
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); }