Beginning of support for texture rectangles.
Adds support for importing a RECTANGLE texture into Skia via GrTexureProvider::wrapBackendTexture().
Tests read/writing pixels, copySurface, and clear.
Does not add support for texturing from a RECTANGLE texture as the coords will be incorrectly normalized.
BUG=skia:3868
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1583863002
Review URL: https://codereview.chromium.org/1583863002
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index a637e8e..b64ff64 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -39,6 +39,7 @@
'<(skia_include_path)/gpu/GrTextureAccess.h',
'<(skia_include_path)/gpu/GrTestUtils.h',
'<(skia_include_path)/gpu/GrTypes.h',
+ '<(skia_include_path)/gpu/GrTypesPriv.h',
'<(skia_include_path)/gpu/GrXferProcessor.h',
'<(skia_include_path)/gpu/effects/GrConstColorProcessor.h',
diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h
index 6a9c44f..c46e25b 100644
--- a/include/gpu/GrTypesPriv.h
+++ b/include/gpu/GrTypesPriv.h
@@ -26,8 +26,9 @@
kMat44f_GrSLType,
kSampler2D_GrSLType,
kSamplerExternal_GrSLType,
+ kSampler2DRect_GrSLType,
- kLast_GrSLType = kSamplerExternal_GrSLType
+ kLast_GrSLType = kSampler2DRect_GrSLType
};
static const int kGrSLTypeCount = kLast_GrSLType + 1;
@@ -64,7 +65,7 @@
*/
static inline int GrSLTypeVectorCount(GrSLType type) {
SkASSERT(type >= 0 && type < static_cast<GrSLType>(kGrSLTypeCount));
- static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1, -1 };
+ static const int kCounts[] = { -1, 1, 2, 3, 4, -1, -1, -1, -1, -1 };
return kCounts[type];
GR_STATIC_ASSERT(0 == kVoid_GrSLType);
@@ -76,6 +77,7 @@
GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
+ GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
GR_STATIC_ASSERT(SK_ARRAY_COUNT(kCounts) == kGrSLTypeCount);
}
@@ -105,7 +107,8 @@
GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
- GR_STATIC_ASSERT(9 == kGrSLTypeCount);
+ GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
+ GR_STATIC_ASSERT(10 == kGrSLTypeCount);
}
/** Returns the size in bytes for floating point GrSLTypes. For non floating point type returns 0 */
@@ -120,7 +123,8 @@
9 * sizeof(float), // kMat33f_GrSLType
16 * sizeof(float), // kMat44f_GrSLType
0, // kSampler2D_GrSLType
- 0 // kSamplerExternal_GrSLType
+ 0, // kSamplerExternal_GrSLType
+ 0 // kSampler2DRect_GrSLType
};
return kSizes[type];
@@ -133,7 +137,17 @@
GR_STATIC_ASSERT(6 == kMat44f_GrSLType);
GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
- GR_STATIC_ASSERT(9 == kGrSLTypeCount);
+ GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
+ GR_STATIC_ASSERT(10 == kGrSLTypeCount);
+}
+
+static inline bool GrSLTypeIsSamplerType(GrSLType type) {
+ SkASSERT(type >= 0 && type < static_cast<GrSLType>(kGrSLTypeCount));
+ return type >= 7 && type <= 9;
+
+ GR_STATIC_ASSERT(7 == kSampler2D_GrSLType);
+ GR_STATIC_ASSERT(8 == kSamplerExternal_GrSLType);
+ GR_STATIC_ASSERT(9 == kSampler2DRect_GrSLType);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/include/gpu/gl/SkGLContext.h b/include/gpu/gl/SkGLContext.h
index 7edfa73..77fd325 100644
--- a/include/gpu/gl/SkGLContext.h
+++ b/include/gpu/gl/SkGLContext.h
@@ -41,6 +41,11 @@
virtual GrEGLImage texture2DToEGLImage(GrGLuint /*texID*/) const { return 0; }
virtual void destroyEGLImage(GrEGLImage) const {}
+ /** Used for testing GL_TEXTURE_RECTANGLE integration. */
+ GrGLint createTextureRectangle(int width, int height, GrGLenum internalFormat,
+ GrGLenum externalFormat, GrGLenum externalType,
+ GrGLvoid* data);
+
/**
* Used for testing EGLImage integration. Takes a EGLImage and wraps it in a
* GL_TEXTURE_EXTERNAL_OES.
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 678c62a..ddc52cc 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -42,6 +42,7 @@
fIsCoreProfile = false;
fBindFragDataLocationSupport = false;
fExternalTextureSupport = false;
+ fRectangleTextureSupport = false;
fTextureSwizzleSupport = false;
fSRGBWriteControl = false;
fRGBA8888PixelsOpsAreSlow = false;
@@ -219,6 +220,11 @@
}
}
+ if ((kGL_GrGLStandard == standard && version >= GR_GL_VER(3, 2)) ||
+ ctxInfo.hasExtension("GL_ARB_texture_rectangle")) {
+ fRectangleTextureSupport = true;
+ }
+
if (kGL_GrGLStandard == standard) {
if (version >= GR_GL_VER(3,3) || ctxInfo.hasExtension("GL_ARB_texture_swizzle")) {
fTextureSwizzleSupport = true;
@@ -885,6 +891,7 @@
r.appendf("Partial FBO read is slow: %s\n", (fPartialFBOReadIsSlow ? "YES" : "NO"));
r.appendf("Bind uniform location support: %s\n", (fBindUniformLocationSupport ? "YES" : "NO"));
r.appendf("External texture support: %s\n", (fExternalTextureSupport ? "YES" : "NO"));
+ r.appendf("Rectangle texture support: %s\n", (fRectangleTextureSupport? "YES" : "NO"));
r.appendf("Texture swizzle support: %s\n", (fTextureSwizzleSupport ? "YES" : "NO"));
r.append("Configs\n-------\n");
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index c51dce1..c4f4270 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -297,6 +297,9 @@
/// Are textures with GL_TEXTURE_EXTERNAL_OES type supported.
bool externalTextureSupport() const { return fExternalTextureSupport; }
+ /// Are textures with GL_TEXTURE_RECTANGLE type supported.
+ bool rectangleTextureSupport() const { return fRectangleTextureSupport; }
+
/// GL_ARB_texture_swizzle
bool textureSwizzleSupport() const { return fTextureSwizzleSupport; }
@@ -377,6 +380,7 @@
bool fPartialFBOReadIsSlow : 1;
bool fBindUniformLocationSupport : 1;
bool fExternalTextureSupport : 1;
+ bool fRectangleTextureSupport : 1;
bool fTextureSwizzleSupport : 1;
/** Number type of the components (with out considering number of bits.) */
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index 228f258..318fcd4 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -939,6 +939,9 @@
/* GL_OES_EGL_image_external */
#define GR_GL_TEXTURE_EXTERNAL 0x8D65
+/* GL_ARB_texture_rectangle */
+#define GR_GL_TEXTURE_RECTANGLE 0x84F5
+
/* EGL Defines */
#define GR_EGL_NO_DISPLAY ((GrEGLDisplay)0)
#define GR_EGL_EXTENSIONS 0x3055
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 41d2da0..248a5df 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -447,6 +447,7 @@
#else
idDesc.fInfo = *info;
#endif
+
if (GR_GL_TEXTURE_EXTERNAL == idDesc.fInfo.fTarget) {
if (renderTarget) {
// This combination is not supported.
@@ -455,8 +456,15 @@
if (!this->glCaps().externalTextureSupport()) {
return nullptr;
}
+ } else if (GR_GL_TEXTURE_RECTANGLE == idDesc.fInfo.fTarget) {
+ if (!this->glCaps().rectangleTextureSupport()) {
+ return nullptr;
+ }
+ } else if (GR_GL_TEXTURE_2D != idDesc.fInfo.fTarget) {
+ return nullptr;
}
- // Sample count is interpretted to mean the number of samples that Gr code should allocate
+
+ // Sample count is interpreted to mean the number of samples that Gr code should allocate
// for a render buffer that resolves to the texture. We don't support MSAA textures.
if (desc.fSampleCnt && !renderTarget) {
return nullptr;
@@ -469,7 +477,7 @@
case kBorrow_GrWrapOwnership:
idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
break;
- }
+ }
surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
surfDesc.fWidth = desc.fWidth;
@@ -546,8 +554,8 @@
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.
+ if (GR_GL_TEXTURE_EXTERNAL == texture->target()) {
+ // We don't currently support writing pixels to EXTERNAL textures.
return false;
}
}
@@ -608,8 +616,8 @@
return false;
}
- // Write or transfer of pixels is only implemented for TEXTURE_2D textures
- if (GR_GL_TEXTURE_2D != glTex->target()) {
+ // Write or transfer of pixels is not implemented for TEXTURE_EXTERNAL textures
+ if (GR_GL_TEXTURE_EXTERNAL == glTex->target()) {
return false;
}
@@ -2876,10 +2884,18 @@
fCopyPrograms[i].fProgram = 0;
}
const char* version = this->glCaps().glslCaps()->versionDeclString();
- 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) {
+ static const GrSLType kSamplerTypes[3] = { kSampler2D_GrSLType, kSamplerExternal_GrSLType,
+ kSampler2DRect_GrSLType };
+ SkASSERT(3 == SK_ARRAY_COUNT(fCopyPrograms));
+ for (int i = 0; i < 3; ++i) {
+ if (kSamplerExternal_GrSLType == kSamplerTypes[i] &&
+ !this->glCaps().externalTextureSupport()) {
+ continue;
+ }
+ if (kSampler2DRect_GrSLType == kSamplerTypes[i] &&
+ !this->glCaps().rectangleTextureSupport()) {
+ continue;
+ }
GrGLSLShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kAttribute_TypeModifier);
GrGLSLShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
GrShaderVar::kUniform_TypeModifier);
@@ -2938,7 +2954,7 @@
" %s = %s(u_texture, v_texCoord);"
"}",
fsOutName,
- GrGLSLTexture2DFunctionName(kVec2f_GrSLType, this->glslGeneration())
+ GrGLSLTexture2DFunctionName(kVec2f_GrSLType, kSamplerTypes[i], this->glslGeneration())
);
GL_CALL_RET(fCopyPrograms[i].fProgram, CreateProgram());
@@ -3183,16 +3199,23 @@
dy1 = -dy1;
}
- // src rect edges in normalized texture space (0 to 1)
- int sw = src->width();
+ GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft;
+ GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w);
+ GrGLfloat sy0 = (GrGLfloat)srcRect.fTop;
+ GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h);
int sh = src->height();
- GrGLfloat sx0 = (GrGLfloat)srcRect.fLeft / sw;
- GrGLfloat sx1 = (GrGLfloat)(srcRect.fLeft + w) / sw;
- GrGLfloat sy0 = (GrGLfloat)srcRect.fTop / sh;
- GrGLfloat sy1 = (GrGLfloat)(srcRect.fTop + h) / sh;
if (kBottomLeft_GrSurfaceOrigin == src->origin()) {
- sy0 = 1.f - sy0;
- sy1 = 1.f - sy1;
+ sy0 = sh - sy0;
+ sy1 = sh - sy1;
+ }
+ // src rect edges in normalized texture space (0 to 1) unless we're using a RECTANGLE texture.
+ GrGLenum srcTarget = srcTex->target();
+ if (GR_GL_TEXTURE_RECTANGLE != srcTarget) {
+ int sw = src->width();
+ sx0 /= sw;
+ sx1 /= sw;
+ sy0 /= sh;
+ sy1 /= sh;
}
GL_CALL(Uniform4f(fCopyPrograms[progIdx].fPosXformUniform, dx1 - dx0, dy1 - dy0, dx0, dy0));
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index cdd8a38..b2eec45 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -524,7 +524,7 @@
GrGLint fTextureUniform;
GrGLint fTexCoordXformUniform;
GrGLint fPosXformUniform;
- } fCopyPrograms[2];
+ } fCopyPrograms[3];
GrGLuint fCopyProgramArrayBuffer;
struct {
@@ -535,11 +535,16 @@
GrGLuint fWireRectArrayBuffer;
static int TextureTargetToCopyProgramIdx(GrGLenum target) {
- if (target == GR_GL_TEXTURE_2D) {
- return 0;
- } else {
- SkASSERT(target == GR_GL_TEXTURE_EXTERNAL);
- return 1;
+ switch (target) {
+ case GR_GL_TEXTURE_2D:
+ return 0;
+ case GR_GL_TEXTURE_EXTERNAL:
+ return 1;
+ case GR_GL_TEXTURE_RECTANGLE:
+ return 2;
+ default:
+ SkFAIL("Unexpected texture target type.");
+ return 0;
}
}
diff --git a/src/gpu/gl/GrGLProgramDataManager.cpp b/src/gpu/gl/GrGLProgramDataManager.cpp
index 54ca73a..06f568e 100644
--- a/src/gpu/gl/GrGLProgramDataManager.cpp
+++ b/src/gpu/gl/GrGLProgramDataManager.cpp
@@ -63,7 +63,8 @@
void GrGLProgramDataManager::setSampler(UniformHandle u, int texUnit) const {
const Uniform& uni = fUniforms[u.toIndex()];
- SkASSERT(uni.fType == kSampler2D_GrSLType || uni.fType == kSamplerExternal_GrSLType);
+ SkASSERT(uni.fType == kSampler2D_GrSLType || uni.fType == kSamplerExternal_GrSLType ||
+ uni.fType == kSampler2DRect_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 4c95e2b..5edacf5 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -7,12 +7,19 @@
#include "GrGLProgramDesc.h"
#include "GrProcessor.h"
-#include "GrGLGpu.h"
#include "GrPipeline.h"
#include "SkChecksum.h"
+#include "gl/GrGLDefines.h"
+#include "gl/GrGLTexture.h"
+#include "gl/GrGLTypes.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLCaps.h"
+static uint16_t texture_target_key(GrGLenum target) {
+ SkASSERT((uint32_t)target < SK_MaxU16);
+ return target;
+}
static void add_texture_key(GrProcessorKeyBuilder* b, const GrProcessor& proc,
const GrGLSLCaps& caps) {
@@ -25,10 +32,9 @@
uint16_t* k16 = SkTCast<uint16_t*>(b->add32n(word32Count));
for (int i = 0; i < numTextures; ++i) {
const GrTextureAccess& access = proc.textureAccess(i);
- bool isExternal = (GR_GL_TEXTURE_EXTERNAL ==
- static_cast<GrGLTexture*>(access.getTexture())->target());
- k16[i] = caps.configTextureSwizzle(access.getTexture()->config()).asKey() |
- (isExternal ? 0xFF00 : 0x0000);
+ GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture());
+ k16[i] = caps.configTextureSwizzle(texture->config()).asKey() |
+ (texture_target_key(texture->target()) << 16);
}
// zero the last 16 bits if the number of textures is odd.
if (numTextures & 0x1) {
diff --git a/src/gpu/gl/SkGLContext.cpp b/src/gpu/gl/SkGLContext.cpp
index ec318cb..07c61f7 100644
--- a/src/gpu/gl/SkGLContext.cpp
+++ b/src/gpu/gl/SkGLContext.cpp
@@ -152,3 +152,26 @@
GLsync glsync = static_cast<GLsync>(fence);
fGLDeleteSync(glsync);
}
+
+GrGLint SkGLContext::createTextureRectangle(int width, int height, GrGLenum internalFormat,
+ GrGLenum externalFormat, GrGLenum externalType,
+ GrGLvoid* data) {
+ if (!(kGL_GrGLStandard == fGL->fStandard && GrGLGetVersion(fGL) >= GR_GL_VER(3, 2)) &&
+ !fGL->fExtensions.has("GL_ARB_texture_rectangle")) {
+ return 0;
+ }
+ GrGLuint id;
+ GR_GL_CALL(fGL, GenTextures(1, &id));
+ GR_GL_CALL(fGL, BindTexture(GR_GL_TEXTURE_RECTANGLE, id));
+ GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MAG_FILTER,
+ GR_GL_NEAREST));
+ GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_MIN_FILTER,
+ GR_GL_NEAREST));
+ GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_S,
+ GR_GL_CLAMP_TO_EDGE));
+ GR_GL_CALL(fGL, TexParameteri(GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_WRAP_T,
+ GR_GL_CLAMP_TO_EDGE));
+ GR_GL_CALL(fGL, TexImage2D(GR_GL_TEXTURE_RECTANGLE, 0, internalFormat, width, height, 0,
+ externalFormat, externalType, data));
+ return id;
+}
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 4503d1a..4a1b2e9 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -74,6 +74,8 @@
GrGLTexture* glTexture = static_cast<GrGLTexture*>(access.getTexture());
if (glTexture->target() == GR_GL_TEXTURE_EXTERNAL) {
return kSamplerExternal_GrSLType;
+ } else if (glTexture->target() == GR_GL_TEXTURE_RECTANGLE) {
+ return kSampler2DRect_GrSLType;
} else {
SkASSERT(glTexture->target() == GR_GL_TEXTURE_2D);
return kSampler2D_GrSLType;
diff --git a/src/gpu/glsl/GrGLSL.h b/src/gpu/glsl/GrGLSL.h
index ac38522..f2accc5 100644
--- a/src/gpu/glsl/GrGLSL.h
+++ b/src/gpu/glsl/GrGLSL.h
@@ -48,12 +48,23 @@
* Gets the name of the function that should be used to sample a 2D texture. Coord type is used
* to indicate whether the texture is sampled using projective textured (kVec3f) or not (kVec2f).
*/
-inline const char* GrGLSLTexture2DFunctionName(GrSLType coordType, GrGLSLGeneration glslGen) {
+inline const char* GrGLSLTexture2DFunctionName(GrSLType coordType, GrSLType samplerType,
+ GrGLSLGeneration glslGen) {
+ SkASSERT(GrSLTypeIsSamplerType(samplerType));
+ SkASSERT(kVec2f_GrSLType == coordType || kVec3f_GrSLType == coordType);
+ // GL_TEXTURE_RECTANGLE_ARB is written against OpenGL 2.0/GLSL 1.10. At that time there were
+ // separate texture*() functions. In OpenGL 3.0/GLSL 1.30 the different texture*() functions
+ // were deprecated in favor or the unified texture() function. RECTANGLE textures became
+ // standard in OpenGL 3.2/GLSL 1.50 and use texture(). It isn't completely clear what function
+ // should be used for RECTANGLE textures in GLSL versions >= 1.30 && < 1.50. We're going with
+ // using texture().
+ if (glslGen >= k130_GrGLSLGeneration) {
+ return (kVec2f_GrSLType == coordType) ? "texture" : "textureProj";
+ }
if (kVec2f_GrSLType == coordType) {
- return glslGen >= k130_GrGLSLGeneration ? "texture" : "texture2D";
+ return (samplerType == kSampler2DRect_GrSLType) ? "texture2DRect" : "texture2D";
} else {
- SkASSERT(kVec3f_GrSLType == coordType);
- return glslGen >= k130_GrGLSLGeneration ? "textureProj" : "texture2DProj";
+ return (samplerType == kSampler2DRect_GrSLType) ? "texture2DRectProj" : "texture2DProj";
}
}
@@ -87,6 +98,8 @@
return "sampler2D";
case kSamplerExternal_GrSLType:
return "samplerExternalOES";
+ case kSampler2DRect_GrSLType:
+ return "sampler2DRect";
default:
SkFAIL("Unknown shader var type.");
return ""; // suppress warning
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index 2d2ff87..f1ede1d 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -62,8 +62,9 @@
GrSLType varyingType) const {
const GrGLSLCaps* glslCaps = fProgramBuilder->glslCaps();
GrGLSLUniformHandler* uniformHandler = fProgramBuilder->uniformHandler();
+ GrSLType samplerType = uniformHandler->getUniformVariable(sampler.fSamplerUniform).getType();
out->appendf("%s(%s, %s)",
- GrGLSLTexture2DFunctionName(varyingType, glslCaps->generation()),
+ GrGLSLTexture2DFunctionName(varyingType, samplerType, glslCaps->generation()),
uniformHandler->getUniformCStr(sampler.fSamplerUniform),
coordName);
diff --git a/tests/RectangleTextureTest.cpp b/tests/RectangleTextureTest.cpp
new file mode 100644
index 0000000..a98dd34
--- /dev/null
+++ b/tests/RectangleTextureTest.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+#if SK_SUPPORT_GPU
+#include "GrContext.h"
+#include "GrDrawContext.h"
+#include "gl/GrGLGpu.h"
+#include "gl/GrGLUtil.h"
+#include "gl/SkGLContext.h"
+
+static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context,
+ GrTexture* rectangleTexture, uint32_t expectedPixelValues[]) {
+ int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
+ SkAutoTMalloc<uint32_t> pixels(pixelCnt);
+ memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
+ bool read = rectangleTexture->readPixels(0, 0, rectangleTexture->width(),
+ rectangleTexture->height(), kRGBA_8888_GrPixelConfig,
+ pixels.get());
+ if (!read) {
+ ERRORF(reporter, "Error reading rectangle texture.");
+ }
+ for (int i = 0; i < pixelCnt; ++i) {
+ if (pixels.get()[i] != expectedPixelValues[i]) {
+ ERRORF(reporter, "Error, rectangle texture pixel value %d should be 0x%08x,"
+ " got 0x%08x.", i, expectedPixelValues[i], pixels.get()[i]);
+ break;
+ }
+ }
+}
+
+static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context,
+ GrTexture* rectangleTexture) {
+ int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
+ SkAutoTMalloc<uint32_t> pixels(pixelCnt);
+ for (int y = 0; y < rectangleTexture->width(); ++y) {
+ for (int x = 0; x < rectangleTexture->height(); ++x) {
+ pixels.get()[y * rectangleTexture->width() + x] = GrColorPackRGBA(x, y, x + y, x * y);
+ }
+ }
+ bool write = rectangleTexture->writePixels(0, 0, rectangleTexture->width(),
+ rectangleTexture->height(), kRGBA_8888_GrPixelConfig,
+ pixels.get());
+ if (!write) {
+ ERRORF(reporter, "Error writing to rectangle texture.");
+ }
+ test_read_pixels(reporter, context, rectangleTexture, pixels.get());
+}
+
+static void test_copy_surface_src(skiatest::Reporter* reporter, GrContext* context,
+ GrTexture* rectangleTexture, uint32_t expectedPixelValues[]) {
+ GrSurfaceDesc copyDstDesc;
+ copyDstDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ copyDstDesc.fWidth = rectangleTexture->width();
+ copyDstDesc.fHeight = rectangleTexture->height();
+ copyDstDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+ SkAutoTUnref<GrTexture> dst(context->textureProvider()->createTexture(copyDstDesc, true));
+ context->copySurface(dst, rectangleTexture);
+ test_read_pixels(reporter, context, dst, expectedPixelValues);
+}
+
+static void test_copy_surface_dst(skiatest::Reporter* reporter, GrContext* context,
+ GrTexture* rectangleTexture) {
+ int pixelCnt = rectangleTexture->width() * rectangleTexture->height();
+ SkAutoTMalloc<uint32_t> pixels(pixelCnt);
+ for (int y = 0; y < rectangleTexture->width(); ++y) {
+ for (int x = 0; x < rectangleTexture->height(); ++x) {
+ pixels.get()[y * rectangleTexture->width() + x] = GrColorPackRGBA(y, x, x * y, x *+ y);
+ }
+ }
+
+ GrSurfaceDesc copySrcDesc;
+ copySrcDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ copySrcDesc.fWidth = rectangleTexture->width();
+ copySrcDesc.fHeight = rectangleTexture->height();
+ copySrcDesc.fFlags = kRenderTarget_GrSurfaceFlag;
+ SkAutoTUnref<GrTexture> src(context->textureProvider()->createTexture(copySrcDesc, true,
+ pixels.get(), 0));
+
+ context->copySurface(rectangleTexture, src);
+ test_read_pixels(reporter, context, rectangleTexture, pixels.get());
+}
+
+static void test_clear(skiatest::Reporter* reporter, GrContext* context,
+ GrTexture* rectangleTexture) {
+ if (rectangleTexture->asRenderTarget()) {
+ SkAutoTUnref<GrDrawContext> dc(context->drawContext(rectangleTexture->asRenderTarget()));
+ if (!dc) {
+ ERRORF(reporter, "Could not get GrDrawContext for rectangle texture.");
+ return;
+ }
+
+ // Clear the whole thing.
+ GrColor color0 = GrColorPackRGBA(0xA, 0xB, 0xC, 0xD);
+ dc->clear(nullptr, color0, false);
+
+ int w = rectangleTexture->width();
+ int h = rectangleTexture->height();
+ int pixelCnt = w * h;
+ SkAutoTMalloc<uint32_t> expectedPixels(pixelCnt);
+
+ // The clear color is a GrColor, our readback is to kRGBA_8888, which may be different.
+ uint32_t expectedColor0;
+ uint8_t* expectedBytes0 = SkTCast<uint8_t*>(&expectedColor0);
+ expectedBytes0[0] = GrColorUnpackR(color0);
+ expectedBytes0[1] = GrColorUnpackG(color0);
+ expectedBytes0[2] = GrColorUnpackB(color0);
+ expectedBytes0[3] = GrColorUnpackA(color0);
+ for (int i = 0; i < rectangleTexture->width() * rectangleTexture->height(); ++i) {
+ expectedPixels.get()[i] = expectedColor0;
+ }
+
+ // Clear the the top to a different color.
+ GrColor color1 = GrColorPackRGBA(0x1, 0x2, 0x3, 0x4);
+ SkIRect rect = SkIRect::MakeWH(w, h/2);
+ dc->clear(&rect, color1, false);
+
+ uint32_t expectedColor1;
+ uint8_t* expectedBytes1 = SkTCast<uint8_t*>(&expectedColor1);
+ expectedBytes1[0] = GrColorUnpackR(color1);
+ expectedBytes1[1] = GrColorUnpackG(color1);
+ expectedBytes1[2] = GrColorUnpackB(color1);
+ expectedBytes1[3] = GrColorUnpackA(color1);
+
+ for (int y = 0; y < h/2; ++y) {
+ for (int x = 0; x < w; ++x) {
+ expectedPixels.get()[y * h + x] = expectedColor1;
+ }
+ }
+
+ test_read_pixels(reporter, context, rectangleTexture, expectedPixels.get());
+ }
+}
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(RectangleTexture, reporter, context, glContext) {
+ static const int kWidth = 13;
+ static const int kHeight = 13;
+
+ GrColor pixels[kWidth * kHeight];
+ for (int y = 0; y < kHeight; ++y) {
+ for (int x = 0; x < kWidth; ++x) {
+ pixels[y * kWidth + x] = y * kWidth + x;
+ }
+ }
+
+ for (int origin = 0; origin < 2; ++origin) {
+ GrGLuint rectTexID = glContext->createTextureRectangle(kWidth, kHeight, GR_GL_RGBA,
+ GR_GL_RGBA, GR_GL_UNSIGNED_BYTE,
+ pixels);
+
+ if (!rectTexID) {
+ return;
+ }
+
+ // Let GrContext know that we messed with the GL context directly.
+ context->resetContext();
+
+ // Wrap the rectangle texture ID in a GrTexture
+ GrGLTextureInfo rectangleInfo;
+ rectangleInfo.fID = rectTexID;
+ rectangleInfo.fTarget = GR_GL_TEXTURE_RECTANGLE;
+
+ GrBackendTextureDesc rectangleDesc;
+ rectangleDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
+ rectangleDesc.fConfig = kRGBA_8888_GrPixelConfig;
+ rectangleDesc.fWidth = kWidth;
+ rectangleDesc.fHeight = kHeight;
+ rectangleDesc.fOrigin = origin ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
+ rectangleDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&rectangleInfo);
+
+ GrColor refPixels[kWidth * kHeight];
+ bool flipRef = rectangleDesc.fOrigin == kBottomLeft_GrSurfaceOrigin;
+ for (int y = 0; y < kHeight; ++y) {
+ for (int x = 0; x < kWidth; ++x) {
+ int y0 = flipRef ? kHeight - y - 1 : y;
+ refPixels[y * kWidth + x] = pixels[y0 * kWidth + x];
+ }
+ }
+
+ SkAutoTUnref<GrTexture> rectangleTexture(
+ context->textureProvider()->wrapBackendTexture(rectangleDesc));
+ if (!rectangleTexture) {
+ ERRORF(reporter, "Error wrapping rectangle texture in GrTexture.");
+ GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID));
+ continue;
+ }
+
+ test_read_pixels(reporter, context, rectangleTexture, refPixels);
+
+ test_copy_surface_src(reporter, context, rectangleTexture, refPixels);
+
+ test_copy_surface_dst(reporter, context, rectangleTexture);
+
+ test_write_pixels(reporter, context, rectangleTexture);
+
+ test_clear(reporter, context, rectangleTexture);
+
+ GR_GL_CALL(glContext->gl(), DeleteTextures(1, &rectTexID));
+ }
+}
+
+#endif