2019-02-08 17:33:08 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2019 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkSurface.h"
|
|
|
|
#include "src/gpu/GrContextPriv.h"
|
|
|
|
#include "src/gpu/gl/GrGLDefines.h"
|
|
|
|
#include "src/gpu/gl/GrGLGpu.h"
|
|
|
|
#include "src/gpu/gl/GrGLUtil.h"
|
|
|
|
#include "tests/Test.h"
|
2019-02-08 17:33:08 +00:00
|
|
|
|
2019-11-08 21:18:15 +00:00
|
|
|
#ifdef SK_GL
|
|
|
|
|
2019-02-08 17:33:08 +00:00
|
|
|
DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(TextureBindingsResetTest, reporter, ctxInfo) {
|
|
|
|
#define GL(F) GR_GL_CALL(ctxInfo.glContext()->gl(), F)
|
|
|
|
|
|
|
|
GrContext* context = ctxInfo.grContext();
|
2019-05-13 14:40:06 +00:00
|
|
|
GrGpu* gpu = context->priv().getGpu();
|
|
|
|
GrGLGpu* glGpu = static_cast<GrGLGpu*>(context->priv().getGpu());
|
2019-02-08 17:33:08 +00:00
|
|
|
|
|
|
|
struct Target {
|
|
|
|
GrGLenum fName;
|
|
|
|
GrGLenum fQuery;
|
|
|
|
};
|
|
|
|
SkTDArray<Target> targets;
|
|
|
|
targets.push_back({GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BINDING_2D});
|
|
|
|
bool supportExternal;
|
2019-05-13 14:40:06 +00:00
|
|
|
if ((supportExternal = glGpu->glCaps().shaderCaps()->externalTextureSupport())) {
|
2019-02-08 17:33:08 +00:00
|
|
|
targets.push_back({GR_GL_TEXTURE_EXTERNAL, GR_GL_TEXTURE_BINDING_EXTERNAL});
|
|
|
|
}
|
|
|
|
bool supportRectangle;
|
2019-05-13 14:40:06 +00:00
|
|
|
if ((supportRectangle = glGpu->glCaps().rectangleTextureSupport())) {
|
2019-02-08 17:33:08 +00:00
|
|
|
targets.push_back({GR_GL_TEXTURE_RECTANGLE, GR_GL_TEXTURE_BINDING_RECTANGLE});
|
|
|
|
}
|
|
|
|
GrGLint numUnits;
|
|
|
|
GL(GetIntegerv(GR_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numUnits));
|
|
|
|
SkTDArray<GrGLuint> claimedIDs;
|
|
|
|
claimedIDs.setCount(numUnits * targets.count());
|
|
|
|
GL(GenTextures(claimedIDs.count(), claimedIDs.begin()));
|
|
|
|
|
|
|
|
auto resetBindings = [&] {
|
|
|
|
int i = 0;
|
|
|
|
for (int u = 0; u < numUnits; ++u) {
|
|
|
|
GL(ActiveTexture(GR_GL_TEXTURE0 + u));
|
|
|
|
for (auto target : targets) {
|
|
|
|
GL(BindTexture(target.fName, claimedIDs[i++]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
auto checkBindings = [&] {
|
|
|
|
int i = 0;
|
|
|
|
for (int u = 0; u < numUnits; ++u) {
|
|
|
|
GL(ActiveTexture(GR_GL_TEXTURE0 + u));
|
|
|
|
for (auto target : targets) {
|
|
|
|
GrGLuint boundID = ~0;
|
|
|
|
GL(GetIntegerv(target.fQuery, reinterpret_cast<GrGLint*>(&boundID)));
|
|
|
|
if (boundID != claimedIDs[i] && boundID != 0) {
|
|
|
|
ERRORF(reporter, "Unit %d, target 0x%04x has ID %d bound. Expected %d or 0.", u,
|
|
|
|
target.fName, boundID, claimedIDs[i]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Initialize texture unit/target combo bindings to 0.
|
|
|
|
context->flush();
|
|
|
|
resetBindings();
|
|
|
|
context->resetContext();
|
|
|
|
|
|
|
|
// Test creating a texture and then resetting bindings.
|
2020-02-07 19:17:25 +00:00
|
|
|
static constexpr SkISize kDims = {10, 10};
|
2019-08-05 16:58:39 +00:00
|
|
|
auto format = gpu->caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888, GrRenderable::kNo);
|
2020-02-07 19:17:25 +00:00
|
|
|
auto tex = gpu->createTexture(kDims, format, GrRenderable::kNo, 1, GrMipMapped::kNo,
|
2019-09-17 13:01:56 +00:00
|
|
|
SkBudgeted::kNo, GrProtected::kNo);
|
2019-02-08 17:33:08 +00:00
|
|
|
REPORTER_ASSERT(reporter, tex);
|
|
|
|
context->resetGLTextureBindings();
|
|
|
|
checkBindings();
|
|
|
|
resetBindings();
|
|
|
|
context->resetContext();
|
|
|
|
|
|
|
|
// Test drawing and then resetting bindings. This should force a MIP regeneration if MIP
|
|
|
|
// maps are supported as well.
|
|
|
|
auto info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
|
|
|
|
auto surf = SkSurface::MakeRenderTarget(context, SkBudgeted::kYes, info, 1, nullptr);
|
|
|
|
surf->getCanvas()->clear(0x80FF0000);
|
|
|
|
auto img = surf->makeImageSnapshot();
|
|
|
|
surf->getCanvas()->clear(SK_ColorBLUE);
|
|
|
|
surf->getCanvas()->save();
|
|
|
|
surf->getCanvas()->scale(0.25, 0.25);
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setFilterQuality(kHigh_SkFilterQuality);
|
|
|
|
surf->getCanvas()->drawImage(img, 0, 0, &paint);
|
|
|
|
surf->getCanvas()->restore();
|
|
|
|
surf->flush();
|
|
|
|
context->resetGLTextureBindings();
|
|
|
|
checkBindings();
|
|
|
|
resetBindings();
|
|
|
|
context->resetContext();
|
|
|
|
|
|
|
|
if (supportExternal) {
|
2019-06-04 15:03:06 +00:00
|
|
|
GrBackendTexture texture2D = context->createBackendTexture(
|
2019-06-04 11:16:10 +00:00
|
|
|
10, 10, kRGBA_8888_SkColorType,
|
2019-07-01 19:04:06 +00:00
|
|
|
SkColors::kTransparent, GrMipMapped::kNo, GrRenderable::kNo, GrProtected::kNo);
|
2019-02-08 17:33:08 +00:00
|
|
|
GrGLTextureInfo info2D;
|
|
|
|
REPORTER_ASSERT(reporter, texture2D.getGLTextureInfo(&info2D));
|
|
|
|
GrEGLImage eglImage = ctxInfo.glContext()->texture2DToEGLImage(info2D.fID);
|
|
|
|
REPORTER_ASSERT(reporter, eglImage);
|
|
|
|
GrGLTextureInfo infoExternal;
|
|
|
|
infoExternal.fID = ctxInfo.glContext()->eglImageToExternalTexture(eglImage);
|
|
|
|
infoExternal.fTarget = GR_GL_TEXTURE_EXTERNAL;
|
|
|
|
infoExternal.fFormat = info2D.fFormat;
|
|
|
|
REPORTER_ASSERT(reporter, infoExternal.fID);
|
|
|
|
GrBackendTexture backendTexture(10, 10, GrMipMapped::kNo, infoExternal);
|
|
|
|
// Above texture creation will have messed with GL state and bindings.
|
|
|
|
resetBindings();
|
|
|
|
context->resetContext();
|
|
|
|
img = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
|
|
|
|
kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
|
|
|
|
REPORTER_ASSERT(reporter, img);
|
|
|
|
surf->getCanvas()->drawImage(img, 0, 0);
|
|
|
|
img.reset();
|
|
|
|
surf->flush();
|
|
|
|
context->resetGLTextureBindings();
|
|
|
|
checkBindings();
|
|
|
|
resetBindings();
|
|
|
|
GL(DeleteTextures(1, &infoExternal.fID));
|
|
|
|
ctxInfo.glContext()->destroyEGLImage(eglImage);
|
2019-05-20 12:38:07 +00:00
|
|
|
context->deleteBackendTexture(texture2D);
|
2019-02-08 17:33:08 +00:00
|
|
|
context->resetContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (supportRectangle) {
|
|
|
|
GrGLuint id = ctxInfo.glContext()->createTextureRectangle(10, 10, GR_GL_RGBA, GR_GL_RGBA,
|
|
|
|
GR_GL_UNSIGNED_BYTE, nullptr);
|
|
|
|
// Above texture creation will have messed with GL state and bindings.
|
|
|
|
resetBindings();
|
|
|
|
context->resetContext();
|
|
|
|
if (id) {
|
|
|
|
GrGLTextureInfo info;
|
|
|
|
info.fTarget = GR_GL_TEXTURE_RECTANGLE;
|
|
|
|
info.fFormat = GR_GL_RGBA8;
|
|
|
|
info.fID = id;
|
|
|
|
GrBackendTexture backendTexture(10, 10, GrMipMapped::kNo, info);
|
|
|
|
img = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin,
|
|
|
|
kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
|
|
|
|
REPORTER_ASSERT(reporter, img);
|
|
|
|
surf->getCanvas()->drawImage(img, 0, 0);
|
|
|
|
img.reset();
|
|
|
|
surf->flush();
|
|
|
|
context->resetGLTextureBindings();
|
|
|
|
checkBindings();
|
|
|
|
resetBindings();
|
|
|
|
GL(DeleteTextures(1, &id));
|
|
|
|
context->resetContext();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GL(DeleteTextures(claimedIDs.count(), claimedIDs.begin()));
|
|
|
|
|
|
|
|
#undef GL
|
|
|
|
}
|
2019-11-08 21:18:15 +00:00
|
|
|
|
|
|
|
#endif // SK_GL
|