return obj;
}
+ void swap(SkAutoTDelete* that) {
+ SkTSwap(fObj, that->fObj);
+ }
+
private:
T* fObj;
};
#ifndef GrGLExtensions_DEFINED
#define GrGLExtensions_DEFINED
-#include "GrGLInterface.h"
+#include "GrGLFunctions.h"
#include "SkString.h"
#include "SkTArray.h"
+struct GrGLInterface;
+
/**
* This helper queries the current GL context for its extensions, remembers them, and can be
* queried. It supports both glGetString- and glGetStringi-style extension string APIs and will
* use the latter if it is available.
*/
-class GrGLExtensions {
+class GrGLExtensions : public SkNoncopyable {
public:
- bool init(const GrGLInterface* iface) {
- return this->init(iface->fStandard,
- iface->fGetString,
- iface->fGetStringi,
- iface->fGetIntegerv);
+
+ GrGLExtensions() : fInitialized(false), fStrings(SkNEW(SkTArray<SkString>)) {}
+
+ void swap(GrGLExtensions* that) {
+ fStrings.swap(&that->fStrings);
}
+
/**
* We sometimes need to use this class without having yet created a GrGLInterface. This version
* of init expects that getString is always non-NULL while getIntegerv and getStringi are non-
GrGLGetStringiProc getStringi,
GrGLGetIntegervProc getIntegerv);
+ bool isInitialized() const { return fInitialized; }
+
/**
* Queries whether an extension is present. This will fail if init() has not been called.
*/
bool has(const char*) const;
- void reset() { fStrings.reset(); }
+ void reset() { fStrings->reset(); }
void print(const char* sep = "\n") const;
private:
- SkTArray<SkString> fStrings;
+ bool fInitialized;
+ SkAutoTDelete<SkTArray<SkString> > fStrings;
};
#endif
#include "GrGLConfig.h"
+////////////////////////////////////////////////////////////////////////////////
+
/**
- * Declares typedefs for all the GL functions used in GrGLInterface
+ * Classifies GL contexts by which standard they implement (currently as Desktop
+ * vs. ES).
*/
+enum GrGLStandard {
+ kNone_GrGLStandard,
+ kGL_GrGLStandard,
+ kGLES_GrGLStandard,
+};
+
+// Temporary aliases until Chromium can be updated.
+typedef GrGLStandard GrGLBinding;
+static const GrGLStandard kES2_GrGLBinding = kGLES_GrGLStandard;
+static const GrGLStandard kDesktop_GrGLBinding = kGL_GrGLStandard;
///////////////////////////////////////////////////////////////////////////////
+/**
+ * Declares typedefs for all the GL functions used in GrGLInterface
+ */
+
typedef unsigned int GrGLenum;
typedef unsigned char GrGLboolean;
typedef unsigned int GrGLbitfield;
#define GrGLInterface_DEFINED
#include "GrGLFunctions.h"
+#include "GrGLExtensions.h"
#include "SkRefCnt.h"
////////////////////////////////////////////////////////////////////////////////
/**
- * Classifies GL contexts by which standard they implement (currently as Desktop
- * vs. ES).
- */
-enum GrGLStandard {
- kNone_GrGLStandard,
- kGL_GrGLStandard,
- kGLES_GrGLStandard,
-};
-
-// Temporary aliases until Chromium can be updated.
-typedef GrGLStandard GrGLBinding;
-static const GrGLStandard kES2_GrGLBinding = kGLES_GrGLStandard;
-static const GrGLStandard kDesktop_GrGLBinding = kGL_GrGLStandard;
-
-////////////////////////////////////////////////////////////////////////////////
-
-/**
* Rather than depend on platform-specific GL headers and libraries, we require
* the client to provide a struct of GL function pointers. This struct can be
* specified per-GrContext as a parameter to GrContext::Create. If NULL is
GrGLStandard fBindingsExported; // Legacy name, will be remove when Chromium is updated.
};
+ GrGLExtensions fExtensions;
+
+ // This wrapper and const hackery is necessary because the factories in Chromium do not yet
+ // initialize fExtensions.
+ bool hasExtension(const char ext[]) const {
+ if (!fExtensions.isInitialized()) {
+ GrGLExtensions* extensions = const_cast<GrGLExtensions*>(&fExtensions);
+ if (!extensions->init(fStandard, fGetString, fGetStringi, fGetIntegerv)) {
+ return false;
+ }
+ }
+ return fExtensions.has(ext);
+ }
+
GLPtr<GrGLActiveTextureProc> fActiveTexture;
GLPtr<GrGLAttachShaderProc> fAttachShader;
GLPtr<GrGLBeginQueryProc> fBeginQuery;
#ifndef SkGLContextHelper_DEFINED
#define SkGLContextHelper_DEFINED
-#include "GrGLExtensions.h"
#include "GrGLInterface.h"
/**
bool hasExtension(const char* extensionName) const {
SkASSERT(NULL != fGL);
- return fExtensions.has(extensionName);
+ return fGL->hasExtension(extensionName);
}
protected:
virtual void destroyGLContext() = 0;
private:
- GrGLExtensions fExtensions;
GrGLuint fFBO;
GrGLuint fColorBufferID;
GrGLuint fDepthStencilBufferID;
// The GL_EXT_texture_format_BGRA8888 extension does not add BGRA to the list of
// configs that are color-renderable and can be passed to glRenderBufferStorageMultisample.
// Chromium may have an extension to allow BGRA renderbuffers to work on desktop platforms.
- if (ctxInfo.extensions().has("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
+ if (ctxInfo.hasExtension("GL_CHROMIUM_renderbuffer_format_BGRA8888")) {
fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] = true;
} else {
fConfigRenderSupport[kBGRA_8888_GrPixelConfig][kYes_MSAA] =
fGLSLGeneration = that.fGLSLGeneration;
fVendor = that.fVendor;
fRenderer = that.fRenderer;
- fExtensions = that.fExtensions;
fIsMesa = that.fIsMesa;
fIsChromium = that.fIsChromium;
*fGLCaps = *that.fGLCaps.get();
GR_GL_CALL_RET(interface, rendererUByte, GetString(GR_GL_RENDERER));
const char* renderer = reinterpret_cast<const char*>(rendererUByte);
- if (interface->validate() && fExtensions.init(interface)) {
+ if (interface->validate()) {
fGLVersion = GrGLGetVersionFromString(ver);
fRenderer = kOther_GrGLRenderer;
fIsMesa = false;
fIsChromium = false;
- fExtensions.reset();
fGLCaps->reset();
}
bool isChromium() const { return fIsChromium; }
const GrGLCaps* caps() const { return fGLCaps.get(); }
GrGLCaps* caps() { return fGLCaps; }
- const GrGLExtensions& extensions() const { return fExtensions; }
-
- /**
- * Shortcut for extensions().has(ext)
- */
bool hasExtension(const char* ext) const {
if (!this->isInitialized()) {
return false;
}
- return fExtensions.has(ext);
+ return fInterface->hasExtension(ext);
}
/**
GrGLSLGeneration fGLSLGeneration;
GrGLVendor fVendor;
GrGLRenderer fRenderer;
- GrGLExtensions fExtensions;
bool fIsMesa;
bool fIsChromium;
SkAutoTUnref<GrGLCaps> fGLCaps;
GrGLGetStringProc getString,
GrGLGetStringiProc getStringi,
GrGLGetIntegervProc getIntegerv) {
- fStrings.reset();
+ fInitialized = false;
+ fStrings->reset();
+
if (NULL == getString) {
return false;
}
}
GrGLint extensionCnt = 0;
getIntegerv(GR_GL_NUM_EXTENSIONS, &extensionCnt);
- fStrings.push_back_n(extensionCnt);
+ fStrings->push_back_n(extensionCnt);
for (int i = 0; i < extensionCnt; ++i) {
const char* ext = (const char*) getStringi(GR_GL_EXTENSIONS, i);
- fStrings[i] = ext;
+ (*fStrings)[i] = ext;
}
} else {
const char* extensions = (const char*) getString(GR_GL_EXTENSIONS);
}
// we found an extension
size_t length = strcspn(extensions, " ");
- fStrings.push_back().set(extensions, length);
+ fStrings->push_back().set(extensions, length);
extensions += length;
}
}
- if (!fStrings.empty()) {
+ if (!fStrings->empty()) {
SkTLessFunctionToFunctorAdaptor<SkString, extension_compare> cmp;
- SkTQSort(&fStrings.front(), &fStrings.back(), cmp);
+ SkTQSort(&fStrings->front(), &fStrings->back(), cmp);
}
+ fInitialized = true;
return true;
}
bool GrGLExtensions::has(const char* ext) const {
- if (fStrings.empty()) {
+ if (fStrings->empty()) {
return false;
}
SkString extensionStr(ext);
- int idx = SkTSearch<SkString, extension_compare>(&fStrings.front(),
- fStrings.count(),
+ int idx = SkTSearch<SkString, extension_compare>(&fStrings->front(),
+ fStrings->count(),
extensionStr,
sizeof(SkString));
return idx >= 0;
if (NULL == sep) {
sep = " ";
}
- int cnt = fStrings.count();
+ int cnt = fStrings->count();
for (int i = 0; i < cnt; ++i) {
- GrPrintf("%s%s", fStrings[i].c_str(), (i < cnt - 1) ? sep : "");
+ GrPrintf("%s%s", (*fStrings)[i].c_str(), (i < cnt - 1) ? sep : "");
}
}
return false;
}
- GrGLExtensions extensions;
- if (!extensions.init(this)) {
- return false;
+ // This const hackery is necessary because the factories in Chromium do not yet initialize
+ // fExtensions.
+ if (!fExtensions.isInitialized()) {
+ GrGLExtensions* extensions = const_cast<GrGLExtensions*>(&fExtensions);
+ if (!extensions->init(fStandard, fGetString, fGetStringi, fGetIntegerv)) {
+ return false;
+ }
}
// functions that are always required
}
// Now check that baseline ES/Desktop fns not covered above are present
- // and that we have fn pointers for any advertised extensions that we will
+ // and that we have fn pointers for any advertised fExtensions that we will
// try to use.
// these functions are part of ES2, we assume they are available
if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
return false;
}
- if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
+ if (glVer >= GR_GL_VER(2,0) || fExtensions.has("GL_ARB_draw_buffers")) {
if (NULL == fDrawBuffers) {
return false;
}
}
- if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
+ if (glVer >= GR_GL_VER(1,5) || fExtensions.has("GL_ARB_occlusion_query")) {
if (NULL == fGenQueries ||
NULL == fDeleteQueries ||
NULL == fBeginQuery ||
}
}
if (glVer >= GR_GL_VER(3,3) ||
- extensions.has("GL_ARB_timer_query") ||
- extensions.has("GL_EXT_timer_query")) {
+ fExtensions.has("GL_ARB_timer_query") ||
+ fExtensions.has("GL_EXT_timer_query")) {
if (NULL == fGetQueryObjecti64v ||
NULL == fGetQueryObjectui64v) {
return false;
}
}
- if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
+ if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) {
if (NULL == fQueryCounter) {
return false;
}
return false;
}
}
- if (false && extensions.has("GL_NV_path_rendering")) {
+ if (false && fExtensions.has("GL_NV_path_rendering")) {
if (NULL == fPathCommands ||
NULL == fPathCoords ||
NULL == fPathSubCommands ||
// optional function on desktop before 1.3
if (kGL_GrGLStandard != fStandard ||
(glVer >= GR_GL_VER(1,3)) ||
- extensions.has("GL_ARB_texture_compression")) {
+ fExtensions.has("GL_ARB_texture_compression")) {
if (NULL == fCompressedTexImage2D) {
return false;
}
// There is a desktop ARB extension and an ES+desktop EXT extension
if (kGL_GrGLStandard == fStandard) {
if (glVer >= GR_GL_VER(4,2) ||
- extensions.has("GL_ARB_texture_storage") ||
- extensions.has("GL_EXT_texture_storage")) {
+ fExtensions.has("GL_ARB_texture_storage") ||
+ fExtensions.has("GL_EXT_texture_storage")) {
if (NULL == fTexStorage2D) {
return false;
}
}
- } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) {
+ } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) {
if (NULL == fTexStorage2D) {
return false;
}
}
- if (extensions.has("GL_EXT_discard_framebuffer")) {
+ if (fExtensions.has("GL_EXT_discard_framebuffer")) {
// FIXME: Remove this once Chromium is updated to provide this function
#if 0
if (NULL == fDiscardFramebuffer) {
// FBO MSAA
if (kGL_GrGLStandard == fStandard) {
// GL 3.0 and the ARB extension have multisample + blit
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
+ if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) {
if (NULL == fRenderbufferStorageMultisample ||
NULL == fBlitFramebuffer) {
return false;
}
} else {
- if (extensions.has("GL_EXT_framebuffer_blit") &&
+ if (fExtensions.has("GL_EXT_framebuffer_blit") &&
NULL == fBlitFramebuffer) {
return false;
}
- if (extensions.has("GL_EXT_framebuffer_multisample") &&
+ if (fExtensions.has("GL_EXT_framebuffer_multisample") &&
NULL == fRenderbufferStorageMultisample) {
return false;
}
}
} else {
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
+ if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) {
if (NULL == fRenderbufferStorageMultisample ||
NULL == fBlitFramebuffer) {
return false;
}
}
- if (extensions.has("GL_APPLE_framebuffer_multisample")) {
+ if (fExtensions.has("GL_APPLE_framebuffer_multisample")) {
if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
NULL == fResolveMultisampleFramebuffer) {
return false;
}
}
- if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
- extensions.has("GL_EXT_multisampled_render_to_texture")) {
+ if (fExtensions.has("GL_IMG_multisampled_render_to_texture") ||
+ fExtensions.has("GL_EXT_multisampled_render_to_texture")) {
if (NULL == fRenderbufferStorageMultisampleES2EXT ||
NULL == fFramebufferTexture2DMultisample) {
return false;
// On ES buffer mapping is an extension. On Desktop
// buffer mapping was part of original VBO extension
// which we require.
- if (kGL_GrGLStandard == fStandard || extensions.has("GL_OES_mapbuffer")) {
+ if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) {
if (NULL == fMapBuffer ||
NULL == fUnmapBuffer) {
return false;
// Dual source blending
if (kGL_GrGLStandard == fStandard &&
- (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
+ (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended"))) {
if (NULL == fBindFragDataLocationIndexed) {
return false;
}
}
if (kGL_GrGLStandard == fStandard) {
- if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
+ if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) {
if (NULL == fBindVertexArray ||
NULL == fDeleteVertexArrays ||
NULL == fGenVertexArrays) {
}
}
} else {
- if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) {
+ if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) {
if (NULL == fBindVertexArray ||
NULL == fDeleteVertexArrays ||
NULL == fGenVertexArrays) {
GrPrintf("------ RENDERER %s\n", renderer);
GrPrintf("------ VERSION %s\n", version);
GrPrintf("------ EXTENSIONS\n");
- ctx.extensions().print();
+#if 0 // TODO: Reenable this after GrGLInterface's extensions can be accessed safely.
+ ctx.extensions().print();
+#endif
GrPrintf("\n");
GrPrintf(this->glCaps().dump().c_str());
}
if (fGL) {
const GrGLubyte* temp;
- if (!fGL->validate() || !fExtensions.init(fGL)) {
+ if (!fGL->validate()) {
fGL = NULL;
this->destroyGLContext();
return false;
#include <EGL/egl.h>
-static const GrGLInterface* create_es_interface(GrGLVersion version,
- const GrGLExtensions& extensions) {
+static GrGLInterface* create_es_interface(GrGLVersion version,
+ const GrGLExtensions& extensions) {
if (version < GR_GL_VER(2,0)) {
return NULL;
}
return interface;
}
-static const GrGLInterface* create_desktop_interface(GrGLVersion version,
- const GrGLExtensions& extensions) {
+static GrGLInterface* create_desktop_interface(GrGLVersion version,
+ const GrGLExtensions& extensions) {
// Currently this assumes a 4.4 context or later. Supporting lower GL versions would require
// getting suffixed versions of pointers for supported extensions.
if (version < GR_GL_VER(4,4)) {
return NULL;
}
+ GrGLInterface* interface = NULL;
if (kGLES_GrGLStandard == standard) {
- return create_es_interface(version, extensions);
+ interface = create_es_interface(version, extensions);
} else if (kGL_GrGLStandard == standard) {
- return create_desktop_interface(version, extensions);
- } else {
- return NULL;
+ interface = create_desktop_interface(version, extensions);
+ }
+
+ if (NULL != interface) {
+ interface->fExtensions.swap(&extensions);
}
+
+ return interface;
}
#endif
interface->fStandard = kGLES_GrGLStandard;
-
+ interface->fExtensions.init(kGLES_GrGLStandard, glGetString, NULL, glGetIntegerv);
return interface;
}
#include "gl/GrGLInterface.h"
-#include "gl/GrGLExtensions.h"
#include "../GrGLUtil.h"
#include <dlfcn.h>
// ARB extension doesn't use the ARB suffix on the function name
GET_PROC(BindFragDataLocationIndexed);
}
+
+ interface->fExtensions.swap(&extensions);
return interface;
}
return NULL;
}
GR_GL_GET_PROC(BindFragDataLocationIndexed);
+
interface->fStandard = kGL_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
+
return interface;
} else {
return NULL;
*/
-#include "gl/GrGLExtensions.h"
#include "gl/GrGLInterface.h"
#include "../GrGLUtil.h"
}
interface->fStandard = kGL_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
return interface;
} else {
* found in the LICENSE file.
*/
-
-#include "gl/GrGLExtensions.h"
#include "gl/GrGLInterface.h"
#include "gl/GrGLUtil.h"
#define WIN32_LEAN_AND_MEAN
}
interface->fStandard = kGL_GrGLStandard;
+ interface->fExtensions.swap(&extensions);
return interface;
} else {