aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2015-11-22 14:51:00 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2015-11-22 14:51:00 -0800
commit7ea33f5e1ae9eb1fb1e7377d6edf6acdcf71d103 (patch)
tree92aa7841b61ab93ec8a95d834e309ae0d2cf04e8 /src/gpu/gl
parentde3aac8cea8a7113f31591e6e02c51fe0ac45280 (diff)
Initial version of external_oes texture support and unit test
Diffstat (limited to 'src/gpu/gl')
-rw-r--r--src/gpu/gl/GrGLAssembleInterface.cpp2
-rw-r--r--src/gpu/gl/GrGLCaps.cpp21
-rw-r--r--src/gpu/gl/GrGLCaps.h4
-rw-r--r--src/gpu/gl/GrGLDefines.h10
-rw-r--r--src/gpu/gl/GrGLGpu.cpp272
-rw-r--r--src/gpu/gl/GrGLGpu.h15
-rw-r--r--src/gpu/gl/GrGLInterface.cpp4
-rw-r--r--src/gpu/gl/GrGLProgramDataManager.cpp2
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp41
-rw-r--r--src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp33
-rw-r--r--src/gpu/gl/angle/SkANGLEGLContext.cpp66
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp20
-rw-r--r--src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp10
-rw-r--r--src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp59
14 files changed, 412 insertions, 147 deletions
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index e606f4a29e..dbc54adbe4 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -14,7 +14,7 @@
#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_EGL_PROC_SUFFIX(F, S) functions->f ## F = (GrEGL ## F ## Proc) get(ctx, "egl" #F #S)
+#define GET_EGL_PROC_SUFFIX(F, S) functions->fEGL ## F = (GrEGL ## F ## Proc) get(ctx, "egl" #F #S)
const GrGLInterface* GrGLAssembleInterface(void* ctx, GrGLGetProc get) {
GET_PROC_LOCAL(GetString);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 28401fe9e6..a768b37105 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -46,6 +46,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fUseNonVBOVertexAndIndexDynamicData = false;
fIsCoreProfile = false;
fBindFragDataLocationSupport = false;
+ fExternalTextureSupport = false;
fSRGBWriteControl = false;
fRGBA8888PixelsOpsAreSlow = false;
fPartialFBOReadIsSlow = false;
@@ -259,6 +260,16 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
fBindUniformLocationSupport = false;
#endif
+ if (ctxInfo.hasExtension("GL_OES_EGL_image_external")) {
+ if (ctxInfo.glslGeneration() == k110_GrGLSLGeneration) {
+ fExternalTextureSupport = true;
+ } else if (ctxInfo.hasExtension("GL_OES_EGL_image_external_essl3") ||
+ ctxInfo.hasExtension("OES_EGL_image_external_essl3")) {
+ // At least one driver has been found that has this extension without the "GL_" prefix.
+ fExternalTextureSupport = true;
+ }
+ }
+
#ifdef SK_BUILD_FOR_WIN
// We're assuming that on Windows Chromium we're using ANGLE.
bool isANGLE = kANGLE_GrGLDriver == ctxInfo.driver() ||
@@ -588,13 +599,21 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
glslCaps->fSecondaryOutputExtensionString = "GL_EXT_blend_func_extended";
}
+ if (fExternalTextureSupport) {
+ if (ctxInfo.glslGeneration() == k110_GrGLSLGeneration) {
+ glslCaps->fExternalTextureExtensionString = "GL_OES_EGL_image_external";
+ } else {
+ glslCaps->fExternalTextureExtensionString = "GL_OES_EGL_image_external_essl3";
+ }
+ }
+
// The Tegra3 compiler will sometimes never return if we have min(abs(x), 1.0), so we must do
// the abs first in a separate expression.
if (kTegra3_GrGLRenderer == ctxInfo.renderer()) {
glslCaps->fCanUseMinAndAbsTogether = false;
}
- // On Intel GPU there is an issue where it reads the second arguement to atan "- %s.x" as an int
+ // On Intel GPU there is an issue where it reads the second argument to atan "- %s.x" as an int
// thus must us -1.0 * %s.x to work correctly
if (kIntel_GrGLVendor == ctxInfo.vendor()) {
glslCaps->fMustForceNegatedAtanParamToFloat = true;
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 5f1ca3e340..0ec6c85b47 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -232,6 +232,9 @@ public:
bool bindUniformLocationSupport() const { return fBindUniformLocationSupport; }
+ /// Are textures with GL_TEXTURE_EXTERNAL_OES type supported.
+ bool externalTextureSupport() const { return fExternalTextureSupport; }
+
/**
* Is there support for enabling/disabling sRGB writes for sRGB-capable color attachments?
* If false this does not mean sRGB is not supported but rather that if it is supported
@@ -360,6 +363,7 @@ private:
bool fRGBA8888PixelsOpsAreSlow : 1;
bool fPartialFBOReadIsSlow : 1;
bool fBindUniformLocationSupport : 1;
+ bool fExternalTextureSupport : 1;
struct ReadPixelsSupportedFormat {
GrGLenum fFormat;
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index 603a319ca0..dfab5e7e13 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -928,8 +928,18 @@
#define GR_GL_PROGRAM_PIPELINE 0x82E4
#define GR_GL_SAMPLER 0x82E6
+/* GL_OES_EGL_image_external */
+#define GR_GL_TEXTURE_EXTERNAL 0x8D65
+
/* EGL Defines */
#define GR_EGL_NO_DISPLAY ((GrEGLDisplay)0)
#define GR_EGL_EXTENSIONS 0x3055
+#define GR_EGL_GL_TEXTURE_2D 0x30B1
+#define GR_EGL_GL_TEXTURE_LEVEL 0x30BC
+#define GR_EGL_IMAGE_PRESERVED 0x30D2
+#define GR_EGL_FALSE 0x0
+#define GR_EGL_TRUE 0x1
+#define GR_EGL_NONE 0x3038
+#define GR_EGL_NO_IMAGE ((GrEGLImage)0)
#endif
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 2bd36b6404..51145c8988 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -233,7 +233,7 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
fPathRendering.reset(new GrGLPathRendering(this));
}
- this->createCopyProgram();
+ this->createCopyPrograms();
}
GrGLGpu::~GrGLGpu() {
@@ -253,12 +253,13 @@ GrGLGpu::~GrGLGpu() {
GL_CALL(DeleteFramebuffers(1, &fStencilClearFBOID));
}
- if (0 != fCopyProgram.fArrayBuffer) {
- GL_CALL(DeleteBuffers(1, &fCopyProgram.fArrayBuffer));
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
+ if (0 != fCopyPrograms[i].fProgram) {
+ GL_CALL(DeleteProgram(fCopyPrograms[i].fProgram));
+ }
}
-
- if (0 != fCopyProgram.fProgram) {
- GL_CALL(DeleteProgram(fCopyProgram.fProgram));
+ if (0 != fCopyProgramArrayBuffer) {
+ GL_CALL(DeleteBuffers(1, &fCopyProgramArrayBuffer));
}
delete fProgramCache;
@@ -271,8 +272,10 @@ void GrGLGpu::contextAbandoned() {
fTempSrcFBOID = 0;
fTempDstFBOID = 0;
fStencilClearFBOID = 0;
- fCopyProgram.fArrayBuffer = 0;
- fCopyProgram.fProgram = 0;
+ fCopyProgramArrayBuffer = 0;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
+ fCopyPrograms[i].fProgram = 0;
+ }
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
this->glPathRendering()->abandonGpuResources();
}
@@ -429,6 +432,9 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
return nullptr;
}
+ // next line relies on GrBackendTextureDesc's flags matching GrTexture's
+ bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
+
GrGLTexture::IDDesc idDesc;
GrSurfaceDesc surfDesc;
@@ -439,6 +445,15 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
#else
idDesc.fInfo = *info;
#endif
+ if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) {
+ if (renderTarget) {
+ // This combination is not supported.
+ return nullptr;
+ }
+ if (!this->glCaps().externalTextureSupport()) {
+ return nullptr;
+ }
+ }
switch (ownership) {
case kAdopt_GrWrapOwnership:
@@ -449,13 +464,11 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
break;
}
- // next line relies on GrBackendTextureDesc's flags matching GrTexture's
surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
surfDesc.fWidth = desc.fWidth;
surfDesc.fHeight = desc.fHeight;
surfDesc.fConfig = desc.fConfig;
surfDesc.fSampleCnt = SkTMin(desc.fSampleCnt, this->caps()->maxSampleCount());
- bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
// FIXME: this should be calling resolve_origin(), but Chrome code is currently
// assuming the old behaviour, which is that backend textures are always
// BottomLeft, even for non-RT's. Once Chrome is fixed, change this to:
@@ -524,6 +537,12 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
// into it. We could use glDrawPixels on GLs that have it, but we don't today.
if (!dstSurface->asTexture()) {
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
+ } else {
+ GrGLTexture* texture = static_cast<GrGLTexture*>(dstSurface->asTexture());
+ if (GR_GL_TEXTURE_2D != texture->target()) {
+ // We don't currently support writing pixels to non-TEXTURE_2D textures.
+ return false;
+ }
}
if (GrPixelConfigIsSRGB(dstSurface->config()) != GrPixelConfigIsSRGB(srcConfig)) {
@@ -585,6 +604,11 @@ bool GrGLGpu::onWritePixels(GrSurface* surface,
return false;
}
+ // Write pixels is only implemented for TEXTURE_2D textures
+ if (GR_GL_TEXTURE_2D != glTex->target()) {
+ return false;
+ }
+
this->setScratchTextureUnit();
GL_CALL(BindTexture(glTex->target(), glTex->textureID()));
@@ -2752,11 +2776,10 @@ void GrGLGpu::setScratchTextureUnit() {
fHWBoundTextureUniqueIDs[lastUnitIdx] = SK_InvalidUniqueID;
}
-namespace {
// Determines whether glBlitFramebuffer could be used between src and dst.
-inline bool can_blit_framebuffer(const GrSurface* dst,
- const GrSurface* src,
- const GrGLGpu* gpu) {
+static inline bool can_blit_framebuffer(const GrSurface* dst,
+ const GrSurface* src,
+ const GrGLGpu* gpu) {
if (gpu->glCaps().isConfigRenderable(dst->config(), dst->desc().fSampleCnt > 0) &&
gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
gpu->glCaps().usesMSAARenderBuffers()) {
@@ -2766,15 +2789,23 @@ inline bool can_blit_framebuffer(const GrSurface* dst,
(src->desc().fSampleCnt > 0 || src->config() != dst->config())) {
return false;
}
+ const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
+ if (dstTex && dstTex->target() != GR_GL_TEXTURE_2D) {
+ return false;
+ }
+ const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(dst->asTexture());
+ if (srcTex && srcTex->target() != GR_GL_TEXTURE_2D) {
+ return false;
+ }
return true;
} else {
return false;
}
}
-inline bool can_copy_texsubimage(const GrSurface* dst,
- const GrSurface* src,
- const GrGLGpu* gpu) {
+static inline bool can_copy_texsubimage(const GrSurface* dst,
+ const GrSurface* src,
+ const GrGLGpu* gpu) {
// Table 3.9 of the ES2 spec indicates the supported formats with CopyTexSubImage
// and BGRA isn't in the spec. There doesn't appear to be any extension that adds it. Perhaps
// many drivers would allow it to work, but ANGLE does not.
@@ -2794,18 +2825,29 @@ inline bool can_copy_texsubimage(const GrSurface* dst,
if (srcRT && srcRT->renderFBOID() != srcRT->textureFBOID()) {
return false;
}
+
+ const GrGLTexture* dstTex = static_cast<const GrGLTexture*>(dst->asTexture());
+ // CopyTex(Sub)Image writes to a texture and we have no way of dynamically wrapping a RT in a
+ // texture.
+ if (!dstTex) {
+ return false;
+ }
+
+ const GrGLTexture* srcTex = static_cast<const GrGLTexture*>(src->asTexture());
+
+ // Check that we could wrap the source in an FBO, that the dst is TEXTURE_2D, that no mirroring
+ // is required.
if (gpu->glCaps().isConfigRenderable(src->config(), src->desc().fSampleCnt > 0) &&
- dst->asTexture() &&
- dst->origin() == src->origin() &&
- !GrPixelConfigIsCompressed(src->config())) {
+ !GrPixelConfigIsCompressed(src->config()) &&
+ (!srcTex || srcTex->target() == GR_GL_TEXTURE_2D) &&
+ dstTex->target() == GR_GL_TEXTURE_2D &&
+ dst->origin() == src->origin()) {
return true;
} else {
return false;
}
}
-}
-
// If a temporary FBO was created, its non-zero ID is returned. The viewport that the copy rect is
// relative to is output.
void GrGLGpu::bindSurfaceFBOForCopy(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport,
@@ -2863,6 +2905,12 @@ bool GrGLGpu::initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc)
return true;
}
+ const GrGLTexture* srcTexture = static_cast<const GrGLTexture*>(src->asTexture());
+ if (srcTexture && srcTexture->target() != GR_GL_TEXTURE_2D) {
+ // Not supported for FBO blit or CopyTexSubImage
+ return false;
+ }
+
// We look for opportunities to use CopyTexSubImage, or fbo blit. If neither are
// possible and we return false to fallback to creating a render target dst for render-to-
// texture. This code prefers CopyTexSubImage to fbo blit and avoids triggering temporary fbo
@@ -2927,92 +2975,109 @@ bool GrGLGpu::onCopySurface(GrSurface* dst,
}
-void GrGLGpu::createCopyProgram() {
+void GrGLGpu::createCopyPrograms() {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
+ fCopyPrograms[i].fProgram = 0;
+ }
const char* version = this->glCaps().glslCaps()->versionDeclString();
-
- GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
- GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
+ static const GrSLType kSamplerTypes[2] = { kSampler2D_GrSLType, kSamplerExternal_GrSLType };
+ SkASSERT(2 == SK_ARRAY_COUNT(fCopyPrograms));
+ int programCount = this->glCaps().externalTextureSupport() ? 2 : 1;
+ for (int i = 0; i < programCount; ++i) {
+ GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
+ GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
+ GrShaderVar::kUniform_TypeModifier);
+ GrGLSLShaderVar uPosXform("u_posXform", kVec4f_GrSLType,
+ GrShaderVar::kUniform_TypeModifier);
+ GrGLSLShaderVar uTexture("u_texture", kSamplerTypes[i],
GrShaderVar::kUniform_TypeModifier);
- GrGLSLShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
- GrGLSLShaderVar uTexture("u_texture", kSampler2D_GrSLType, GrShaderVar::kUniform_TypeModifier);
- GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kVaryingOut_TypeModifier);
- GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
+ GrGLSLShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType,
+ GrShaderVar::kVaryingOut_TypeModifier);
+ GrGLSLShaderVar oFragColor("o_FragColor", kVec4f_GrSLType,
+ GrShaderVar::kOut_TypeModifier);
- SkString vshaderTxt(version);
- aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
- vshaderTxt.append(";");
- uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
- vshaderTxt.append(";");
- uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
- vshaderTxt.append(";");
- vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
- vshaderTxt.append(";");
+ SkString vshaderTxt(version);
+ aVertex.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
+ vshaderTxt.append(";");
+ uTexCoordXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
+ vshaderTxt.append(";");
+ uPosXform.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
+ vshaderTxt.append(";");
+ vTexCoord.appendDecl(this->glCaps().glslCaps(), &vshaderTxt);
+ vshaderTxt.append(";");
- vshaderTxt.append(
- "// Copy Program VS\n"
- "void main() {"
- " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
- " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
- " gl_Position.zw = vec2(0, 1);"
- "}"
- );
-
- SkString fshaderTxt(version);
- GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
- *this->glCaps().glslCaps(),
- &fshaderTxt);
- vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
- vTexCoord.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
- fshaderTxt.append(";");
- uTexture.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
- fshaderTxt.append(";");
- const char* fsOutName;
- if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) {
- oFragColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
+ vshaderTxt.append(
+ "// Copy Program VS\n"
+ "void main() {"
+ " v_texCoord = a_vertex.xy * u_texCoordXform.xy + u_texCoordXform.zw;"
+ " gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
+ " gl_Position.zw = vec2(0, 1);"
+ "}"
+ );
+
+ SkString fshaderTxt(version);
+ if (kSamplerTypes[i] == kSamplerExternal_GrSLType) {
+ fshaderTxt.appendf("#extension %s : require\n",
+ this->glCaps().glslCaps()->externalTextureExtensionString());
+ }
+ GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision,
+ *this->glCaps().glslCaps(),
+ &fshaderTxt);
+ vTexCoord.setTypeModifier(GrShaderVar::kVaryingIn_TypeModifier);
+ vTexCoord.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
fshaderTxt.append(";");
- fsOutName = oFragColor.c_str();
- } else {
- fsOutName = "gl_FragColor";
- }
- fshaderTxt.appendf(
- "// Copy Program FS\n"
- "void main() {"
- " %s = %s(u_texture, v_texCoord);"
- "}",
- fsOutName,
- GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration())
- );
+ uTexture.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
+ fshaderTxt.append(";");
+ const char* fsOutName;
+ if (this->glCaps().glslCaps()->mustDeclareFragmentShaderOutput()) {
+ oFragColor.appendDecl(this->glCaps().glslCaps(), &fshaderTxt);
+ fshaderTxt.append(";");
+ fsOutName = oFragColor.c_str();
+ } else {
+ fsOutName = "gl_FragColor";
+ }
+ fshaderTxt.appendf(
+ "// Copy Program FS\n"
+ "void main() {"
+ " %s = %s(u_texture, v_texCoord);"
+ "}",
+ fsOutName,
+ GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration())
+ );
- GL_CALL_RET(fCopyProgram.fProgram, CreateProgram());
- const char* str;
- GrGLint length;
+ GL_CALL_RET(fCopyPrograms[i].fProgram, CreateProgram());
+ const char* str;
+ GrGLint length;
- str = vshaderTxt.c_str();
- length = SkToInt(vshaderTxt.size());
- GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyProgram.fProgram,
- GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats);
+ str = vshaderTxt.c_str();
+ length = SkToInt(vshaderTxt.size());
+ GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[i].fProgram,
+ GR_GL_VERTEX_SHADER, &str, &length, 1,
+ &fStats);
- str = fshaderTxt.c_str();
- length = SkToInt(fshaderTxt.size());
- GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyProgram.fProgram,
- GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats);
+ str = fshaderTxt.c_str();
+ length = SkToInt(fshaderTxt.size());
+ GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fCopyPrograms[i].fProgram,
+ GR_GL_FRAGMENT_SHADER, &str, &length, 1,
+ &fStats);
- GL_CALL(LinkProgram(fCopyProgram.fProgram));
+ GL_CALL(LinkProgram(fCopyPrograms[i].fProgram));
- GL_CALL_RET(fCopyProgram.fTextureUniform, GetUniformLocation(fCopyProgram.fProgram,
- "u_texture"));
- GL_CALL_RET(fCopyProgram.fPosXformUniform, GetUniformLocation(fCopyProgram.fProgram,
- "u_posXform"));
- GL_CALL_RET(fCopyProgram.fTexCoordXformUniform, GetUniformLocation(fCopyProgram.fProgram,
- "u_texCoordXform"));
+ GL_CALL_RET(fCopyPrograms[i].fTextureUniform,
+ GetUniformLocation(fCopyPrograms[i].fProgram, "u_texture"));
+ GL_CALL_RET(fCopyPrograms[i].fPosXformUniform,
+ GetUniformLocation(fCopyPrograms[i].fProgram, "u_posXform"));
+ GL_CALL_RET(fCopyPrograms[i].fTexCoordXformUniform,
+ GetUniformLocation(fCopyPrograms[i].fProgram, "u_texCoordXform"));
- GL_CALL(BindAttribLocation(fCopyProgram.fProgram, 0, "a_vertex"));
+ GL_CALL(BindAttribLocation(fCopyPrograms[i].fProgram, 0, "a_vertex"));
- GL_CALL(DeleteShader(vshader));
- GL_CALL(DeleteShader(fshader));
+ GL_CALL(DeleteShader(vshader));
+ GL_CALL(DeleteShader(fshader));
+ }
- GL_CALL(GenBuffers(1, &fCopyProgram.fArrayBuffer));
- fHWGeometryState.setVertexBufferID(this, fCopyProgram.fArrayBuffer);
+ GL_CALL(GenBuffers(1, &fCopyProgramArrayBuffer));
+ fHWGeometryState.setVertexBufferID(this, fCopyProgramArrayBuffer);
static const GrGLfloat vdata[] = {
0, 0,
0, 1,
@@ -3041,14 +3106,16 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX, dstPoint.fY, w, h);
this->flushRenderTarget(dstRT, &dstRect);
- GL_CALL(UseProgram(fCopyProgram.fProgram));
- fHWProgramID = fCopyProgram.fProgram;
+ int progIdx = TextureTargetToCopyProgramIdx(srcTex->target());
+
+ GL_CALL(UseProgram(fCopyPrograms[progIdx].fProgram));
+ fHWProgramID = fCopyPrograms[progIdx].fProgram;
fHWGeometryState.setVertexArrayID(this, 0);
GrGLAttribArrayState* attribs =
- fHWGeometryState.bindArrayAndBufferToDraw(this, fCopyProgram.fArrayBuffer);
- attribs->set(this, 0, fCopyProgram.fArrayBuffer, 2, GR_GL_FLOAT, false,
+ fHWGeometryState.bindArrayAndBufferToDraw(this, fCopyProgramArrayBuffer);
+ attribs->set(this, 0, fCopyProgramArrayBuffer, 2, GR_GL_FLOAT, false,
2 * sizeof(GrGLfloat), 0);
attribs->disableUnusedArrays(this, 0x1);
@@ -3076,9 +3143,10 @@ void GrGLGpu::copySurfaceAsDraw(GrSurface* dst,
sy1 = 1.f - sy1;
}
- GL_CALL(Uniform4f(fCopyProgram.fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
- GL_CALL(Uniform4f(fCopyProgram.fTexCoordXformUniform, sx1 - sx0, sy1 - sy0, sx0, sy0));
- GL_CALL(Uniform1i(fCopyProgram.fTextureUniform, 0));
+ GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
+ GL_CALL(Uniform4f(fCopyPrograms[progIdx].fTexCoordXformUniform,
+ sx1 - sx0, sy1 - sy0, sx0, sy0));
+ GL_CALL(Uniform1i(fCopyPrograms[progIdx].fTextureUniform, 0));
GrXferProcessor::BlendInfo blendInfo;
blendInfo.reset();
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index c8da150a0d..637a1cf161 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -322,7 +322,7 @@ private:
SkAutoTUnref<GrGLContext> fGLContext;
- void createCopyProgram();
+ void createCopyPrograms();
// GL program-related state
ProgramCache* fProgramCache;
@@ -497,8 +497,17 @@ private:
GrGLint fTextureUniform;
GrGLint fTexCoordXformUniform;
GrGLint fPosXformUniform;
- GrGLuint fArrayBuffer;
- } fCopyProgram;
+ } fCopyPrograms[2];
+ GrGLuint fCopyProgramArrayBuffer;
+
+ static int TextureTargetToCopyProgramIdx(GrGLenum target) {
+ if (target == GR_GL_TEXTURE_2D) {
+ return 0;
+ } else {
+ SkASSERT(target == GR_GL_TEXTURE_EXTERNAL);
+ return 1;
+ }
+ }
TriState fMSAAEnabled;
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index c6c846abf8..da3c656c18 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -727,8 +727,8 @@ bool GrGLInterface::validate() const {
}
if (fExtensions.has("EGL_KHR_image") || fExtensions.has("EGL_KHR_image_base")) {
- if (nullptr == fFunctions.fCreateImage ||
- nullptr == fFunctions.fDestroyImage) {
+ if (nullptr == fFunctions.fEGLCreateImage ||
+ nullptr == fFunctions.fEGLDestroyImage) {
RETURN_FALSE_INTERFACE
}
}
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index a61e6974b6..f0aba49720 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -62,7 +62,7 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, GrGLuint programID,
void GrGLProgramDataManager::setSampler(UniformHandle u, int texUnit) const {
const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kSampler2D_GrSLType);
+ SkASSERT(uni.fType == kSampler2D_GrSLType || uni.fType == kSamplerExternal_GrSLType);
SkASSERT(GrGLSLShaderVar::kNonArray == uni.fArrayCount);
// FIXME: We still insert a single sampler uniform for every stage. If the shader does not
// reference the sampler then the compiler may have optimized it out. Uncomment this assert
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 172aca77ab..e3ee9139c2 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -31,11 +31,16 @@ static bool swizzle_requires_alpha_remapping(const GrGLSLCaps& caps, GrPixelConf
static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
uint32_t key = 0;
int numTextures = proc.numTextures();
+ int shift = 0;
for (int t = 0; t < numTextures; ++t) {
const GrTextureAccess& access = proc.textureAccess(t);
if (swizzle_requires_alpha_remapping(*caps.glslCaps(), access.getTexture()->config())) {
- key |= 1 << t;
+ key |= 1 << shift;
}
+ if (GR_GL_TEXTURE_EXTERNAL == static_cast<GrGLTexture*>(access.getTexture())->target()) {
+ key |= 2 << shift;
+ }
+ shift += 2;
}
return key;
}
@@ -48,10 +53,8 @@ static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
* which must be different for every GrProcessor subclass. It can fail if an effect uses too many
* textures, transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share
* this function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
- *
- * TODO: A better name for this function would be "compute" instead of "get".
*/
-static bool get_meta_key(const GrProcessor& proc,
+static bool gen_meta_key(const GrProcessor& proc,
const GrGLCaps& caps,
uint32_t transformKey,
GrProcessorKeyBuilder* b) {
@@ -59,31 +62,25 @@ static bool get_meta_key(const GrProcessor& proc,
uint32_t textureKey = gen_texture_key(proc, caps);
uint32_t classID = proc.classID();
- // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
- // don't fit.
+ // Currently we allow 16 bits for the class id and the overall processor key size.
static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
- if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) {
- return false;
- }
- if (processorKeySize > SK_MaxU16) {
+ if ((processorKeySize | classID) & kMetaKeyInvalidMask) {
return false;
}
- uint32_t* key = b->add32n(2);
- key[0] = (textureKey << 16 | transformKey);
- key[1] = (classID << 16 | SkToU16(processorKeySize));
+ uint32_t* key = b->add32n(3);
+ key[0] = (classID << 16) | SkToU32(processorKeySize);
+ key[1] = textureKey;
+ key[2] = transformKey;
return true;
}
-/*
- * TODO: A better name for this function would be "compute" instead of "get".
- */
-static bool get_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
+static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
const GrFragmentProcessor& fp,
const GrGLCaps& caps,
GrProcessorKeyBuilder* b) {
for (int i = 0; i < fp.numChildProcessors(); ++i) {
- if (!get_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), caps, b)) {
+ if (!gen_frag_proc_and_meta_keys(primProc, fp.childProcessor(i), caps, b)) {
return false;
}
}
@@ -91,7 +88,7 @@ static bool get_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
fp.getGLSLProcessorKey(*caps.glslCaps(), b);
//**** use glslCaps here?
- return get_meta_key(fp, caps, primProc.getTransformKey(fp.coordTransforms(),
+ return gen_meta_key(fp, caps, primProc.getTransformKey(fp.coordTransforms(),
fp.numTransformsExclChildren()), b);
}
@@ -115,14 +112,14 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
primProc.getGLSLProcessorKey(*gpu->glCaps().glslCaps(), &b);
//**** use glslCaps here?
- if (!get_meta_key(primProc, gpu->glCaps(), 0, &b)) {
+ if (!gen_meta_key(primProc, gpu->glCaps(), 0, &b)) {
glDesc->key().reset();
return false;
}
for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
const GrFragmentProcessor& fp = pipeline.getFragmentProcessor(i);
- if (!get_frag_proc_and_meta_keys(primProc, fp, gpu->glCaps(), &b)) {
+ if (!gen_frag_proc_and_meta_keys(primProc, fp, gpu->glCaps(), &b)) {
glDesc->key().reset();
return false;
}
@@ -131,7 +128,7 @@ bool GrGLProgramDescBuilder::Build(GrProgramDesc* desc,
const GrXferProcessor& xp = *pipeline.getXferProcessor();
xp.getGLSLProcessorKey(*gpu->glCaps().glslCaps(), &b);
//**** use glslCaps here?
- if (!get_meta_key(xp, gpu->glCaps(), 0, &b)) {
+ if (!gen_meta_key(xp, gpu->glCaps(), 0, &b)) {
glDesc->key().reset();
return false;
}
diff --git a/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp b/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
index 834e122f57..05afb2cb1c 100644
--- a/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
+++ b/src/gpu/gl/angle/GrGLCreateANGLEInterface.cpp
@@ -12,8 +12,20 @@
#include <EGL/egl.h>
+namespace {
+struct Libs {
+ void* fGLLib;
+ void* fEGLLib;
+};
+}
+
static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
- GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(ctx, name);
+ const Libs* libs = reinterpret_cast<const Libs*>(ctx);
+ GrGLFuncPtr proc = (GrGLFuncPtr) GetProcedureAddress(libs->fGLLib, name);
+ if (proc) {
+ return proc;
+ }
+ proc = (GrGLFuncPtr) GetProcedureAddress(libs->fEGLLib, name);
if (proc) {
return proc;
}
@@ -21,23 +33,26 @@ static GrGLFuncPtr angle_get_gl_proc(void* ctx, const char name[]) {
}
const GrGLInterface* GrGLCreateANGLEInterface() {
- static void* gANGLELib = nullptr;
+ static Libs gLibs = { nullptr, nullptr };
- if (nullptr == gANGLELib) {
+ if (nullptr == gLibs.fGLLib) {
// We load the ANGLE library and never let it go
#if defined _WIN32
- gANGLELib = DynamicLoadLibrary("libGLESv2.dll");
+ gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.dll");
+ gLibs.fEGLLib = DynamicLoadLibrary("libEGL.dll");
#elif defined SK_BUILD_FOR_MAC
- gANGLELib = DynamicLoadLibrary("libGLESv2.dylib");
+ gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.dylib");
+ gLibs.fEGLLib = DynamicLoadLibrary("libEGL.dylib");
#else
- gANGLELib = DynamicLoadLibrary("libGLESv2.so");
-#endif // defined _WIN32
+ gLibs.fGLLib = DynamicLoadLibrary("libGLESv2.so");
+ gLibs.fGLLib = DynamicLoadLibrary("libEGL.so");
+#endif
}
- if (nullptr == gANGLELib) {
+ if (nullptr == gLibs.fGLLib || nullptr == gLibs.fEGLLib) {
// We can't setup the interface correctly w/o the so
return nullptr;
}
- return GrGLAssembleGLESInterface(gANGLELib, angle_get_gl_proc);
+ return GrGLAssembleGLESInterface(&gLibs, angle_get_gl_proc);
}
diff --git a/src/gpu/gl/angle/SkANGLEGLContext.cpp b/src/gpu/gl/angle/SkANGLEGLContext.cpp
index 64a3bdec74..54ef02d492 100644
--- a/src/gpu/gl/angle/SkANGLEGLContext.cpp
+++ b/src/gpu/gl/angle/SkANGLEGLContext.cpp
@@ -11,6 +11,9 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include "gl/GrGLDefines.h"
+#include "gl/GrGLUtil.h"
+
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
@@ -34,8 +37,7 @@ void* SkANGLEGLContext::GetD3DEGLDisplay(void* nativeDisplay, bool useGLBackend)
EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
EGL_NONE
};
- display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
- nativeDisplay, attribs);
+ display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
} else {
// Try for an ANGLE D3D11 context, fall back to D3D9, and finally GL.
EGLint attribs[3][3] = {
@@ -56,8 +58,7 @@ void* SkANGLEGLContext::GetD3DEGLDisplay(void* nativeDisplay, bool useGLBackend)
}
};
for (int i = 0; i < 3 && display == EGL_NO_DISPLAY; ++i) {
- display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
- nativeDisplay, attribs[i]);
+ display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,nativeDisplay, attribs[i]);
}
}
return display;
@@ -79,6 +80,7 @@ SkANGLEGLContext::SkANGLEGLContext(bool useGLBackend)
EGL_NONE
};
+ fIsGLBackend = useGLBackend;
fDisplay = GetD3DEGLDisplay(EGL_DEFAULT_DISPLAY, useGLBackend);
if (EGL_NO_DISPLAY == fDisplay) {
SkDebugf("Could not create EGL display!");
@@ -129,6 +131,62 @@ SkANGLEGLContext::~SkANGLEGLContext() {
this->destroyGLContext();
}
+GrEGLImage SkANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
+ if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
+ return GR_EGL_NO_IMAGE;
+ }
+ GrEGLImage img;
+ GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
+ GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
+ GR_EGL_NONE };
+ // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
+ GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
+ GR_GL_CALL_RET(this->gl(), img,
+ EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
+ attribs));
+ return img;
+}
+
+void SkANGLEGLContext::destroyEGLImage(GrEGLImage image) const {
+ GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
+}
+
+GrGLuint SkANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
+ GrGLClearErr(this->gl());
+ if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
+ return 0;
+ }
+ GrGLEGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
+ (GrGLEGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
+ if (!glEGLImageTargetTexture2D) {
+ return 0;
+ }
+ GrGLuint texID;
+ GR_GL_CALL(this->gl(), GenTextures(1, &texID));
+ if (!texID) {
+ return 0;
+ }
+ GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
+ if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
+ return 0;
+ }
+ glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
+ if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
+ GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
+ return 0;
+ }
+ return texID;
+}
+
+SkGLContext* SkANGLEGLContext::createNew() const {
+ SkGLContext* ctx = SkANGLEGLContext::Create(this->gl()->fStandard, fIsGLBackend);
+ if (ctx) {
+ ctx->makeCurrent();
+ }
+ return ctx;
+}
+
void SkANGLEGLContext::destroyGLContext() {
if (fDisplay) {
eglMakeCurrent(fDisplay, 0, 0, 0);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 0ae4f96101..b5108a74d0 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -319,6 +319,16 @@ void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
SkASSERT(fFS.hasReadFragmentPosition() == fp.willReadFragmentPosition());
}
+static GrSLType get_sampler_type(const GrTextureAccess& access) {
+ GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture());
+ if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) {
+ return kSamplerExternal_GrSLType;
+ } else {
+ SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D);
+ return kSampler2D_GrSLType;
+ }
+}
+
template <class Proc>
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
GrGLSLTextureSampler::TextureSamplerArray* outSamplers,
@@ -329,11 +339,19 @@ void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
SkString name;
for (int t = 0; t < numTextures; ++t) {
name.printf("Sampler%d", t);
+ GrSLType samplerType = get_sampler_type(processor.textureAccess(t));
localSamplerUniforms[t] = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kSampler2D_GrSLType, kDefault_GrSLPrecision,
+ samplerType, kDefault_GrSLPrecision,
name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLSLTextureSampler,
(localSamplerUniforms[t], processor.textureAccess(t)));
+ if (kSamplerExternal_GrSLType == samplerType) {
+ const char* externalFeatureString = this->glslCaps()->externalTextureExtensionString();
+ // We shouldn't ever create a GrGLTexture that requires external sampler type
+ SkASSERT(externalFeatureString);
+ fFS.addFeature(1 << GrGLSLFragmentShaderBuilder::kExternalTexture_GLSLPrivateFeature,
+ externalFeatureString);
+ }
}
}
diff --git a/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp b/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp
index 703e39d097..fef4f0276f 100644
--- a/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp
+++ b/src/gpu/gl/egl/GrGLCreateNativeInterface_egl.cpp
@@ -14,7 +14,15 @@
static GrGLFuncPtr egl_get_gl_proc(void* ctx, const char name[]) {
SkASSERT(nullptr == ctx);
- return eglGetProcAddress(name);
+ GrGLFuncPtr ptr = eglGetProcAddress(name);
+ if (!ptr) {
+ if (0 == strcmp("eglQueryString", name)) {
+ return (GrGLFuncPtr)eglQueryString;
+ } else if (0 == strcmp("eglGetCurrentDisplay", name)) {
+ return (GrGLFuncPtr)eglGetCurrentDisplay;
+ }
+ }
+ return ptr;
}
const GrGLInterface* GrGLCreateNativeInterface() {
diff --git a/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp b/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp
index d1335d355f..591cae349c 100644
--- a/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp
+++ b/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp
@@ -13,6 +13,9 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include "gl/GrGLDefines.h"
+#include "gl/GrGLUtil.h"
+
namespace {
// TODO: Share this class with ANGLE if/when it gets support for EGL_KHR_fence_sync.
@@ -37,6 +40,11 @@ public:
EGLGLContext(GrGLStandard forcedGpuAPI);
~EGLGLContext() override;
+ GrEGLImage texture2DToEGLImage(GrGLuint texID) const override;
+ void destroyEGLImage(GrEGLImage) const override;
+ GrGLuint eglImageToExternalTexture(GrEGLImage) const override;
+ SkGLContext* createNew() const override;
+
private:
void destroyGLContext();
@@ -200,6 +208,57 @@ void EGLGLContext::destroyGLContext() {
}
}
+GrEGLImage EGLGLContext::texture2DToEGLImage(GrGLuint texID) const {
+ if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
+ return GR_EGL_NO_IMAGE;
+ }
+ GrEGLImage img;
+ GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0, GR_EGL_NONE };
+ GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>(texID);
+ GR_GL_CALL_RET(this->gl(), img,
+ EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer, attribs));
+ return img;
+}
+
+void EGLGLContext::destroyEGLImage(GrEGLImage image) const {
+ GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
+}
+
+GrGLuint EGLGLContext::eglImageToExternalTexture(GrEGLImage image) const {
+ GrGLClearErr(this->gl());
+ if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
+ return 0;
+ }
+ GrGLEGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
+ (GrGLEGLImageTargetTexture2DProc) eglGetProcAddress("glEGLImageTargetTexture2DOES");
+ if (!glEGLImageTargetTexture2D) {
+ return 0;
+ }
+ GrGLuint texID;
+ glGenTextures(1, &texID);
+ if (!texID) {
+ return 0;
+ }
+ glBindTexture(GR_GL_TEXTURE_EXTERNAL, texID);
+ if (glGetError() != GR_GL_NO_ERROR) {
+ glDeleteTextures(1, &texID);
+ return 0;
+ }
+ glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
+ if (glGetError() != GR_GL_NO_ERROR) {
+ glDeleteTextures(1, &texID);
+ return 0;
+ }
+ return texID;
+}
+
+SkGLContext* EGLGLContext::createNew() const {
+ SkGLContext* ctx = SkCreatePlatformGLContext(this->gl()->fStandard);
+ if (ctx) {
+ ctx->makeCurrent();
+ }
+ return ctx;
+}
void EGLGLContext::onPlatformMakeCurrent() const {
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {