diff options
36 files changed, 644 insertions, 366 deletions
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp index e097fe0947..3a9f0c2a46 100644 --- a/bench/benchmain.cpp +++ b/bench/benchmain.cpp @@ -48,6 +48,11 @@ const char* BenchMode_Name[] = { static const char kDefaultsConfigStr[] = "defaults"; +#if SK_SUPPORT_GPU +static const char kGpuAPINameGL[] = "gl"; +static const char kGpuAPINameGLES[] = "gles"; +#endif + /////////////////////////////////////////////////////////////////////////////// class Iter { @@ -225,6 +230,10 @@ DEFINE_bool(forceFilter, false, "Force bitmap filtering?"); DEFINE_string(forceDither, "default", "Force dithering: true, false, or default?"); DEFINE_bool(forceBlend, false, "Force alpha blending?"); +DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" " + "forces OpenGL API. Using \"gles\" forces OpenGL ES API. " + "Defaults to empty string, which selects the API native to the " + "system."); DEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes. 0 to disable cache."); DEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count. 0 to disable cache."); @@ -346,11 +355,24 @@ int tool_main(int argc, char** argv) { } #if SK_SUPPORT_GPU + GrGLStandard gpuAPI = kNone_GrGLStandard; + if (1 == FLAGS_gpuAPI.count()) { + if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { + gpuAPI = kGL_GrGLStandard; + } else if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { + gpuAPI = kGLES_GrGLStandard; + } else { + SkDebugf("Selected gpu API could not be used. Using the default.\n"); + } + } else if (FLAGS_gpuAPI.count() > 1) { + SkDebugf("Selected gpu API could not be used. Using the default.\n"); + } + for (int i = 0; i < configs.count(); ++i) { const Config& config = gConfigs[configs[i]]; if (Benchmark::kGPU_Backend == config.backend) { - GrContext* context = gContextFactory.get(config.contextType); + GrContext* context = gContextFactory.get(config.contextType, gpuAPI); if (NULL == context) { SkDebugf("GrContext could not be created for config %s. Config will be skipped.\n", config.name); @@ -410,7 +432,7 @@ int tool_main(int argc, char** argv) { if (Benchmark::kGPU_Backend != config.backend) { continue; } - GrContext* context = gContextFactory.get(config.contextType); + GrContext* context = gContextFactory.get(config.contextType, gpuAPI); if (NULL == context) { continue; } @@ -456,7 +478,7 @@ int tool_main(int argc, char** argv) { #if SK_SUPPORT_GPU SkGLContextHelper* glContext = NULL; if (Benchmark::kGPU_Backend == config.backend) { - context = gContextFactory.get(config.contextType); + context = gContextFactory.get(config.contextType, gpuAPI); if (NULL == context) { continue; } @@ -37,8 +37,15 @@ using skiagm::GMRegistry; using skiatest::Test; using skiatest::TestRegistry; +static const char kGpuAPINameGL[] = "gl"; +static const char kGpuAPINameGLES[] = "gles"; + DEFINE_int32(threads, -1, "Threads for CPU work. Default NUM_CPUS."); DEFINE_int32(gpuThreads, 1, "Threads for GPU work."); +DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" " + "forces OpenGL API. Using \"gles\" forces OpenGL ES API. " + "Defaults to empty string, which selects the API native to the " + "system."); DEFINE_string2(expectations, r, "", "If a directory, compare generated images against images under this path. " "If a file, compare generated images against JSON expectations at this path." @@ -95,6 +102,7 @@ native; static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms, const SkTArray<SkString>& configs, + GrGLStandard gpuAPI, const DM::Expectations& expectations, DM::Reporter* reporter, DM::TaskRunner* tasks) { @@ -104,17 +112,18 @@ static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms, } for (int i = 0; i < gms.count(); i++) { for (int j = 0; j < configs.count(); j++) { + START("565", CpuGMTask, expectations, kRGB_565_SkColorType); START("8888", CpuGMTask, expectations, kN32_SkColorType); - START("gpu", GpuGMTask, expectations, native, 0); - START("msaa4", GpuGMTask, expectations, native, 4); - START("msaa16", GpuGMTask, expectations, native, 16); - START("nvprmsaa4", GpuGMTask, expectations, nvpr, 4); - START("nvprmsaa16", GpuGMTask, expectations, nvpr, 16); - START("gpunull", GpuGMTask, expectations, null, 0); - START("gpudebug", GpuGMTask, expectations, debug, 0); - START("angle", GpuGMTask, expectations, angle, 0); - START("mesa", GpuGMTask, expectations, mesa, 0); + START("gpu", GpuGMTask, expectations, native, gpuAPI, 0); + START("msaa4", GpuGMTask, expectations, native, gpuAPI, 4); + START("msaa16", GpuGMTask, expectations, native, gpuAPI, 16); + START("nvprmsaa4", GpuGMTask, expectations, nvpr, gpuAPI, 4); + START("nvprmsaa16", GpuGMTask, expectations, nvpr, gpuAPI, 16); + START("gpunull", GpuGMTask, expectations, null, gpuAPI, 0); + START("gpudebug", GpuGMTask, expectations, debug, gpuAPI, 0); + START("angle", GpuGMTask, expectations, angle, gpuAPI, 0); + START("mesa", GpuGMTask, expectations, mesa, gpuAPI, 0); START("pdf", PDFTask, RASTERIZE_PDF_PROC); } } @@ -123,6 +132,7 @@ static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms, static void kick_off_benches(const SkTDArray<BenchRegistry::Factory>& benches, const SkTArray<SkString>& configs, + GrGLStandard gpuAPI, DM::Reporter* reporter, DM::TaskRunner* tasks) { #define START(name, type, ...) \ @@ -134,15 +144,15 @@ static void kick_off_benches(const SkTDArray<BenchRegistry::Factory>& benches, START("nonrendering", NonRenderingBenchTask); START("565", CpuBenchTask, kRGB_565_SkColorType); START("8888", CpuBenchTask, kN32_SkColorType); - START("gpu", GpuBenchTask, native, 0); - START("msaa4", GpuBenchTask, native, 4); - START("msaa16", GpuBenchTask, native, 16); - START("nvprmsaa4", GpuBenchTask, nvpr, 4); - START("nvprmsaa16", GpuBenchTask, nvpr, 16); - START("gpunull", GpuBenchTask, null, 0); - START("gpudebug", GpuBenchTask, debug, 0); - START("angle", GpuBenchTask, angle, 0); - START("mesa", GpuBenchTask, mesa, 0); + START("gpu", GpuBenchTask, native, gpuAPI, 0); + START("msaa4", GpuBenchTask, native, gpuAPI, 4); + START("msaa16", GpuBenchTask, native, gpuAPI, 16); + START("nvprmsaa4", GpuBenchTask, nvpr, gpuAPI, 4); + START("nvprmsaa16", GpuBenchTask, nvpr, gpuAPI, 16); + START("gpunull", GpuBenchTask, null, gpuAPI, 0); + START("gpudebug", GpuBenchTask, debug, gpuAPI, 0); + START("angle", GpuBenchTask, angle, gpuAPI, 0); + START("mesa", GpuBenchTask, mesa, gpuAPI, 0); } } #undef START @@ -204,6 +214,16 @@ static void report_failures(const SkTArray<SkString>& failures) { SkDebugf("%d failures.\n", failures.count()); } +static GrGLStandard get_gl_standard() { + if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { + return kGL_GrGLStandard; + } + if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { + return kGLES_GrGLStandard; + } + return kNone_GrGLStandard; +} + template <typename T, typename Registry> static void append_matching_factories(Registry* head, SkTDArray<typename Registry::Factory>* out) { for (const Registry* reg = head; reg != NULL; reg = reg->next()) { @@ -232,6 +252,8 @@ int tool_main(int argc, char** argv) { SkStrSplit(FLAGS_config[i], ", ", &configs); } + GrGLStandard gpuAPI = get_gl_standard(); + SkTDArray<GMRegistry::Factory> gms; SkAutoTDelete<DM::Expectations> expectations(SkNEW(DM::NoExpectations)); if (FLAGS_gms) { @@ -261,8 +283,8 @@ int tool_main(int argc, char** argv) { gms.count(), benches.count(), configs.count(), tests.count()); DM::Reporter reporter; DM::TaskRunner tasks(FLAGS_threads, FLAGS_gpuThreads); - kick_off_gms(gms, configs, *expectations, &reporter, &tasks); - kick_off_benches(benches, configs, &reporter, &tasks); + kick_off_gms(gms, configs, gpuAPI, *expectations, &reporter, &tasks); + kick_off_benches(benches, configs, gpuAPI, &reporter, &tasks); kick_off_tests(tests, &reporter, &tasks); kick_off_skps(&reporter, &tasks); tasks.wait(); diff --git a/dm/DMBenchTask.cpp b/dm/DMBenchTask.cpp index 7cd2fdcb03..9bdbbf2974 100644 --- a/dm/DMBenchTask.cpp +++ b/dm/DMBenchTask.cpp @@ -33,11 +33,13 @@ GpuBenchTask::GpuBenchTask(const char* config, TaskRunner* tasks, BenchRegistry::Factory factory, GrContextFactory::GLContextType contextType, + GrGLStandard gpuAPI, int sampleCount) : GpuTask(reporter, tasks) , fBench(factory(NULL)) , fName(bench_name(fBench->getName(), config)) , fContextType(contextType) + , fGpuAPI(gpuAPI) , fSampleCount(sampleCount) {} bool NonRenderingBenchTask::shouldSkip() const { @@ -74,8 +76,12 @@ void GpuBenchTask::draw(GrContextFactory* grFactory) { fBench->getSize().y(), kN32_SkColorType, kPremul_SkAlphaType); - SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, info, fSampleCount)); - + SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, fGpuAPI, info, + fSampleCount)); + if (!surface) { + this->fail("Could not create context for the config and the api."); + return; + } fBench->preDraw(); fBench->draw(1, surface->getCanvas()); } diff --git a/dm/DMBenchTask.h b/dm/DMBenchTask.h index 3c71cd76f0..d2b58004f9 100644 --- a/dm/DMBenchTask.h +++ b/dm/DMBenchTask.h @@ -46,6 +46,7 @@ public: TaskRunner*, BenchRegistry::Factory, GrContextFactory::GLContextType, + GrGLStandard gpuAPI, int sampleCount); virtual void draw(GrContextFactory*) SK_OVERRIDE; @@ -56,6 +57,7 @@ private: SkAutoTDelete<Benchmark> fBench; const SkString fName; const GrContextFactory::GLContextType fContextType; + const GrGLStandard fGpuAPI; int fSampleCount; }; diff --git a/dm/DMGpuGMTask.cpp b/dm/DMGpuGMTask.cpp index b384485e4c..4c44fae970 100644 --- a/dm/DMGpuGMTask.cpp +++ b/dm/DMGpuGMTask.cpp @@ -15,12 +15,14 @@ GpuGMTask::GpuGMTask(const char* config, skiagm::GMRegistry::Factory gmFactory, const Expectations& expectations, GrContextFactory::GLContextType contextType, + GrGLStandard gpuAPI, int sampleCount) : GpuTask(reporter, taskRunner) , fGM(gmFactory(NULL)) , fName(UnderJoin(fGM->getName(), config)) , fExpectations(expectations) , fContextType(contextType) + , fGpuAPI(gpuAPI) , fSampleCount(sampleCount) {} @@ -29,7 +31,12 @@ void GpuGMTask::draw(GrContextFactory* grFactory) { SkScalarCeilToInt(fGM->height()), kN32_SkColorType, kPremul_SkAlphaType); - SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, info, fSampleCount)); + SkAutoTUnref<SkSurface> surface(NewGpuSurface(grFactory, fContextType, fGpuAPI, info, + fSampleCount)); + if (!surface) { + this->fail("Could not create context for the config and the api."); + return; + } SkCanvas* canvas = surface->getCanvas(); canvas->concat(fGM->getInitialTransform()); diff --git a/dm/DMGpuGMTask.h b/dm/DMGpuGMTask.h index 6621a49836..46b4c981bc 100644 --- a/dm/DMGpuGMTask.h +++ b/dm/DMGpuGMTask.h @@ -23,6 +23,7 @@ public: skiagm::GMRegistry::Factory, const Expectations&, GrContextFactory::GLContextType, + GrGLStandard gpuAPI, int sampleCount); virtual void draw(GrContextFactory*) SK_OVERRIDE; @@ -34,6 +35,7 @@ private: const SkString fName; const Expectations& fExpectations; const GrContextFactory::GLContextType fContextType; + GrGLStandard fGpuAPI; const int fSampleCount; }; diff --git a/dm/DMGpuSupport.h b/dm/DMGpuSupport.h index 46896b4321..bcc00c27e4 100644 --- a/dm/DMGpuSupport.h +++ b/dm/DMGpuSupport.h @@ -19,9 +19,10 @@ static const bool kGPUDisabled = false; static inline SkSurface* NewGpuSurface(GrContextFactory* grFactory, GrContextFactory::GLContextType type, + GrGLStandard gpuAPI, SkImageInfo info, int samples) { - return SkSurface::NewRenderTarget(grFactory->get(type), info, samples); + return SkSurface::NewRenderTarget(grFactory->get(type, gpuAPI), info, samples); } } // namespace DM @@ -30,6 +31,12 @@ static inline SkSurface* NewGpuSurface(GrContextFactory* grFactory, // Ganesh is not available. Fake it. +enum GrGLStandard { + kNone_GrGLStandard, + kGL_GrGLStandard, + kGLES_GrGLStandard +}; + class GrContextFactory { public: typedef int GLContextType; @@ -48,6 +55,7 @@ static const bool kGPUDisabled = true; static inline SkSurface* NewGpuSurface(GrContextFactory*, GrContextFactory::GLContextType, + GrGLStandard, SkImageInfo, int) { return NULL; diff --git a/experimental/PdfViewer/pdf_viewer_main.cpp b/experimental/PdfViewer/pdf_viewer_main.cpp index 2f1a055e4d..c1b0284d8a 100644 --- a/experimental/PdfViewer/pdf_viewer_main.cpp +++ b/experimental/PdfViewer/pdf_viewer_main.cpp @@ -168,7 +168,8 @@ static bool render_page(const SkString& outputDir, #if SK_SUPPORT_GPU else if (strcmp(FLAGS_config[0], "gpu") == 0) { SkAutoTUnref<GrSurface> target; - GrContext* gr = gContextFactory.get(GrContextFactory::kNative_GLContextType); + GrContext* gr = gContextFactory.get(GrContextFactory::kNative_GLContextType, + kNone_GrGLStandard); if (gr) { // create a render target to back the device GrTextureDesc desc; diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp index 364e771a36..96a3454bec 100644 --- a/gm/gmmain.cpp +++ b/gm/gmmain.cpp @@ -67,6 +67,7 @@ class GrContextFactory; class GrContext; class GrSurface; typedef int GLContextType; +typedef int GrGLStandard; #endif #define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message") @@ -1335,6 +1336,10 @@ static const PDFRasterizerData kPDFRasterizers[] = { static const char kDefaultsConfigStr[] = "defaults"; static const char kExcludeConfigChar = '~'; +#if SK_SUPPORT_GPU +static const char kGpuAPINameGL[] = "gl"; +static const char kGpuAPINameGLES[] = "gles"; +#endif static SkString configUsage() { SkString result; @@ -1424,6 +1429,10 @@ DEFINE_bool(dryRun, false, "Don't actually run the tests, just print what would DEFINE_string(excludeConfig, "", "Space delimited list of configs to skip."); DEFINE_bool(forceBWtext, false, "Disable text anti-aliasing."); #if SK_SUPPORT_GPU +DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" " + "forces OpenGL API. Using \"gles\" forces OpenGL ES API. " + "Defaults to empty string, which selects the API native to the " + "system."); DEFINE_string(gpuCacheSize, "", "<bytes> <count>: Limit the gpu cache to byte size or " "object count. " TOSTRING(DEFAULT_CACHE_VALUE) " for either value means " "use the default. 0 for either disables the cache."); @@ -1701,12 +1710,14 @@ ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs, const SkTDArray<const PDFRasterizerData*> &pdfRasterizers, const SkTDArray<SkScalar> &tileGridReplayScales, - GrContextFactory *grFactory); + GrContextFactory *grFactory, + GrGLStandard gpuAPI); ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs, const SkTDArray<const PDFRasterizerData*> &pdfRasterizers, const SkTDArray<SkScalar> &tileGridReplayScales, - GrContextFactory *grFactory) { + GrContextFactory *grFactory, + GrGLStandard gpuAPI) { const char renderModeDescriptor[] = ""; ErrorCombination errorsForAllConfigs; uint32_t gmFlags = gm->getFlags(); @@ -1756,7 +1767,7 @@ ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, if (FLAGS_resetGpuContext) { grFactory->destroyContexts(); } - GrContext* gr = grFactory->get(config.fGLContextType); + GrContext* gr = grFactory->get(config.fGLContextType, gpuAPI); bool grSuccess = false; if (gr) { // create a render target to back the device @@ -1927,7 +1938,7 @@ static bool prepare_subdirectories(const char *root, bool useFileHierarchy, } static bool parse_flags_configs(SkTDArray<size_t>* outConfigs, - GrContextFactory* grFactory) { + GrContextFactory* grFactory, GrGLStandard gpuAPI) { SkTDArray<size_t> excludeConfigs; for (int i = 0; i < FLAGS_config.count(); i++) { @@ -1994,7 +2005,7 @@ static bool parse_flags_configs(SkTDArray<size_t>* outConfigs, for (int i = 0; i < outConfigs->count(); ++i) { size_t index = (*outConfigs)[i]; if (kGPU_Backend == gRec[index].fBackend) { - GrContext* ctx = grFactory->get(gRec[index].fGLContextType); + GrContext* ctx = grFactory->get(gRec[index].fGLContextType, gpuAPI); if (NULL == ctx) { SkDebugf("GrContext could not be created for config %s. Config will be skipped.\n", gRec[index].fName); @@ -2148,6 +2159,25 @@ static bool parse_flags_gpu_cache(int* sizeBytes, int* sizeCount) { } return true; } + +static bool parse_flags_gl_standard(GrGLStandard* gpuAPI) { + if (0 == FLAGS_gpuAPI.count()) { + *gpuAPI = kNone_GrGLStandard; + return true; + } + if (1 == FLAGS_gpuAPI.count()) { + if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { + *gpuAPI = kGL_GrGLStandard; + return true; + } + if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { + *gpuAPI = kGLES_GrGLStandard; + return true; + } + } + SkDebugf("--gpuAPI invalid api value"); + return false; +} #endif static bool parse_flags_tile_grid_replay_scales(SkTDArray<SkScalar>* outScales) { @@ -2238,8 +2268,10 @@ int tool_main(int argc, char** argv) { SkTDArray<const PDFRasterizerData*> pdfRasterizers; SkTDArray<SkScalar> tileGridReplayScales; #if SK_SUPPORT_GPU + GrGLStandard gpuAPI = kNone_GrGLStandard; GrContextFactory* grFactory = new GrContextFactory; #else + GrGLStandard gpuAPI = 0; GrContextFactory* grFactory = NULL; #endif @@ -2252,10 +2284,11 @@ int tool_main(int argc, char** argv) { !parse_flags_ignore_tests(gmmain.fIgnorableTestNames) || #if SK_SUPPORT_GPU !parse_flags_gpu_cache(&gGpuCacheSizeBytes, &gGpuCacheSizeCount) || + !parse_flags_gl_standard(&gpuAPI) || #endif !parse_flags_tile_grid_replay_scales(&tileGridReplayScales) || !parse_flags_jpeg_quality() || - !parse_flags_configs(&configs, grFactory) || + !parse_flags_configs(&configs, grFactory, gpuAPI) || !parse_flags_pdf_rasterizers(configs, &pdfRasterizers) || !parse_flags_gmmain_paths(&gmmain)) { return -1; @@ -2337,7 +2370,8 @@ int tool_main(int argc, char** argv) { SkDebugf("%sdrawing... %s [%d %d]\n", moduloStr.c_str(), shortName, size.width(), size.height()); if (!FLAGS_dryRun) - run_multiple_configs(gmmain, gm, configs, pdfRasterizers, tileGridReplayScales, grFactory); + run_multiple_configs(gmmain, gm, configs, pdfRasterizers, tileGridReplayScales, + grFactory, gpuAPI); } if (FLAGS_dryRun) @@ -2414,7 +2448,7 @@ int tool_main(int argc, char** argv) { ConfigData config = gRec[configs[i]]; if (FLAGS_verbose && (kGPU_Backend == config.fBackend)) { - GrContext* gr = grFactory->get(config.fGLContextType); + GrContext* gr = grFactory->get(config.fGLContextType, gpuAPI); SkDebugf("config: %s %x\n", config.fName, gr); gr->printCacheStats(); @@ -2427,7 +2461,7 @@ int tool_main(int argc, char** argv) { ConfigData config = gRec[configs[i]]; if (kGPU_Backend == config.fBackend) { - GrContext* gr = grFactory->get(config.fGLContextType); + GrContext* gr = grFactory->get(config.fGLContextType, gpuAPI); gr->dumpFontCache(); } diff --git a/include/gpu/GrContextFactory.h b/include/gpu/GrContextFactory.h index f09bad932b..1f1f89df14 100644 --- a/include/gpu/GrContextFactory.h +++ b/include/gpu/GrContextFactory.h @@ -88,8 +88,7 @@ public: } } - GrContextFactory() { - } + GrContextFactory() { } ~GrContextFactory() { this->destroyContexts(); } @@ -105,9 +104,12 @@ public: /** * Get a GrContext initialized with a type of GL context. It also makes the GL context current. */ - GrContext* get(GLContextType type) { - + GrContext* get(GLContextType type, GrGLStandard forcedGpuAPI = kNone_GrGLStandard) { for (int i = 0; i < fContexts.count(); ++i) { + if (forcedGpuAPI != kNone_GrGLStandard && + forcedGpuAPI != fContexts[i].fGLContext->gl()->fStandard) + continue; + if (fContexts[i].fType == type) { fContexts[i].fGLContext->makeCurrent(); return fContexts[i].fGrContext; @@ -141,7 +143,7 @@ public: if (!glCtx.get()) { return NULL; } - if (!glCtx.get()->init(kBogusSize, kBogusSize)) { + if (!glCtx.get()->init(forcedGpuAPI, kBogusSize, kBogusSize)) { return NULL; } diff --git a/include/gpu/gl/SkANGLEGLContext.h b/include/gpu/gl/SkANGLEGLContext.h index 99ef4e9a99..c5f62ff3ce 100644 --- a/include/gpu/gl/SkANGLEGLContext.h +++ b/include/gpu/gl/SkANGLEGLContext.h @@ -36,7 +36,8 @@ public: }; protected: - virtual const GrGLInterface* createGLContext() SK_OVERRIDE; + virtual const GrGLInterface* createGLContext( + GrGLStandard forcedGpuAPI) SK_OVERRIDE; virtual void destroyGLContext() SK_OVERRIDE; private: diff --git a/include/gpu/gl/SkDebugGLContext.h b/include/gpu/gl/SkDebugGLContext.h index 545ef40027..9318cb455f 100644 --- a/include/gpu/gl/SkDebugGLContext.h +++ b/include/gpu/gl/SkDebugGLContext.h @@ -19,7 +19,7 @@ public: virtual void swapBuffers() const SK_OVERRIDE {}; protected: - virtual const GrGLInterface* createGLContext() SK_OVERRIDE; + virtual const GrGLInterface* createGLContext(GrGLStandard forcedGpuAPI) SK_OVERRIDE; virtual void destroyGLContext() SK_OVERRIDE {}; }; diff --git a/include/gpu/gl/SkGLContextHelper.h b/include/gpu/gl/SkGLContextHelper.h index ea940c8bc0..9da8741840 100644 --- a/include/gpu/gl/SkGLContextHelper.h +++ b/include/gpu/gl/SkGLContextHelper.h @@ -25,7 +25,7 @@ public: /** * Initializes the context and makes it current. */ - bool init(const int width, const int height); + bool init(GrGLStandard forcedGpuAPI, const int width, const int height); int getFBOID() const { return fFBO; } @@ -57,7 +57,7 @@ protected: * format and size of backbuffers does not matter since an FBO will be * created. */ - virtual const GrGLInterface* createGLContext() = 0; + virtual const GrGLInterface* createGLContext(GrGLStandard forcedGpuAPI) = 0; /** * Subclass should destroy the underlying GL context. diff --git a/include/gpu/gl/SkMesaGLContext.h b/include/gpu/gl/SkMesaGLContext.h index 55235fa603..28349ddd88 100644 --- a/include/gpu/gl/SkMesaGLContext.h +++ b/include/gpu/gl/SkMesaGLContext.h @@ -38,7 +38,7 @@ public: }; protected: - virtual const GrGLInterface* createGLContext() SK_OVERRIDE; + virtual const GrGLInterface* createGLContext(GrGLStandard forcedGpuAPI) SK_OVERRIDE; virtual void destroyGLContext() SK_OVERRIDE; private: diff --git a/include/gpu/gl/SkNativeGLContext.h b/include/gpu/gl/SkNativeGLContext.h index 7254de1509..fac52b354f 100644 --- a/include/gpu/gl/SkNativeGLContext.h +++ b/include/gpu/gl/SkNativeGLContext.h @@ -58,7 +58,7 @@ public: }; protected: - virtual const GrGLInterface* createGLContext() SK_OVERRIDE; + virtual const GrGLInterface* createGLContext(GrGLStandard forcedGpuAPI) SK_OVERRIDE; virtual void destroyGLContext() SK_OVERRIDE; private: diff --git a/include/gpu/gl/SkNullGLContext.h b/include/gpu/gl/SkNullGLContext.h index 02d968eeff..6c2a1d7e59 100644 --- a/include/gpu/gl/SkNullGLContext.h +++ b/include/gpu/gl/SkNullGLContext.h @@ -20,7 +20,7 @@ public: virtual void swapBuffers() const SK_OVERRIDE {}; protected: - virtual const GrGLInterface* createGLContext() SK_OVERRIDE; + virtual const GrGLInterface* createGLContext(GrGLStandard forcedGpuAPI) SK_OVERRIDE; virtual void destroyGLContext() SK_OVERRIDE {}; }; diff --git a/include/utils/SkWGL.h b/include/utils/SkWGL.h index 5f630a1689..5272f17c87 100644 --- a/include/utils/SkWGL.h +++ b/include/utils/SkWGL.h @@ -104,12 +104,22 @@ private: CreateContextAttribsProc fCreateContextAttribs; }; +enum SkWGLContextRequest { + /** Requests to create core profile context if possible, otherwise + compatibility profile. */ + kGLPreferCoreProfile_SkWGLContextRequest, + /** Requests to create compatibility profile context if possible, otherwise + core profile. */ + kGLPreferCompatibilityProfile_SkWGLContextRequest, + /** Requests to create GL ES profile context. */ + kGLES_SkWGLContextRequest +}; /** * Helper to create an OpenGL context for a DC using WGL. Configs with a sample count >= to * msaaSampleCount are preferred but if none is available then a context with a lower sample count * (including non-MSAA) will be created. If preferCoreProfile is true but a core profile cannot be * created then a compatible profile context will be created. */ -HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile); +HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest context); #endif diff --git a/src/gpu/gl/GrGLAssembleGLESInterface.h b/src/gpu/gl/GrGLAssembleGLESInterface.h new file mode 100644 index 0000000000..30602c12d5 --- /dev/null +++ b/src/gpu/gl/GrGLAssembleGLESInterface.h @@ -0,0 +1,256 @@ + +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* This file is meant to be included "inline" the implementation that is using the function. + * The platform native GL implementation header file should be included before this file. + * Following macros should be defined before this file is included: + * GET_PROC and GET_PROC_SUFFIX + * Call the get function and assign to the interface instance + * GET_PROC_LOCAL + * Call the get function and assign to a local variable + * GET_LINKED and GET_LINKED_SUFFIX + * Get the link-time address of the function and assign it to the interface instance. If + * using the linked addresses is not intended, can be the same as GET_PROC. + */ + +/** + * Generic function for creating a GrGLInterface for an OpenGL ES (but not Open GL) context. It + * calls get() to get each function address. ctx is a generic ptr passed to and interpreted by + * get(). + */ +static const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) { + const char* verStr = reinterpret_cast<const char*>(glGetString(GR_GL_VERSION)); + GrGLVersion version = GrGLGetVersionFromString(verStr); + + if (version < GR_GL_VER(2,0)) { + return NULL; + } + + GET_PROC_LOCAL(GetIntegerv); + GET_PROC_LOCAL(GetStringi); + GrGLExtensions extensions; + if (!extensions.init(kGLES_GrGLStandard, glGetString, GetStringi, GetIntegerv)) { + return NULL; + } + + GrGLInterface* interface = SkNEW(GrGLInterface); + GrGLInterface::Functions* functions = &interface->fFunctions; + + GET_LINKED(ActiveTexture); + GET_LINKED(AttachShader); + GET_LINKED(BindAttribLocation); + GET_LINKED(BindBuffer); + GET_LINKED(BindTexture); + GET_LINKED_SUFFIX(BindVertexArray, OES); + GET_LINKED(BlendColor); + GET_LINKED(BlendFunc); + GET_LINKED(BufferData); + GET_LINKED(BufferSubData); + GET_LINKED(Clear); + GET_LINKED(ClearColor); + GET_LINKED(ClearStencil); + GET_LINKED(ColorMask); + GET_LINKED(CompileShader); + GET_LINKED(CompressedTexImage2D); + GET_LINKED(CompressedTexSubImage2D); + GET_LINKED(CopyTexSubImage2D); + GET_LINKED(CreateProgram); + GET_LINKED(CreateShader); + GET_LINKED(CullFace); + GET_LINKED(DeleteBuffers); + GET_LINKED(DeleteProgram); + GET_LINKED(DeleteShader); + GET_LINKED(DeleteTextures); + GET_LINKED_SUFFIX(DeleteVertexArrays, OES); + GET_LINKED(DepthMask); + GET_LINKED(Disable); + GET_LINKED(DisableVertexAttribArray); + GET_LINKED(DrawArrays); + GET_LINKED(DrawElements); + GET_LINKED(Enable); + GET_LINKED(EnableVertexAttribArray); + GET_LINKED(Finish); + GET_LINKED(Flush); + GET_LINKED(FrontFace); + GET_LINKED(GenBuffers); + GET_LINKED(GenerateMipmap); + GET_LINKED(GenTextures); + GET_LINKED_SUFFIX(GenVertexArrays, OES); + GET_LINKED(GetBufferParameteriv); + GET_LINKED(GetError); + GET_LINKED(GetIntegerv); + GET_LINKED(GetProgramInfoLog); + GET_LINKED(GetProgramiv); + GET_LINKED(GetShaderInfoLog); + GET_LINKED(GetShaderiv); + GET_LINKED(GetString); +#if GL_ES_VERSION_3_0 + GET_LINKED(GetStringi); +#else + GET_PROC(GetStringi); +#endif + GET_LINKED(GetUniformLocation); + GET_LINKED(LineWidth); + GET_LINKED(LinkProgram); + GET_LINKED(PixelStorei); + GET_LINKED(ReadPixels); + GET_LINKED(Scissor); +#if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE + functions->fShaderSource = (GrGLShaderSourceProc) glShaderSource; +#else + GET_LINKED(ShaderSource); +#endif + GET_LINKED(StencilFunc); + GET_LINKED(StencilFuncSeparate); + GET_LINKED(StencilMask); + GET_LINKED(StencilMaskSeparate); + GET_LINKED(StencilOp); + GET_LINKED(StencilOpSeparate); + GET_LINKED(TexImage2D); + GET_LINKED(TexParameteri); + GET_LINKED(TexParameteriv); + GET_LINKED(TexSubImage2D); + + if (version >= GR_GL_VER(3,0)) { +#if GL_ES_VERSION_3_0 + GET_LINKED(TexStorage2D); +#else + GET_PROC(TexStorage2D); +#endif + } else { +#if GL_EXT_texture_storage + GET_LINKED_SUFFIX(TexStorage2D, EXT); +#else + GET_PROC_SUFFIX(TexStorage2D, EXT); +#endif + } + +#if GL_EXT_discard_framebuffer + GET_LINKED_SUFFIX(DiscardFramebuffer, EXT); +#endif + GET_LINKED(Uniform1f); + GET_LINKED(Uniform1i); + GET_LINKED(Uniform1fv); + GET_LINKED(Uniform1iv); + GET_LINKED(Uniform2f); + GET_LINKED(Uniform2i); + GET_LINKED(Uniform2fv); + GET_LINKED(Uniform2iv); + GET_LINKED(Uniform3f); + GET_LINKED(Uniform3i); + GET_LINKED(Uniform3fv); + GET_LINKED(Uniform3iv); + GET_LINKED(Uniform4f); + GET_LINKED(Uniform4i); + GET_LINKED(Uniform4fv); + GET_LINKED(Uniform4iv); + GET_LINKED(UniformMatrix2fv); + GET_LINKED(UniformMatrix3fv); + GET_LINKED(UniformMatrix4fv); + GET_LINKED(UseProgram); + GET_LINKED(VertexAttrib4fv); + GET_LINKED(VertexAttribPointer); + GET_LINKED(Viewport); + GET_LINKED(BindFramebuffer); + GET_LINKED(BindRenderbuffer); + GET_LINKED(CheckFramebufferStatus); + GET_LINKED(DeleteFramebuffers); + GET_LINKED(DeleteRenderbuffers); + GET_LINKED(FramebufferRenderbuffer); + GET_LINKED(FramebufferTexture2D); + + if (version >= GR_GL_VER(3,0)) { +#if GL_ES_VERSION_3_0 + GET_LINKED(RenderbufferStorageMultisample); + GET_LINKED(BlitFramebuffer); +#else + GET_PROC(RenderbufferStorageMultisample); + GET_PROC(BlitFramebuffer); +#endif + } + + if (extensions.has("GL_EXT_multisampled_render_to_texture")) { +#if GL_EXT_multisampled_render_to_texture + GET_LINKED_SUFFIX(FramebufferTexture2DMultisample, EXT); + functions->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleEXT; +#else + GET_PROC_SUFFIX(FramebufferTexture2DMultisample, EXT); + functions->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) get(ctx, "glRenderbufferStorageMultisampleEXT"); +#endif + } else if (extensions.has("GL_IMG_multisampled_render_to_texture")) { +#if GL_IMG_multisampled_render_to_texture + GET_LINKED_SUFFIX(FramebufferTexture2DMultisample, IMG); + functions->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleIMG; +#else + GET_PROC_SUFFIX(FramebufferTexture2DMultisample, IMG); + functions->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) get(ctx, "glRenderbufferStorageMultisampleIMG"); +#endif + } + + GET_LINKED(GenFramebuffers); + GET_LINKED(GenRenderbuffers); + GET_LINKED(GetFramebufferAttachmentParameteriv); + GET_LINKED(GetRenderbufferParameteriv); + GET_LINKED(RenderbufferStorage); + +#if GL_OES_mapbuffer + GET_LINKED_SUFFIX(MapBuffer, OES); + GET_LINKED_SUFFIX(UnmapBuffer, OES); +#else + GET_PROC_SUFFIX(MapBuffer, OES); + GET_PROC_SUFFIX(UnmapBuffer, OES); +#endif + + if (version >= GR_GL_VER(3,0)) { +#if GL_ES_VERSION_3_0 + GET_LINKED(MapBufferRange); + GET_LINKED(FlushMappedBufferRange); +#else + GET_PROC(MapBufferRange); + GET_PROC(FlushMappedBufferRange); +#endif + } else if (extensions.has("GL_EXT_map_buffer_range")) { +#if GL_EXT_map_buffer_range + GET_LINKED_SUFFIX(MapBufferRange, EXT); + GET_LINKED_SUFFIX(FlushMappedBufferRange, EXT); +#else + GET_PROC_SUFFIX(MapBufferRange, EXT); + GET_PROC_SUFFIX(FlushMappedBufferRange, EXT); +#endif + } + + if (extensions.has("GL_EXT_debug_marker")) { + GET_PROC(InsertEventMarker); + GET_PROC(PushGroupMarker); + GET_PROC(PopGroupMarker); + // The below check is here because a device has been found that has the extension string but + // returns NULL from the eglGetProcAddress for the functions + if (NULL == functions->fInsertEventMarker || + NULL == functions->fPushGroupMarker || + NULL == functions->fPopGroupMarker) { + extensions.remove("GL_EXT_debug_marker"); + } + } + +#if GL_ES_VERSION_3_0 + GET_LINKED(InvalidateFramebuffer); + GET_LINKED(InvalidateSubFramebuffer); +#else + GET_PROC(InvalidateFramebuffer); + GET_PROC(InvalidateSubFramebuffer); +#endif + GET_PROC(InvalidateBufferData); + GET_PROC(InvalidateBufferSubData); + GET_PROC(InvalidateTexImage); + GET_PROC(InvalidateTexSubImage); + + interface->fStandard = kGLES_GrGLStandard; + interface->fExtensions.swap(&extensions); + + return interface; +} diff --git a/src/gpu/gl/SkGLContextHelper.cpp b/src/gpu/gl/SkGLContextHelper.cpp index b06f755f67..2381a84519 100644 --- a/src/gpu/gl/SkGLContextHelper.cpp +++ b/src/gpu/gl/SkGLContextHelper.cpp @@ -27,13 +27,14 @@ SkGLContextHelper::~SkGLContextHelper() { SkSafeUnref(fGL); } -bool SkGLContextHelper::init(int width, int height) { +bool SkGLContextHelper::init(GrGLStandard forcedGpuAPI, int width, + int height) { if (fGL) { fGL->unref(); this->destroyGLContext(); } - fGL = this->createGLContext(); + fGL = this->createGLContext(forcedGpuAPI); if (fGL) { const GrGLubyte* temp; diff --git a/src/gpu/gl/SkNullGLContext.cpp b/src/gpu/gl/SkNullGLContext.cpp index 86c09b2045..576ee526f1 100644 --- a/src/gpu/gl/SkNullGLContext.cpp +++ b/src/gpu/gl/SkNullGLContext.cpp @@ -8,6 +8,9 @@ #include "gl/SkNullGLContext.h" -const GrGLInterface* SkNullGLContext::createGLContext() { +const GrGLInterface* SkNullGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + if (kGLES_GrGLStandard == forcedGpuAPI) { + return NULL; + } return GrGLCreateNullInterface(); }; diff --git a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp index 781e29bc9d..df212b1995 100644 --- a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp +++ b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp @@ -18,258 +18,29 @@ #include <EGL/egl.h> -static GrGLInterface* create_es_interface(GrGLVersion version, - GrGLExtensions* extensions) { - if (version < GR_GL_VER(2,0)) { - return NULL; - } - - GrGLInterface* interface = SkNEW(GrGLInterface); - interface->fStandard = kGLES_GrGLStandard; - GrGLInterface::Functions* functions = &interface->fFunctions; - - functions->fActiveTexture = glActiveTexture; - functions->fAttachShader = glAttachShader; - functions->fBindAttribLocation = glBindAttribLocation; - functions->fBindBuffer = glBindBuffer; - functions->fBindTexture = glBindTexture; - functions->fBindVertexArray = glBindVertexArrayOES; - functions->fBlendColor = glBlendColor; - functions->fBlendFunc = glBlendFunc; - functions->fBufferData = glBufferData; - functions->fBufferSubData = glBufferSubData; - functions->fClear = glClear; - functions->fClearColor = glClearColor; - functions->fClearStencil = glClearStencil; - functions->fColorMask = glColorMask; - functions->fCompileShader = glCompileShader; - functions->fCompressedTexImage2D = glCompressedTexImage2D; - functions->fCompressedTexSubImage2D = glCompressedTexSubImage2D; - functions->fCopyTexSubImage2D = glCopyTexSubImage2D; - functions->fCreateProgram = glCreateProgram; - functions->fCreateShader = glCreateShader; - functions->fCullFace = glCullFace; - functions->fDeleteBuffers = glDeleteBuffers; - functions->fDeleteProgram = glDeleteProgram; - functions->fDeleteShader = glDeleteShader; - functions->fDeleteTextures = glDeleteTextures; - functions->fDeleteVertexArrays = glDeleteVertexArraysOES; - functions->fDepthMask = glDepthMask; - functions->fDisable = glDisable; - functions->fDisableVertexAttribArray = glDisableVertexAttribArray; - functions->fDrawArrays = glDrawArrays; - functions->fDrawElements = glDrawElements; - functions->fEnable = glEnable; - functions->fEnableVertexAttribArray = glEnableVertexAttribArray; - functions->fFinish = glFinish; - functions->fFlush = glFlush; - functions->fFrontFace = glFrontFace; - functions->fGenBuffers = glGenBuffers; - functions->fGenerateMipmap = glGenerateMipmap; - functions->fGenTextures = glGenTextures; - functions->fGenVertexArrays = glGenVertexArraysOES; - functions->fGetBufferParameteriv = glGetBufferParameteriv; - functions->fGetError = glGetError; - functions->fGetIntegerv = glGetIntegerv; - functions->fGetProgramInfoLog = glGetProgramInfoLog; - functions->fGetProgramiv = glGetProgramiv; - functions->fGetShaderInfoLog = glGetShaderInfoLog; - functions->fGetShaderiv = glGetShaderiv; - functions->fGetString = glGetString; -#if GL_ES_VERSION_3_0 - functions->fGetStringi = glGetStringi; -#else - functions->fGetStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi"); -#endif - functions->fGetUniformLocation = glGetUniformLocation; - functions->fLineWidth = glLineWidth; - functions->fLinkProgram = glLinkProgram; - functions->fPixelStorei = glPixelStorei; - functions->fReadPixels = glReadPixels; - functions->fScissor = glScissor; -#if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE - functions->fShaderSource = (GrGLShaderSourceProc) glShaderSource; -#else - functions->fShaderSource = glShaderSource; -#endif - functions->fStencilFunc = glStencilFunc; - functions->fStencilFuncSeparate = glStencilFuncSeparate; - functions->fStencilMask = glStencilMask; - functions->fStencilMaskSeparate = glStencilMaskSeparate; - functions->fStencilOp = glStencilOp; - functions->fStencilOpSeparate = glStencilOpSeparate; - functions->fTexImage2D = glTexImage2D; - functions->fTexParameteri = glTexParameteri; - functions->fTexParameteriv = glTexParameteriv; - functions->fTexSubImage2D = glTexSubImage2D; - - if (version >= GR_GL_VER(3,0)) { -#if GL_ES_VERSION_3_0 - functions->fTexStorage2D = glTexStorage2D; -#else - functions->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2D"); -#endif - } else { -#if GL_EXT_texture_storage - functions->fTexStorage2D = glTexStorage2DEXT; -#else - functions->fTexStorage2D = (GrGLTexStorage2DProc) eglGetProcAddress("glTexStorage2DEXT"); -#endif - } - -#if GL_EXT_discard_framebuffer - functions->fDiscardFramebuffer = glDiscardFramebufferEXT; -#endif - functions->fUniform1f = glUniform1f; - functions->fUniform1i = glUniform1i; - functions->fUniform1fv = glUniform1fv; - functions->fUniform1iv = glUniform1iv; - functions->fUniform2f = glUniform2f; - functions->fUniform2i = glUniform2i; - functions->fUniform2fv = glUniform2fv; - functions->fUniform2iv = glUniform2iv; - functions->fUniform3f = glUniform3f; - functions->fUniform3i = glUniform3i; - functions->fUniform3fv = glUniform3fv; - functions->fUniform3iv = glUniform3iv; - functions->fUniform4f = glUniform4f; - functions->fUniform4i = glUniform4i; - functions->fUniform4fv = glUniform4fv; - functions->fUniform4iv = glUniform4iv; - functions->fUniformMatrix2fv = glUniformMatrix2fv; - functions->fUniformMatrix3fv = glUniformMatrix3fv; - functions->fUniformMatrix4fv = glUniformMatrix4fv; - functions->fUseProgram = glUseProgram; - functions->fVertexAttrib4fv = glVertexAttrib4fv; - functions->fVertexAttribPointer = glVertexAttribPointer; - functions->fViewport = glViewport; - functions->fBindFramebuffer = glBindFramebuffer; - functions->fBindRenderbuffer = glBindRenderbuffer; - functions->fCheckFramebufferStatus = glCheckFramebufferStatus; - functions->fDeleteFramebuffers = glDeleteFramebuffers; - functions->fDeleteRenderbuffers = glDeleteRenderbuffers; - functions->fFramebufferRenderbuffer = glFramebufferRenderbuffer; - functions->fFramebufferTexture2D = glFramebufferTexture2D; - - if (version >= GR_GL_VER(3,0)) { -#if GL_ES_VERSION_3_0 - functions->fRenderbufferStorageMultisample = glRenderbufferStorageMultisample; - functions->fBlitFramebuffer = glBlitFramebuffer; -#else - functions->fRenderbufferStorageMultisample = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisample"); - functions->fBlitFramebuffer = (GrGLBlitFramebufferProc) eglGetProcAddress("glBlitFramebuffer"); -#endif - } - - if (extensions->has("GL_EXT_multisampled_render_to_texture")) { -#if GL_EXT_multisampled_render_to_texture - functions->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleEXT; - functions->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleEXT; -#else - functions->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleEXT"); - functions->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleEXT"); -#endif - } else if (extensions->has("GL_IMG_multisampled_render_to_texture")) { -#if GL_IMG_multisampled_render_to_texture - functions->fFramebufferTexture2DMultisample = glFramebufferTexture2DMultisampleIMG; - functions->fRenderbufferStorageMultisampleES2EXT = glRenderbufferStorageMultisampleIMG; -#else - functions->fFramebufferTexture2DMultisample = (GrGLFramebufferTexture2DMultisampleProc) eglGetProcAddress("glFramebufferTexture2DMultisampleIMG"); - functions->fRenderbufferStorageMultisampleES2EXT = (GrGLRenderbufferStorageMultisampleProc) eglGetProcAddress("glRenderbufferStorageMultisampleIMG"); -#endif - } - - functions->fGenFramebuffers = glGenFramebuffers; - functions->fGenRenderbuffers = glGenRenderbuffers; - functions->fGetFramebufferAttachmentParameteriv = glGetFramebufferAttachmentParameteriv; - functions->fGetRenderbufferParameteriv = glGetRenderbufferParameteriv; - functions->fRenderbufferStorage = glRenderbufferStorage; +#define GET_PROC(F) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F) +#define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S) +#define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F) -#if GL_OES_mapbuffer - functions->fMapBuffer = glMapBufferOES; - functions->fUnmapBuffer = glUnmapBufferOES; -#else - functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES"); - functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES"); +#define GET_LINKED(F) functions->f ## F = gl ## F +#define GET_LINKED_SUFFIX(F, S) functions->f ## F = gl ## F ##S -#endif - - if (version >= GR_GL_VER(3,0)) { -#if GL_ES_VERSION_3_0 - functions->fMapBufferRange = glMapBufferRange; - functions->fFlushMappedBufferRange = glFlushMappedBufferRange; -#else - functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRange"); - functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRange"); -#endif - } else if (extensions->has("GL_EXT_map_buffer_range")) { -#if GL_EXT_map_buffer_range - functions->fMapBufferRange = glMapBufferRangeEXT; - functions->fFlushMappedBufferRange = glFlushMappedBufferRangeEXT; -#else - functions->fMapBufferRange = (GrGLMapBufferRangeProc) eglGetProcAddress("glMapBufferRangeEXT"); - functions->fFlushMappedBufferRange = (GrGLFlushMappedBufferRangeProc) eglGetProcAddress("glFlushMappedBufferRangeEXT"); -#endif - } - - if (extensions->has("GL_EXT_debug_marker")) { - functions->fInsertEventMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glInsertEventMarker"); - functions->fPushGroupMarker = (GrGLInsertEventMarkerProc) eglGetProcAddress("glPushGroupMarker"); - functions->fPopGroupMarker = (GrGLPopGroupMarkerProc) eglGetProcAddress("glPopGroupMarker"); - // The below check is here because a device has been found that has the extension string but - // returns NULL from the eglGetProcAddress for the functions - if (NULL == functions->fInsertEventMarker || - NULL == functions->fPushGroupMarker || - NULL == functions->fPopGroupMarker) { - extensions->remove("GL_EXT_debug_marker"); - } - } - -#if GL_ES_VERSION_3_0 - functions->fInvalidateFramebuffer = glInvalidateFramebuffer; - functions->fInvalidateSubFramebuffer = glInvalidateSubFramebuffer; -#else - functions->fInvalidateFramebuffer = (GrGLInvalidateFramebufferProc) eglGetProcAddress("glInvalidateFramebuffer"); - functions->fInvalidateSubFramebuffer = (GrGLInvalidateSubFramebufferProc) eglGetProcAddress("glInvalidateSubFramebuffer"); -#endif - functions->fInvalidateBufferData = (GrGLInvalidateBufferDataProc) eglGetProcAddress("glInvalidateBufferData"); - functions->fInvalidateBufferSubData = (GrGLInvalidateBufferSubDataProc) eglGetProcAddress("glInvalidateBufferSubData"); - functions->fInvalidateTexImage = (GrGLInvalidateTexImageProc) eglGetProcAddress("glInvalidateTexImage"); - functions->fInvalidateTexSubImage = (GrGLInvalidateTexSubImageProc) eglGetProcAddress("glInvalidateTexSubImage"); - - return interface; -} +#include "gl/GrGLAssembleGLESInterface.h" static GrGLFuncPtr android_get_gl_proc(void* ctx, const char name[]) { SkASSERT(NULL == ctx); return eglGetProcAddress(name); } -static const GrGLInterface* create_desktop_interface() { - return GrGLAssembleGLInterface(NULL, android_get_gl_proc); -} - const GrGLInterface* GrGLCreateNativeInterface() { const char* verStr = reinterpret_cast<const char*>(glGetString(GR_GL_VERSION)); GrGLStandard standard = GrGLGetStandardInUseFromString(verStr); if (kGLES_GrGLStandard == standard) { - GrGLVersion version = GrGLGetVersionFromString(verStr); - GrGLExtensions extensions; - GrGLGetStringiProc getStringi = (GrGLGetStringiProc) eglGetProcAddress("glGetStringi"); - if (!extensions.init(standard, glGetString, getStringi, glGetIntegerv)) { - return NULL; - } - GrGLInterface* interface = create_es_interface(version, &extensions); - - if (NULL != interface) { - interface->fExtensions.swap(&extensions); - } - - return interface; + return GrGLAssembleGLESInterface(NULL, android_get_gl_proc); } else if (kGL_GrGLStandard == standard) { - return create_desktop_interface(); + return GrGLAssembleGLInterface(NULL, android_get_gl_proc); } return NULL; diff --git a/src/gpu/gl/android/SkNativeGLContext_android.cpp b/src/gpu/gl/android/SkNativeGLContext_android.cpp index 462109a6c4..705bd8f49c 100644 --- a/src/gpu/gl/android/SkNativeGLContext_android.cpp +++ b/src/gpu/gl/android/SkNativeGLContext_android.cpp @@ -51,7 +51,7 @@ void SkNativeGLContext::destroyGLContext() { } } -const GrGLInterface* SkNativeGLContext::createGLContext() { +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { static const EGLint kEGLContextAttribsForOpenGL[] = { EGL_NONE }; @@ -81,9 +81,18 @@ const GrGLInterface* SkNativeGLContext::createGLContext() { }, }; + size_t apiLimit = SK_ARRAY_COUNT(kAPIs); + size_t api = 0; + if (forcedGpuAPI == kGL_GrGLStandard) { + apiLimit = 1; + } else if (forcedGpuAPI == kGLES_GrGLStandard) { + api = 1; + } + SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI); + const GrGLInterface* interface = NULL; - for (size_t api = 0; NULL == interface && api < SK_ARRAY_COUNT(kAPIs); ++api) { + for (size_t i = 0; NULL == interface && i < apiLimit; ++api) { fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint majorVersion; diff --git a/src/gpu/gl/angle/SkANGLEGLContext.cpp b/src/gpu/gl/angle/SkANGLEGLContext.cpp index 2600ec4634..884fe7ca11 100644 --- a/src/gpu/gl/angle/SkANGLEGLContext.cpp +++ b/src/gpu/gl/angle/SkANGLEGLContext.cpp @@ -52,7 +52,10 @@ void SkANGLEGLContext::destroyGLContext() { } } -const GrGLInterface* SkANGLEGLContext::createGLContext() { +const GrGLInterface* SkANGLEGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + if (kGL_GrGLStandard == forcedGpuAPI) { + return NULL; + } fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); diff --git a/src/gpu/gl/debug/SkDebugGLContext.cpp b/src/gpu/gl/debug/SkDebugGLContext.cpp index ae42227251..93c0b30b8b 100644 --- a/src/gpu/gl/debug/SkDebugGLContext.cpp +++ b/src/gpu/gl/debug/SkDebugGLContext.cpp @@ -8,6 +8,10 @@ #include "gl/SkDebugGLContext.h" -const GrGLInterface* SkDebugGLContext::createGLContext() { +const GrGLInterface* SkDebugGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + if (kGLES_GrGLStandard == forcedGpuAPI) { + return NULL; + } + return GrGLCreateDebugInterface(); }; diff --git a/src/gpu/gl/iOS/SkNativeGLContext_iOS.mm b/src/gpu/gl/iOS/SkNativeGLContext_iOS.mm index a276fd05da..1e11c0deb7 100644 --- a/src/gpu/gl/iOS/SkNativeGLContext_iOS.mm +++ b/src/gpu/gl/iOS/SkNativeGLContext_iOS.mm @@ -42,7 +42,11 @@ void SkNativeGLContext::destroyGLContext() { [EAGLCTX release]; } -const GrGLInterface* SkNativeGLContext::createGLContext() { +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + if (kGL_GrGLStandard == forcedGpuAPI) { + return NULL; + } + fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; [EAGLContext setCurrentContext:EAGLCTX]; @@ -61,4 +65,4 @@ void SkNativeGLContext::makeCurrent() const { } } -void SkNativeGLContext::swapBuffers() const { }
\ No newline at end of file +void SkNativeGLContext::swapBuffers() const { } diff --git a/src/gpu/gl/mac/SkNativeGLContext_mac.cpp b/src/gpu/gl/mac/SkNativeGLContext_mac.cpp index df316d7ed1..fefbb4c12b 100644 --- a/src/gpu/gl/mac/SkNativeGLContext_mac.cpp +++ b/src/gpu/gl/mac/SkNativeGLContext_mac.cpp @@ -32,8 +32,11 @@ void SkNativeGLContext::destroyGLContext() { } } -const GrGLInterface* SkNativeGLContext::createGLContext() { +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { SkASSERT(NULL == fContext); + if (kGLES_GrGLStandard == forcedGpuAPI) { + return NULL; + } CGLPixelFormatAttribute attributes[] = { #if MAC_OS_X_VERSION_10_7 diff --git a/src/gpu/gl/mesa/SkMesaGLContext.cpp b/src/gpu/gl/mesa/SkMesaGLContext.cpp index 0199d12c19..58e325dfeb 100644 --- a/src/gpu/gl/mesa/SkMesaGLContext.cpp +++ b/src/gpu/gl/mesa/SkMesaGLContext.cpp @@ -53,7 +53,11 @@ void SkMesaGLContext::destroyGLContext() { static const GrGLint gBOGUS_SIZE = 16; -const GrGLInterface* SkMesaGLContext::createGLContext() { +const GrGLInterface* SkMesaGLContext::createGLContext(GrGLStandard forcedGpuAPI) { + if (kGLES_GrGLStandard == forcedGpuAPI) { + return NULL; + } + /* Create an RGBA-mode context */ #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 /* specify Z, stencil, accum sizes */ diff --git a/src/gpu/gl/nacl/SkNativeGLContext_nacl.cpp b/src/gpu/gl/nacl/SkNativeGLContext_nacl.cpp index 69a74caf8a..334be1d954 100644 --- a/src/gpu/gl/nacl/SkNativeGLContext_nacl.cpp +++ b/src/gpu/gl/nacl/SkNativeGLContext_nacl.cpp @@ -26,7 +26,7 @@ SkNativeGLContext::~SkNativeGLContext() { void SkNativeGLContext::destroyGLContext() { } -const GrGLInterface* SkNativeGLContext::createGLContext() { +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { return NULL; } diff --git a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp index ddbfe5de29..b3c7a3c5a9 100644 --- a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp +++ b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp @@ -8,9 +8,19 @@ #include "gl/GrGLInterface.h" #include "gl/GrGLAssembleInterface.h" +#include "gl/GrGLUtil.h" #include <GL/glx.h> +#define GET_PROC(F) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F) +#define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S) +#define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F) + +#define GET_LINKED GET_PROC +#define GET_LINKED_SUFFIX GET_PROC_SUFFIX + +#include "gl/GrGLAssembleGLESInterface.h" + static GrGLFuncPtr glx_get(void* ctx, const char name[]) { SkASSERT(NULL == ctx); SkASSERT(NULL != glXGetCurrentContext()); @@ -21,5 +31,14 @@ const GrGLInterface* GrGLCreateNativeInterface() { if (NULL == glXGetCurrentContext()) { return NULL; } - return GrGLAssembleGLInterface(NULL, glx_get); + + const char* verStr = reinterpret_cast<const char*>(glGetString(GR_GL_VERSION)); + GrGLStandard standard = GrGLGetStandardInUseFromString(verStr); + + if (kGLES_GrGLStandard == standard) { + return GrGLAssembleGLESInterface(NULL, glx_get); + } else if (kGL_GrGLStandard == standard) { + return GrGLAssembleGLInterface(NULL, glx_get); + } + return NULL; } diff --git a/src/gpu/gl/unix/SkNativeGLContext_unix.cpp b/src/gpu/gl/unix/SkNativeGLContext_unix.cpp index c4bd6f937d..4da1eb2f4f 100644 --- a/src/gpu/gl/unix/SkNativeGLContext_unix.cpp +++ b/src/gpu/gl/unix/SkNativeGLContext_unix.cpp @@ -66,7 +66,7 @@ void SkNativeGLContext::destroyGLContext() { } } -const GrGLInterface* SkNativeGLContext::createGLContext() { +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { fDisplay = XOpenDisplay(0); if (!fDisplay) { @@ -187,60 +187,68 @@ const GrGLInterface* SkNativeGLContext::createGLContext() { const char *glxExts = glXQueryExtensionsString( fDisplay, DefaultScreen(fDisplay) ); + + // Check for the GLX_ARB_create_context extension string and the function. // If either is not present, use GLX 1.3 context creation method. - if (!gluCheckExtension( - reinterpret_cast<const GLubyte*>("GLX_ARB_create_context") - , reinterpret_cast<const GLubyte*>(glxExts))) - { - //SkDebugf("GLX_ARB_create_context not found." - // " Using old-style GLX context.\n"); + + if (!gluCheckExtension(reinterpret_cast<const GLubyte*>("GLX_ARB_create_context"), + reinterpret_cast<const GLubyte*>(glxExts))) { + if (kGLES_GrGLStandard != forcedGpuAPI) { #ifdef GLX_1_3 - fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); + fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True); #else - fContext = glXCreateContext(fDisplay, vi, 0, True); + fContext = glXCreateContext(fDisplay, vi, 0, True); #endif - + } } #ifdef GLX_1_3 else { //SkDebugf("Creating context.\n"); - PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((GrGLubyte*)"glXCreateContextAttribsARB"); - int context_attribs[] = { + + static const int context_attribs_gl[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 0, - //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; - fContext = glXCreateContextAttribsARB( - fDisplay, bestFbc, 0, True, context_attribs - ); - - // Sync to ensure any errors generated are processed. - XSync(fDisplay, False); - if (!ctxErrorOccurred && fContext) { - //SkDebugf( "Created GL 3.0 context.\n" ); + static const int context_attribs_gl_fallback[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 1, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + None + }; + static const int context_attribs_gles[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + None + }; + + if (kGLES_GrGLStandard == forcedGpuAPI) { + if (gluCheckExtension( + reinterpret_cast<const GLubyte*>("GLX_EXT_create_context_es2_profile"), + reinterpret_cast<const GLubyte*>(glxExts))) { + fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, + context_attribs_gles); + } } else { - // Couldn't create GL 3.0 context. - // Fall back to old-style 2.x context. - // When a context version below 3.0 is requested, - // implementations will return the newest context version compatible - // with OpenGL versions less than version 3.0. - - // GLX_CONTEXT_MAJOR_VERSION_ARB = 1 - context_attribs[1] = 1; - // GLX_CONTEXT_MINOR_VERSION_ARB = 0 - context_attribs[3] = 0; - - ctxErrorOccurred = false; - - //SkDebugf("Failed to create GL 3.0 context." - // " Using old-style GLX context.\n"); - fContext = glXCreateContextAttribsARB( - fDisplay, bestFbc, 0, True, context_attribs - ); + fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, context_attribs_gl); + + // Sync to ensure any errors generated are processed. + XSync(fDisplay, False); + if (ctxErrorOccurred || !fContext) { + // Couldn't create GL 3.0 context. + // Fall back to old-style 2.x context. + // When a context version below 3.0 is requested, + // implementations will return the newest context version + // compatible with OpenGL versions less than version 3.0. + + ctxErrorOccurred = false; + + fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, + context_attribs_gl_fallback); + } } } #endif diff --git a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp index 6adaf1964f..d63dfbbcd6 100644 --- a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp +++ b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp @@ -8,9 +8,21 @@ #include "gl/GrGLInterface.h" #include "gl/GrGLAssembleInterface.h" +#include "gl/GrGLUtil.h" #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <GL/gl.h> + +#define GET_PROC(F) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F) +#define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S) +#define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F) + +#define GET_LINKED GET_PROC +#define GET_LINKED_SUFFIX GET_PROC_SUFFIX + +#include "gl/GrGLAssembleGLESInterface.h" + class AutoLibraryUnload { public: AutoLibraryUnload(const char* moduleName) { @@ -70,5 +82,13 @@ const GrGLInterface* GrGLCreateNativeInterface() { return NULL; } - return GrGLAssembleGLInterface(&getter, win_get_gl_proc); + const char* verStr = reinterpret_cast<const char*>(glGetString(GR_GL_VERSION)); + GrGLStandard standard = GrGLGetStandardInUseFromString(verStr); + + if (kGLES_GrGLStandard == standard) { + return GrGLAssembleGLESInterface(&getter, win_get_gl_proc); + } else if (kGL_GrGLStandard == standard) { + return GrGLAssembleGLInterface(&getter, win_get_gl_proc); + } + return NULL; } diff --git a/src/gpu/gl/win/SkNativeGLContext_win.cpp b/src/gpu/gl/win/SkNativeGLContext_win.cpp index bae97a780c..f085fdc6ee 100644 --- a/src/gpu/gl/win/SkNativeGLContext_win.cpp +++ b/src/gpu/gl/win/SkNativeGLContext_win.cpp @@ -47,7 +47,7 @@ void SkNativeGLContext::destroyGLContext() { } } -const GrGLInterface* SkNativeGLContext::createGLContext() { +const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) { HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL); if (!gWC) { @@ -85,9 +85,13 @@ const GrGLInterface* SkNativeGLContext::createGLContext() { this->destroyGLContext(); return NULL; } + // Requesting a Core profile would bar us from using NVPR. So we request + // compatibility profile or GL ES. + SkWGLContextRequest contextType = + kGLES_GrGLStandard == forcedGpuAPI ? + kGLES_SkWGLContextRequest : kGLPreferCompatibilityProfile_SkWGLContextRequest; - // Requesting a Core profile would bar us from using NVPR. So we pass false. - if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false))) { + if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, contextType))) { SkDebugf("Could not create rendering context.\n"); this->destroyGLContext(); return NULL; diff --git a/src/utils/win/SkWGL_win.cpp b/src/utils/win/SkWGL_win.cpp index 3b1966dae8..a8552a8ea3 100644 --- a/src/utils/win/SkWGL_win.cpp +++ b/src/utils/win/SkWGL_win.cpp @@ -245,7 +245,7 @@ SkWGLExtensions::SkWGLExtensions() wglMakeCurrent(prevDC, prevGLRC); } -HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile) { +HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, SkWGLContextRequest contextType) { SkWGLExtensions extensions; if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) { return NULL; @@ -307,27 +307,44 @@ HGLRC SkCreateWGLContext(HDC dc, int msaaSampleCount, bool preferCoreProfile) { } HGLRC glrc = NULL; - if (preferCoreProfile && extensions.hasExtension(dc, "WGL_ARB_create_context")) { - static const int kCoreGLVersions[] = { - 4, 3, - 4, 2, - 4, 1, - 4, 0, - 3, 3, - 3, 2, - }; - int coreProfileAttribs[] = { - SK_WGL_CONTEXT_MAJOR_VERSION, -1, - SK_WGL_CONTEXT_MINOR_VERSION, -1, - SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT, + if (kGLES_SkWGLContextRequest == contextType) { + if (!extensions.hasExtension(dc, "WGL_EXT_create_context_es2_profile")) { + return NULL; + } + static const int glesAttribs[] = { + SK_WGL_CONTEXT_MAJOR_VERSION, 3, + SK_WGL_CONTEXT_MINOR_VERSION, 0, + SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_ES2_PROFILE_BIT, 0, }; - for (int v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) { - coreProfileAttribs[1] = kCoreGLVersions[2 * v]; - coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1]; - glrc = extensions.createContextAttribs(dc, NULL, coreProfileAttribs); - if (NULL != glrc) { - break; + glrc = extensions.createContextAttribs(dc, NULL, glesAttribs); + if (NULL == glrc) { + return NULL; + } + } else { + if (kGLPreferCoreProfile_SkWGLContextRequest == contextType && + extensions.hasExtension(dc, "WGL_ARB_create_context")) { + static const int kCoreGLVersions[] = { + 4, 3, + 4, 2, + 4, 1, + 4, 0, + 3, 3, + 3, 2, + }; + int coreProfileAttribs[] = { + SK_WGL_CONTEXT_MAJOR_VERSION, -1, + SK_WGL_CONTEXT_MINOR_VERSION, -1, + SK_WGL_CONTEXT_PROFILE_MASK, SK_WGL_CONTEXT_CORE_PROFILE_BIT, + 0, + }; + for (int v = 0; v < SK_ARRAY_COUNT(kCoreGLVersions) / 2; ++v) { + coreProfileAttribs[1] = kCoreGLVersions[2 * v]; + coreProfileAttribs[3] = kCoreGLVersions[2 * v + 1]; + glrc = extensions.createContextAttribs(dc, NULL, coreProfileAttribs); + if (NULL != glrc) { + break; + } } } } diff --git a/src/views/win/SkOSWindow_win.cpp b/src/views/win/SkOSWindow_win.cpp index 027bc66757..1b47dea329 100644 --- a/src/views/win/SkOSWindow_win.cpp +++ b/src/views/win/SkOSWindow_win.cpp @@ -331,7 +331,8 @@ void SkEvent::SignalQueueTimer(SkMSec delay) bool SkOSWindow::attachGL(int msaaSampleCount, AttachmentInfo* info) { HDC dc = GetDC((HWND)fHWND); if (NULL == fHGLRC) { - fHGLRC = SkCreateWGLContext(dc, msaaSampleCount, false); + fHGLRC = SkCreateWGLContext(dc, msaaSampleCount, + kGLPreferCompatibilityProfile_SkWGLContextRequest); if (NULL == fHGLRC) { return false; } diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h index 13b60ecb09..12ed32e070 100644 --- a/tools/PictureRenderer.h +++ b/tools/PictureRenderer.h @@ -163,7 +163,11 @@ public: /** * Set the backend type. Returns true on success and false on failure. */ +#if SK_SUPPORT_GPU + bool setDeviceType(SkDeviceTypes deviceType, GrGLStandard gpuAPI = kNone_GrGLStandard) { +#else bool setDeviceType(SkDeviceTypes deviceType) { +#endif fDeviceType = deviceType; #if SK_SUPPORT_GPU // In case this function is called more than once @@ -198,7 +202,7 @@ public: return false; } #if SK_SUPPORT_GPU - fGrContext = fGrContextFactory.get(glContextType); + fGrContext = fGrContextFactory.get(glContextType, gpuAPI); if (NULL == fGrContext) { return false; } else { diff --git a/tools/PictureRenderingFlags.cpp b/tools/PictureRenderingFlags.cpp index 3e7821819f..ccec158f95 100644 --- a/tools/PictureRenderingFlags.cpp +++ b/tools/PictureRenderingFlags.cpp @@ -26,6 +26,8 @@ DEFINE_string(bbh, "none", "bbhType [width height]: Set the bounding box hierarc #if SK_SUPPORT_GPU +static const char kGpuAPINameGL[] = "gl"; +static const char kGpuAPINameGLES[] = "gles"; #define GPU_CONFIG_STRING "|gpu|msaa4|msaa16|nvprmsaa4|nvprmsaa16" #else #define GPU_CONFIG_STRING "" @@ -72,6 +74,12 @@ DEFINE_double(scale, 1, "Set the scale factor."); DEFINE_string(tiles, "", "Used with --mode copyTile to specify number of tiles per larger tile " "in the x and y directions."); DEFINE_string(viewport, "", "width height: Set the viewport."); +#if SK_SUPPORT_GPU +DEFINE_string(gpuAPI, "", "Force use of specific gpu API. Using \"gl\" " + "forces OpenGL API. Using \"gles\" forces OpenGL ES API. " + "Defaults to empty string, which selects the API native to the " + "system."); +#endif sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) { error.reset(); @@ -244,6 +252,21 @@ sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) { sk_tools::PictureRenderer::SkDeviceTypes deviceType = sk_tools::PictureRenderer::kBitmap_DeviceType; #if SK_SUPPORT_GPU + GrGLStandard gpuAPI = kNone_GrGLStandard; + if (1 == FLAGS_gpuAPI.count()) { + if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) { + gpuAPI = kGL_GrGLStandard; + } else if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) { + gpuAPI = kGLES_GrGLStandard; + } else { + error.printf("--gpuAPI invalid api value.\n"); + return NULL; + } + } else if (FLAGS_gpuAPI.count() > 1) { + error.printf("--gpuAPI invalid api value.\n"); + return NULL; + } + int sampleCount = 0; #endif if (FLAGS_config.count() > 0) { @@ -285,7 +308,14 @@ sk_tools::PictureRenderer* parseRenderer(SkString& error, PictureTool tool) { error.printf("%s is not a valid mode for --config\n", FLAGS_config[0]); return NULL; } - renderer->setDeviceType(deviceType); +#if SK_SUPPORT_GPU + if (!renderer->setDeviceType(deviceType, gpuAPI)) { +#else + if (!renderer->setDeviceType(deviceType)) { +#endif + error.printf("Could not create backend for --config %s\n", FLAGS_config[0]); + return NULL; + } #if SK_SUPPORT_GPU renderer->setSampleCount(sampleCount); #endif |