aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-04-19 19:15:35 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-04-19 19:15:35 +0000
commit7361f54294d65a5c42ce5cf1cd56d0fd7122e268 (patch)
tree78e0d637725807c0e2b7aa7e55a9f0cf377d7ebe
parent5bfa55b1cd067fa2fe1cbe409573aeaabd98d23c (diff)
Make GM able to run MSAA modes and multiple GPU configs in a single run.
Review URL: http://codereview.appspot.com/6061051/ git-svn-id: http://skia.googlecode.com/svn/trunk@3734 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--gm/gmmain.cpp229
-rw-r--r--gyp/gpu.gyp1
-rw-r--r--include/gpu/GrContextFactory.h120
3 files changed, 229 insertions, 121 deletions
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 7d47bbe26d..3855f2f2dc 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -7,9 +7,8 @@
#include "gm.h"
#include "system_preferences.h"
-#include "GrContext.h"
+#include "GrContextFactory.h"
#include "GrRenderTarget.h"
-
#include "SkColorPriv.h"
#include "SkData.h"
#include "SkDeferredCanvas.h"
@@ -19,14 +18,6 @@
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
-#include "gl/SkNativeGLContext.h"
-#if SK_MESA
-#include "gl/SkMesaGLContext.h"
-#endif
-#if SK_ANGLE
-#include "gl/SkANGLEGLContext.h"
-#endif
-#include "gl/SkDebugGLContext.h"
#include "SkPicture.h"
#include "SkStream.h"
@@ -233,10 +224,22 @@ enum Backend {
kXPS_Backend,
};
+enum ConfigFlags {
+ kNone_ConfigFlag = 0x0,
+ /* Write GM images if a write path is provided. */
+ kWrite_ConfigFlag = 0x1,
+ /* Read comparison GM images if a read path is provided. */
+ kRead_ConfigFlag = 0x2,
+ kRW_ConfigFlag = (kWrite_ConfigFlag | kRead_ConfigFlag),
+};
+
struct ConfigData {
- SkBitmap::Config fConfig;
- Backend fBackend;
- const char* fName;
+ SkBitmap::Config fConfig;
+ Backend fBackend;
+ GrContextFactory::GLContextType fGLContextType; // GPU backend only
+ int fSampleCnt; // GPU backend only
+ ConfigFlags fFlags;
+ const char* fName;
};
/// Returns true if processing should continue, false to skip the
@@ -464,14 +467,11 @@ static ErrorBitfield handle_test_results(GM* gm,
SkString name = make_name(gm->shortName(), gRec.fName);
ErrorBitfield retval = ERROR_NONE;
- if (readPath && (
- gRec.fBackend == kRaster_Backend ||
- gRec.fBackend == kGPU_Backend ||
- (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF))) {
+ if (readPath && (gRec.fFlags & kRead_ConfigFlag)) {
retval |= compare_to_reference_image(readPath, name, bitmap,
diffPath, renderModeDescriptor);
}
- if (writePath) {
+ if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
retval |= write_reference_image(gRec, writePath, renderModeDescriptor,
name, bitmap, pdf);
}
@@ -615,14 +615,7 @@ static void usage(const char * argv0) {
"%s [-w writePath] [-r readPath] [-d diffPath] [-i resourcePath]\n"
" [--noreplay] [--serialize] [--forceBWtext] [--nopdf] \n"
" [--nodeferred] [--match substring] [--notexturecache]\n"
- " "
-#if SK_MESA
- "[--mesagl]"
-#endif
-#if SK_ANGLE
- " [--angle]"
-#endif
- " [--debuggl]\n\n", argv0);
+ , argv0);
SkDebugf(" writePath: directory to write rendered images in.\n");
SkDebugf(
" readPath: directory to read reference images from;\n"
@@ -636,28 +629,40 @@ static void usage(const char * argv0) {
SkDebugf(" --nopdf: skip the pdf rendering test pass.\n");
SkDebugf(" --nodeferred: skip the deferred rendering test pass.\n");
SkDebugf(" --match foo: will only run tests that substring match foo.\n");
-#if SK_MESA
- SkDebugf(" --mesagl: will run using the osmesa sw gl rasterizer.\n");
-#endif
-#if SK_ANGLE
- SkDebugf(" --angle: use ANGLE backend on Windows.\n");
-#endif
- SkDebugf(" --debuggl: will run using the debugging gl utility.\n");
SkDebugf(" --notexturecache: disable the gpu texture cache.\n");
}
+static const GrContextFactory::GLContextType kDontCare_GLContextType =
+ GrContextFactory::kNative_GLContextType;
+
+// If the platform does not support writing PNGs of PDFs then there will be no
+// comparison images to read. However, we can always write the .pdf files
+static const ConfigFlags kPDFConfigFlags = CAN_IMAGE_PDF ? kRW_ConfigFlag :
+ kWrite_ConfigFlag;
+
static const ConfigData gRec[] = {
- { SkBitmap::kARGB_8888_Config, kRaster_Backend, "8888" },
- { SkBitmap::kARGB_4444_Config, kRaster_Backend, "4444" },
- { SkBitmap::kRGB_565_Config, kRaster_Backend, "565" },
+ { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "8888" },
+ { SkBitmap::kARGB_4444_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "4444" },
+ { SkBitmap::kRGB_565_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "565" },
#ifdef SK_SCALAR_IS_FLOAT
- { SkBitmap::kARGB_8888_Config, kGPU_Backend, "gpu" },
-#endif
-#ifdef SK_SUPPORT_PDF
- { SkBitmap::kARGB_8888_Config, kPDF_Backend, "pdf" },
+ { SkBitmap::kARGB_8888_Config, kGPU_Backend, GrContextFactory::kNative_GLContextType, 0, kRW_ConfigFlag, "gpu" },
+ { SkBitmap::kARGB_8888_Config, kGPU_Backend, GrContextFactory::kNative_GLContextType, 16, kRW_ConfigFlag, "msaa16" },
+ /* The debug context does not generate images */
+ { SkBitmap::kARGB_8888_Config, kGPU_Backend, GrContextFactory::kDebug_GLContextType, 0, kNone_ConfigFlag, "debug" },
+ #ifdef SK_ANGLE
+ { SkBitmap::kARGB_8888_Config, kGPU_Backend, GrContextFactory::kANGLE_GLContextType, 0, kRW_ConfigFlag, "angle" },
+ { SkBitmap::kARGB_8888_Config, kGPU_Backend, GrContextFactory::kANGLE_GLContextType, 16, kRW_ConfigFlag, "anglemsaa16" },
+ #endif
+ #ifdef SK_MESA
+ { SkBitmap::kARGB_8888_Config, kGPU_Backend, GrContextFactory::kMESA_GLContextType, 0, kRW_ConfigFlag, "mesa" },
+ #endif
#endif
#ifdef SK_SUPPORT_XPS
- { SkBitmap::kARGB_8888_Config, kXPS_Backend, "xps" },
+ /* At present we have no way of comparing XPS files (either natively or by converting to PNG). */
+ { SkBitmap::kARGB_8888_Config, kXPS_Backend, kDontCare_GLContextType, 0, kWrite_ConfigFlag, "xps" },
+#endif
+#ifdef SK_SUPPORT_PDF
+ { SkBitmap::kARGB_8888_Config, kPDF_Backend, kDontCare_GLContextType, 0, kPDFConfigFlags, "pdf" },
#endif
};
@@ -676,10 +681,39 @@ static bool skip_name(const SkTDArray<const char*> array, const char name[]) {
}
namespace skiagm {
-static GrContext* gGrContext;
+SkAutoTUnref<GrContext> gGrContext;
+/**
+ * Sets the global GrContext, accessible by indivual GMs
+ */
+void SetGr(GrContext* grContext) {
+ SkSafeRef(grContext);
+ gGrContext.reset(grContext);
+}
+
+/**
+ * Gets the global GrContext, can be called by GM tests.
+ */
GrContext* GetGr() {
- return gGrContext;
+ return gGrContext.get();
}
+
+/**
+ * Sets the global GrContext and then resets it to its previous value at
+ * destruction.
+ */
+class AutoResetGr : SkNoncopyable {
+public:
+ AutoResetGr() : fOld(NULL) {}
+ void set(GrContext* context) {
+ SkASSERT(NULL == fOld);
+ fOld = GetGr();
+ SkSafeRef(fOld);
+ SetGr(context);
+ }
+ ~AutoResetGr() { SetGr(fOld); SkSafeUnref(fOld); }
+private:
+ GrContext* fOld;
+};
}
int main(int argc, char * const argv[]) {
@@ -699,12 +733,6 @@ int main(int argc, char * const argv[]) {
bool doPDF = true;
bool doReplay = true;
bool doSerialize = false;
-#if SK_MESA
- bool useMesa = false;
-#endif
-#if SK_ANGLE
- bool useAngle = false;
-#endif
bool useDebugGL = false;
bool doDeferred = true;
bool disableTextureCache = false;
@@ -748,16 +776,6 @@ int main(int argc, char * const argv[]) {
// just record the ptr, no need for a deep copy
*fMatches.append() = *argv;
}
-#if SK_MESA
- } else if (strcmp(*argv, "--mesagl") == 0) {
- useMesa = true;
-#endif
-#if SK_ANGLE
- } else if (strcmp(*argv, "--angle") == 0) {
- useAngle = true;
-#endif
- } else if (strcmp(*argv, "--debuggl") == 0) {
- useDebugGL = true;
} else if (strcmp(*argv, "--notexturecache") == 0) {
disableTextureCache = true;
} else {
@@ -772,49 +790,7 @@ int main(int argc, char * const argv[]) {
GM::SetResourcePath(resourcePath);
- int maxW = -1;
- int maxH = -1;
- Iter iter;
- GM* gm;
- while ((gm = iter.next()) != NULL) {
- SkISize size = gm->getISize();
- maxW = SkMax32(size.width(), maxW);
- maxH = SkMax32(size.height(), maxH);
- // This fixes a memory leak, but we are churning gms; we could
- // instead cache them if we have constructors with side-effects.
- SkDELETE(gm);
- }
- // setup a GL context for drawing offscreen
- SkAutoTUnref<SkGLContext> glContext;
-#if SK_MESA
- if (useMesa) {
- glContext.reset(new SkMesaGLContext());
- } else
-#endif
-#if SK_ANGLE
- if (useAngle) {
- glContext.reset(new SkANGLEGLContext());
- } else
-#endif
- if (useDebugGL) {
- glContext.reset(new SkDebugGLContext());
- } else {
- glContext.reset(new SkNativeGLContext());
- }
-
- GrPlatformRenderTargetDesc rtDesc;
- if (glContext.get()->init(maxW, maxH)) {
- GrPlatform3DContext ctx =
- reinterpret_cast<GrPlatform3DContext>(glContext.get()->gl());
- gGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, ctx);
- if (NULL != gGrContext) {
- rtDesc.fConfig = kSkia8888_PM_GrPixelConfig;
- rtDesc.fStencilBits = 8;
- rtDesc.fRenderTargetHandle = glContext.get()->getFBOID();
- }
- } else {
- fprintf(stderr, "could not create GL context.\n");
- }
+ GrContextFactory grFactory;
if (readPath) {
fprintf(stderr, "reading from %s\n", readPath);
@@ -837,7 +813,8 @@ int main(int argc, char * const argv[]) {
skiagm::GetGr()->setTextureCacheLimits(0, 0);
}
- iter.reset();
+ Iter iter;
+ GM* gm;
while ((gm = iter.next()) != NULL) {
const char* shortName = gm->shortName();
if (skip_name(fMatches, shortName)) {
@@ -850,20 +827,33 @@ int main(int argc, char * const argv[]) {
size.width(), size.height());
SkBitmap forwardRenderedBitmap;
- // Above we created an fbo for the context at maxW x maxH size.
- // Here we lie about the size of the rt. We claim it is the size
- // desired by the test. The reason is that rasterization may change
- // slightly when the viewport dimensions change. Previously, whenever
- // a new test was checked in that bumped maxW or maxH several images
- // would slightly change.
- rtDesc.fWidth = size.width();
- rtDesc.fHeight = size.height();
- SkAutoTUnref<GrRenderTarget> rt;
- if (gGrContext) {
- rt.reset(gGrContext->createPlatformRenderTarget(rtDesc));
- }
-
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
+ SkAutoTUnref<GrRenderTarget> rt;
+ AutoResetGr autogr;
+ if (kGPU_Backend == gRec[i].fBackend) {
+ GrContext* gr = grFactory.get(gRec[i].fGLContextType);
+ if (!gr) {
+ continue;
+ }
+
+ // create a render target to back the device
+ GrTextureDesc desc;
+ desc.fConfig = kSkia8888_PM_GrPixelConfig;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit;
+ desc.fWidth = gm->getISize().width();
+ desc.fHeight = gm->getISize().height();
+ desc.fSampleCnt = gRec[i].fSampleCnt;
+ GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0);
+ if (!tex) {
+ return false;
+ }
+ rt.reset(tex->asRenderTarget());
+ rt.get()->ref();
+ tex->unref();
+
+ autogr.set(gr);
+ }
+
// Skip any tests that we don't even need to try.
uint32_t gmFlags = gm->getFlags();
if ((kPDF_Backend == gRec[i].fBackend) &&
@@ -886,7 +876,7 @@ int main(int argc, char * const argv[]) {
if (ERROR_NONE == testErrors) {
testErrors |= test_drawing(gm, gRec[i],
writePath, readPath, diffPath,
- gGrContext,
+ GetGr(),
rt.get(), &forwardRenderedBitmap);
}
@@ -895,7 +885,7 @@ int main(int argc, char * const argv[]) {
kRaster_Backend == gRec[i].fBackend)) {
testErrors |= test_deferred_drawing(gm, gRec[i],
forwardRenderedBitmap,
- diffPath, gGrContext, rt.get());
+ diffPath, GetGr(), rt.get());
}
if ((ERROR_NONE == testErrors) && doReplay &&
@@ -931,8 +921,5 @@ int main(int argc, char * const argv[]) {
printf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
- SkDELETE(skiagm::gGrContext);
- skiagm::gGrContext = NULL;
-
return (0 == testsFailed) ? 0 : -1;
}
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp
index 0ffaa283bd..685eca18be 100644
--- a/gyp/gpu.gyp
+++ b/gyp/gpu.gyp
@@ -177,6 +177,7 @@
'../include/gpu/GrColor.h',
'../include/gpu/GrConfig.h',
'../include/gpu/GrContext.h',
+ '../include/gpu/GrContextFactory.h',
'../include/gpu/GrFontScaler.h',
'../include/gpu/GrGlyph.h',
'../include/gpu/GrInstanceCounter.h',
diff --git a/include/gpu/GrContextFactory.h b/include/gpu/GrContextFactory.h
new file mode 100644
index 0000000000..0a662745af
--- /dev/null
+++ b/include/gpu/GrContextFactory.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrContextFactory_DEFINED
+#define GrContextFactory_DEFINED
+
+#if SK_ANGLE
+ #include "gl/SkANGLEGLContext.h"
+#endif
+#include "gl/SkDebugGLContext.h"
+#if SK_MESA
+ #include "gl/SkMesaGLContext.h"
+#endif
+#include "gl/SkNativeGLContext.h"
+#include "gl/SkNullGLContext.h"
+
+#include "GrContext.h"
+
+/**
+ * This is a simple class that is useful in test apps that use different
+ * GrContexts backed by different types of GL contexts. It manages creating the
+ * GL context and a GrContext that uses it. The GL/Gr contexts persist until the
+ * factory is destroyed (though the caller can always grab a ref on the returned
+ * GrContext to make it outlive the factory).
+ */
+class GrContextFactory : GrNoncopyable {
+public:
+ /**
+ * Types of GL contexts supported.
+ */
+ enum GLContextType {
+ kNative_GLContextType,
+#if SK_ANGLE
+ kANGLE_GLContextType,
+#endif
+#if SK_MESA
+ kMESA_GLContextType,
+#endif
+ kNull_GLContextType,
+ kDebug_GLContextType,
+ };
+
+ GrContextFactory() {
+ }
+
+ ~GrContextFactory() {
+ for (int i = 0; i < fContexts.count(); ++i) {
+ fContexts[i].fGrContext->unref();
+ fContexts[i].fGLContext->unref();
+ }
+ }
+
+ /**
+ * Get a GrContext initalized with a type of GL context.
+ */
+ GrContext* get(GLContextType type) {
+
+ for (int i = 0; i < fContexts.count(); ++i) {
+ if (fContexts[i].fType == type) {
+ return fContexts[i].fGrContext;
+ }
+ }
+ SkAutoTUnref<SkGLContext> glCtx;
+ SkAutoTUnref<GrContext> grCtx;
+ switch (type) {
+ case kNative_GLContextType:
+ glCtx.reset(new SkNativeGLContext());
+ break;
+#ifdef SK_ANGLE
+ case kANGLE_GLContextType:
+ glCtx.reset(new SkANGLEGLContext());
+ break;
+#endif
+#ifdef SK_MESA
+ case kMESA_GLContextType:
+ glCtx.reset(new SkMesaGLContext());
+ break;
+#endif
+ case kNull_GLContextType:
+ glCtx.reset(new SkNullGLContext());
+ break;
+ case kDebug_GLContextType:
+ glCtx.reset(new SkDebugGLContext());
+ break;
+ }
+ static const int kBogusSize = 1;
+ if (!glCtx.get()) {
+ return NULL;
+ }
+ if (!glCtx.get()->init(kBogusSize, kBogusSize)) {
+ return NULL;
+ }
+ GrPlatform3DContext p3dctx =
+ reinterpret_cast<GrPlatform3DContext>(glCtx.get()->gl());
+ grCtx.reset(GrContext::Create(kOpenGL_Shaders_GrEngine, p3dctx));
+ if (!grCtx.get()) {
+ return NULL;
+ }
+ GPUContext& ctx = fContexts.push_back();
+ ctx.fGLContext = glCtx.get();
+ ctx.fGLContext->ref();
+ ctx.fGrContext = grCtx.get();
+ ctx.fGrContext->ref();
+ ctx.fType = type;
+ return ctx.fGrContext;
+ }
+private:
+ struct GPUContext {
+ GLContextType fType;
+ SkGLContext* fGLContext;
+ GrContext* fGrContext;
+ };
+ SkTArray<GPUContext, true> fContexts;
+};
+
+#endif