Support using OpenGL ES context on desktop
Support using OpenGL ES context on desktop for unix and Android platforms. This
is mainly useful in development.
Add --gpuAPI flag to gm, dm, bench, bench_pictures and render_pictures. The
possible parameters for the flag are "gl" and "gles".
R=bsalomon@google.com, mtklein@google.com, robertphillips@google.com
Author: kkinnunen@nvidia.com
Review URL: https://codereview.chromium.org/319043005
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 5c3b790..016ad2d 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -50,6 +50,11 @@
static const char kDefaultsConfigStr[] = "defaults";
+#if SK_SUPPORT_GPU
+static const char kGpuAPINameGL[] = "gl";
+static const char kGpuAPINameGLES[] = "gles";
+#endif
+
///////////////////////////////////////////////////////////////////////////////
class Iter {
@@ -227,6 +232,10 @@
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.");
@@ -348,11 +357,24 @@
}
#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);
@@ -412,7 +434,7 @@
if (Benchmark::kGPU_Backend != config.backend) {
continue;
}
- GrContext* context = gContextFactory.get(config.contextType);
+ GrContext* context = gContextFactory.get(config.contextType, gpuAPI);
if (NULL == context) {
continue;
}
@@ -458,7 +480,7 @@
#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;
}
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 2981013..2e7966e 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -37,8 +37,15 @@
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 @@
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 @@
}
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_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 @@
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 @@
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 @@
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 @@
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 7cd2fdc..9bdbbf2 100644
--- a/dm/DMBenchTask.cpp
+++ b/dm/DMBenchTask.cpp
@@ -33,11 +33,13 @@
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 @@
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 3c71cd7..d2b5800 100644
--- a/dm/DMBenchTask.h
+++ b/dm/DMBenchTask.h
@@ -46,6 +46,7 @@
TaskRunner*,
BenchRegistry::Factory,
GrContextFactory::GLContextType,
+ GrGLStandard gpuAPI,
int sampleCount);
virtual void draw(GrContextFactory*) SK_OVERRIDE;
@@ -56,6 +57,7 @@
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 b384485..4c44fae 100644
--- a/dm/DMGpuGMTask.cpp
+++ b/dm/DMGpuGMTask.cpp
@@ -15,12 +15,14 @@
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 @@
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 6621a498..46b4c98 100644
--- a/dm/DMGpuGMTask.h
+++ b/dm/DMGpuGMTask.h
@@ -23,6 +23,7 @@
skiagm::GMRegistry::Factory,
const Expectations&,
GrContextFactory::GLContextType,
+ GrGLStandard gpuAPI,
int sampleCount);
virtual void draw(GrContextFactory*) SK_OVERRIDE;
@@ -34,6 +35,7 @@
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 46896b4..bcc00c2 100644
--- a/dm/DMGpuSupport.h
+++ b/dm/DMGpuSupport.h
@@ -19,9 +19,10 @@
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 @@
// 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 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 2f1a055..c1b0284 100644
--- a/experimental/PdfViewer/pdf_viewer_main.cpp
+++ b/experimental/PdfViewer/pdf_viewer_main.cpp
@@ -168,7 +168,8 @@
#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 364e771..96a3454 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -67,6 +67,7 @@
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 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_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 @@
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 @@
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 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 @@
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 @@
}
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 @@
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 @@
!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 @@
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 @@
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 @@
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 f09bad9..1f1f89d 100644
--- a/include/gpu/GrContextFactory.h
+++ b/include/gpu/GrContextFactory.h
@@ -88,8 +88,7 @@
}
}
- GrContextFactory() {
- }
+ GrContextFactory() { }
~GrContextFactory() { this->destroyContexts(); }
@@ -105,9 +104,12 @@
/**
* 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 @@
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 99ef4e9..c5f62ff 100644
--- a/include/gpu/gl/SkANGLEGLContext.h
+++ b/include/gpu/gl/SkANGLEGLContext.h
@@ -36,7 +36,8 @@
};
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 545ef40..9318cb4 100644
--- a/include/gpu/gl/SkDebugGLContext.h
+++ b/include/gpu/gl/SkDebugGLContext.h
@@ -19,7 +19,7 @@
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 ea940c8..9da8741 100644
--- a/include/gpu/gl/SkGLContextHelper.h
+++ b/include/gpu/gl/SkGLContextHelper.h
@@ -25,7 +25,7 @@
/**
* 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 @@
* 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 55235fa..28349dd 100644
--- a/include/gpu/gl/SkMesaGLContext.h
+++ b/include/gpu/gl/SkMesaGLContext.h
@@ -38,7 +38,7 @@
};
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 7254de1..fac52b3 100644
--- a/include/gpu/gl/SkNativeGLContext.h
+++ b/include/gpu/gl/SkNativeGLContext.h
@@ -58,7 +58,7 @@
};
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 02d968e..6c2a1d7 100644
--- a/include/gpu/gl/SkNullGLContext.h
+++ b/include/gpu/gl/SkNullGLContext.h
@@ -20,7 +20,7 @@
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 5f630a1..5272f17 100644
--- a/include/utils/SkWGL.h
+++ b/include/utils/SkWGL.h
@@ -104,12 +104,22 @@
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 0000000..ddbc980
--- /dev/null
+++ b/src/gpu/gl/GrGLAssembleGLESInterface.h
@@ -0,0 +1,240 @@
+
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) {
+ GET_PROC_LOCAL(GetString);
+ const char* verStr = reinterpret_cast<const char*>(GetString(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, GetString, 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 USE_LINKED && 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 USE_LINKED && GL_ES_VERSION_3_0
+ GET_LINKED(TexStorage2D);
+#else
+ GET_PROC(TexStorage2D);
+#endif
+ } else {
+#if USE_LINKED && GL_EXT_texture_storage
+ GET_LINKED_SUFFIX(TexStorage2D, EXT);
+#else
+ GET_PROC_SUFFIX(TexStorage2D, EXT);
+#endif
+ }
+
+#if USE_LINKED && 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 USE_LINKED && 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 USE_LINKED && 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 USE_LINKED && 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 USE_LINKED && 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 USE_LINKED && 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 USE_LINKED && 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 USE_LINKED && 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/GrGLAssembleInterface.h b/src/gpu/gl/GrGLAssembleInterface.h
index 36a4513..4bd8836 100644
--- a/src/gpu/gl/GrGLAssembleInterface.h
+++ b/src/gpu/gl/GrGLAssembleInterface.h
@@ -16,3 +16,10 @@
* get() to get each function address. ctx is a generic ptr passed to and interpreted by get().
*/
const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get);
+
+/**
+ * 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().
+ */
+const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get);
diff --git a/src/gpu/gl/SkGLContextHelper.cpp b/src/gpu/gl/SkGLContextHelper.cpp
index b06f755..2381a84 100644
--- a/src/gpu/gl/SkGLContextHelper.cpp
+++ b/src/gpu/gl/SkGLContextHelper.cpp
@@ -27,13 +27,14 @@
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 86c09b2..576ee52 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 781e29b..ba1c4be 100644
--- a/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
+++ b/src/gpu/gl/android/GrGLCreateNativeInterface_android.cpp
@@ -18,258 +18,30 @@
#include <EGL/egl.h>
-static GrGLInterface* create_es_interface(GrGLVersion version,
- GrGLExtensions* extensions) {
- if (version < GR_GL_VER(2,0)) {
- return NULL;
- }
+#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)
- GrGLInterface* interface = SkNEW(GrGLInterface);
- interface->fStandard = kGLES_GrGLStandard;
- GrGLInterface::Functions* functions = &interface->fFunctions;
+#define GET_LINKED(F) functions->f ## F = gl ## F
+#define GET_LINKED_SUFFIX(F, S) functions->f ## F = gl ## F ##S
+#define USE_LINKED 1
- 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;
-
-#if GL_OES_mapbuffer
- functions->fMapBuffer = glMapBufferOES;
- functions->fUnmapBuffer = glUnmapBufferOES;
-#else
- functions->fMapBuffer = (GrGLMapBufferProc) eglGetProcAddress("glMapBufferOES");
- functions->fUnmapBuffer = (GrGLUnmapBufferProc) eglGetProcAddress("glUnmapBufferOES");
-
-#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 462109a..705bd8f 100644
--- a/src/gpu/gl/android/SkNativeGLContext_android.cpp
+++ b/src/gpu/gl/android/SkNativeGLContext_android.cpp
@@ -51,7 +51,7 @@
}
}
-const GrGLInterface* SkNativeGLContext::createGLContext() {
+const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) {
static const EGLint kEGLContextAttribsForOpenGL[] = {
EGL_NONE
};
@@ -81,9 +81,18 @@
},
};
+ 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 2600ec4..884fe7c 100644
--- a/src/gpu/gl/angle/SkANGLEGLContext.cpp
+++ b/src/gpu/gl/angle/SkANGLEGLContext.cpp
@@ -52,7 +52,10 @@
}
}
-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 ae42227..93c0b30 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 a276fd0..1e11c0d 100644
--- a/src/gpu/gl/iOS/SkNativeGLContext_iOS.mm
+++ b/src/gpu/gl/iOS/SkNativeGLContext_iOS.mm
@@ -42,7 +42,11 @@
[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::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 df316d7..fefbb4c 100644
--- a/src/gpu/gl/mac/SkNativeGLContext_mac.cpp
+++ b/src/gpu/gl/mac/SkNativeGLContext_mac.cpp
@@ -32,8 +32,11 @@
}
}
-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 0199d12..58e325d 100644
--- a/src/gpu/gl/mesa/SkMesaGLContext.cpp
+++ b/src/gpu/gl/mesa/SkMesaGLContext.cpp
@@ -53,7 +53,11 @@
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 69a74ca..334be1d 100644
--- a/src/gpu/gl/nacl/SkNativeGLContext_nacl.cpp
+++ b/src/gpu/gl/nacl/SkNativeGLContext_nacl.cpp
@@ -26,7 +26,7 @@
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 ddbfe5d..45be793 100644
--- a/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
+++ b/src/gpu/gl/unix/GrGLCreateNativeInterface_unix.cpp
@@ -8,9 +8,20 @@
#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
+#define USE_LINKED 0
+
+#include "gl/GrGLAssembleGLESInterface.h"
+
static GrGLFuncPtr glx_get(void* ctx, const char name[]) {
SkASSERT(NULL == ctx);
SkASSERT(NULL != glXGetCurrentContext());
@@ -21,5 +32,14 @@
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 c4bd6f9..4da1eb2 100644
--- a/src/gpu/gl/unix/SkNativeGLContext_unix.cpp
+++ b/src/gpu/gl/unix/SkNativeGLContext_unix.cpp
@@ -66,7 +66,7 @@
}
}
-const GrGLInterface* SkNativeGLContext::createGLContext() {
+const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) {
fDisplay = XOpenDisplay(0);
if (!fDisplay) {
@@ -187,60 +187,68 @@
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");
-#ifdef GLX_1_3
- fContext = glXCreateNewContext(fDisplay, bestFbc, GLX_RGBA_TYPE, 0, True);
-#else
- fContext = glXCreateContext(fDisplay, vi, 0, True);
-#endif
+ 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);
+#else
+ 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
- );
+ 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
+ };
- // Sync to ensure any errors generated are processed.
- XSync(fDisplay, False);
- if (!ctxErrorOccurred && fContext) {
- //SkDebugf( "Created GL 3.0 context.\n" );
+ 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.
+ fContext = glXCreateContextAttribsARB(fDisplay, bestFbc, 0, True, context_attribs_gl);
- // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
- context_attribs[1] = 1;
- // GLX_CONTEXT_MINOR_VERSION_ARB = 0
- context_attribs[3] = 0;
+ // 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;
+ 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_fallback);
+ }
}
}
#endif
diff --git a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
index 6adaf19..4a8af51 100644
--- a/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
+++ b/src/gpu/gl/win/GrGLCreateNativeInterface_win.cpp
@@ -8,9 +8,22 @@
#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
+#define USE_LINKED 0
+
+#include "gl/GrGLAssembleGLESInterface.h"
+
class AutoLibraryUnload {
public:
AutoLibraryUnload(const char* moduleName) {
@@ -70,5 +83,13 @@
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 bae97a78..f085fdc 100644
--- a/src/gpu/gl/win/SkNativeGLContext_win.cpp
+++ b/src/gpu/gl/win/SkNativeGLContext_win.cpp
@@ -47,7 +47,7 @@
}
}
-const GrGLInterface* SkNativeGLContext::createGLContext() {
+const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) {
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
if (!gWC) {
@@ -85,9 +85,13 @@
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 3b1966d..a8552a8 100644
--- a/src/utils/win/SkWGL_win.cpp
+++ b/src/utils/win/SkWGL_win.cpp
@@ -245,7 +245,7 @@
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 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 027bc66..1b47dea 100644
--- a/src/views/win/SkOSWindow_win.cpp
+++ b/src/views/win/SkOSWindow_win.cpp
@@ -331,7 +331,8 @@
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 efe118f..b4e08aa 100644
--- a/tools/PictureRenderer.h
+++ b/tools/PictureRenderer.h
@@ -165,7 +165,11 @@
/**
* 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
@@ -200,7 +204,7 @@
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 5acec26..4ffa16f 100644
--- a/tools/PictureRenderingFlags.cpp
+++ b/tools/PictureRenderingFlags.cpp
@@ -26,6 +26,8 @@
#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 ""
@@ -74,6 +76,12 @@
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();
@@ -261,6 +269,21 @@
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) {
@@ -330,7 +353,14 @@
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