diff options
author | 2010-12-20 18:26:13 +0000 | |
---|---|---|
committer | 2010-12-20 18:26:13 +0000 | |
commit | f2b98d67dcb6fcb3120feede9c72016fc7b3ead8 (patch) | |
tree | d78b57945b29865dcdeb1badbb360575289b292d /samplecode/SampleApp.cpp | |
parent | 29e5054dd07c97c2195c5f64bf67aaa6b5afa204 (diff) |
merge with changes for GPU backend
git-svn-id: http://skia.googlecode.com/svn/trunk@637 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'samplecode/SampleApp.cpp')
-rw-r--r-- | samplecode/SampleApp.cpp | 425 |
1 files changed, 329 insertions, 96 deletions
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 2bd1fe032a..b9e7b48ca3 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -1,6 +1,7 @@ +#include <OpenGL/gl.h> + #include "SkCanvas.h" #include "SkDevice.h" -#include "SkGLCanvas.h" #include "SkGraphics.h" #include "SkImageEncoder.h" #include "SkPaint.h" @@ -11,19 +12,33 @@ #include "SampleCode.h" +#ifdef SUPPORT_GPU + #include "SkGpuCanvas.h" + #include "GrContext.h" + + #ifdef SK_SUPPORT_GL + #include "GrGLConfig.h" + #elif defined(SK_SUPPORT_D3D9) + #include <d3d9.h> + #endif +#else + typedef SkCanvas SkGpuCanvas; + class GrContext; +#endif + +//#define DEFAULT_TO_GPU + extern SkView* create_overview(int, const SkViewFactory[]); #define SK_SUPPORT_GL - -#ifdef SK_SUPPORT_GL -#include <AGL/agl.h> -#include <OpenGL/gl.h> -#endif +//#define SK_SUPPORT_D3D9 #define ANIMATING_EVENTTYPE "nextSample" #define ANIMATING_DELAY 750 -#define USE_OFFSCREEN +#if !defined(SK_BUILD_FOR_WIN32) +//#define USE_OFFSCREEN +#endif SkViewRegister* SkViewRegister::gHead; SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) { @@ -37,69 +52,65 @@ SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) { gHead = this; } -#ifdef SK_SUPPORT_GL -static AGLContext gAGLContext; - -static void init_gl(WindowRef wref) { - GLint major, minor; - - aglGetVersion(&major, &minor); - SkDebugf("---- agl version %d %d\n", major, minor); - - const GLint pixelAttrs[] = { - AGL_RGBA, - AGL_DEPTH_SIZE, 32, - AGL_OFFSCREEN, - AGL_NONE - }; - - AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs); - SkDebugf("----- agl format %p\n", format); - gAGLContext = aglCreateContext(format, NULL); - SkDebugf("----- agl context %p\n", gAGLContext); - aglDestroyPixelFormat(format); - - aglEnable(gAGLContext, GL_BLEND); - aglEnable(gAGLContext, GL_LINE_SMOOTH); - aglEnable(gAGLContext, GL_POINT_SMOOTH); - aglEnable(gAGLContext, GL_POLYGON_SMOOTH); - - aglSetCurrentContext(gAGLContext); -} - -static void setup_offscreen_gl(const SkBitmap& offscreen, WindowRef wref) { - GLboolean success = true; +#if defined(SK_SUPPORT_GL) && defined(SK_SUPPORT_D3D9) + #error "choose either GL or D3D9" +#endif -#ifdef USE_OFFSCREEN - success = aglSetOffScreen(gAGLContext, - offscreen.width(), - offscreen.height(), - offscreen.rowBytes(), - offscreen.getPixels()); -#else - success = aglSetWindowRef(gAGLContext, wref); +#if defined(SK_SUPPORT_GL) + #define SK_USE_SHADERS #endif - GLenum err = aglGetError(); - if (err) { - SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err, - aglErrorString(err), offscreen.width(), offscreen.height()); +static GrContext* get_global_grctx(SkOSWindow* oswin) { +#ifdef SUPPORT_GPU + // should be pthread-local at least + static GrContext* ctx; + if (NULL == ctx) { +#if defined(SK_SUPPORT_GL) + #if defined(SK_USE_SHADERS) + ctx = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL); + #else + ctx = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL); + #endif +#elif defined(SK_SUPPORT_D3D9) + if (oswin->d3d9Device()) { + ctx = GrContext::Create(GrGpu::kDirect3D9_Engine, + (IDirect3DDevice9*) oswin->d3d9Device()); + } +#endif } - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); - glEnable(GL_TEXTURE_2D); - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT); -} + return ctx; +#else + return NULL; #endif +} ////////////////////////////////////////////////////////////////////////////// +static const char gCharEvtName[] = "SampleCode_Char_Event"; +static const char gKeyEvtName[] = "SampleCode_Key_Event"; static const char gTitleEvtName[] = "SampleCode_Title_Event"; static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event"; +static const char gFastTextEvtName[] = "SampleCode_FastText_Event"; + +bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) { + if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) { + if (outUni) { + *outUni = evt.getFast32(); + } + return true; + } + return false; +} + +bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) { + if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) { + if (outKey) { + *outKey = (SkKey)evt.getFast32(); + } + return true; + } + return false; +} bool SampleCode::TitleQ(const SkEvent& evt) { return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1); @@ -122,20 +133,40 @@ void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) { evt->setScalars(gPrefSizeEvtName, 2, size); } +bool SampleCode::FastTextQ(const SkEvent& evt) { + return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1); +} + +/////////////////////////////////////////////////////////////////////////////// + static SkMSec gAnimTime; +static SkMSec gAnimTimePrev; + SkMSec SampleCode::GetAnimTime() { return gAnimTime; } +SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; } +SkScalar SampleCode::GetAnimSecondsDelta() { + return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0); +} SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) { - SkScalar seconds = SkFloatToScalar(gAnimTime / 1000.0f); - SkScalar value = SkScalarMul(speed, seconds); + // since gAnimTime can be up to 32 bits, we can't convert it to a float + // or we'll lose the low bits. Hence we use doubles for the intermediate + // calculations + double seconds = (double)gAnimTime / 1000.0; + double value = SkScalarToDouble(speed) * seconds; if (period) { - value = SkScalarMod(value, period); + value = ::fmod(value, SkScalarToDouble(period)); } - return value; + return SkDoubleToScalar(value); } ////////////////////////////////////////////////////////////////////////////// +static SkView* curr_view(SkWindow* wind) { + SkView::F2BIter iter(wind); + return iter.next(); +} + class SampleWindow : public SkOSWindow { SkTDArray<SkViewFactory> fSamples; public: @@ -156,6 +187,7 @@ protected: virtual void afterChild(SkView* child, SkCanvas* canvas); virtual bool onEvent(const SkEvent& evt); + virtual bool onQuery(SkEvent* evt); #if 0 virtual bool handleChar(SkUnichar uni); @@ -171,13 +203,13 @@ private: int fCurrIndex; SkPicture* fPicture; - SkGLCanvas* fGLCanvas; + SkGpuCanvas* fGpuCanvas; SkPath fClipPath; enum CanvasType { kRaster_CanvasType, kPicture_CanvasType, - kOpenGL_CanvasType + kGPU_CanvasType }; CanvasType fCanvasType; @@ -187,6 +219,7 @@ private: bool fAnimating; bool fRotate; bool fScale; + bool fRequestGrabImage; int fScrollTestX, fScrollTestY; @@ -210,33 +243,35 @@ private: SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) { static const CanvasType gCT[] = { kPicture_CanvasType, - kOpenGL_CanvasType, + kGPU_CanvasType, kRaster_CanvasType }; return gCT[ct]; } SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) { -#ifdef SK_SUPPORT_GL - init_gl((WindowRef)hwnd); -#endif - fPicture = NULL; - fGLCanvas = NULL; + fGpuCanvas = NULL; +#ifdef DEFAULT_TO_GPU + fCanvasType = kGPU_CanvasType; +#else fCanvasType = kRaster_CanvasType; +#endif fUseClip = false; fNClip = false; fRepeatDrawing = false; fAnimating = false; fRotate = false; fScale = false; + fRequestGrabImage = false; fScrollTestX = fScrollTestY = 0; // this->setConfig(SkBitmap::kRGB_565_Config); this->setConfig(SkBitmap::kARGB_8888_Config); this->setVisibleP(true); + this->setClipToBounds(false); { const SkViewRegister* reg = SkViewRegister::Head(); @@ -251,7 +286,7 @@ SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) { SampleWindow::~SampleWindow() { delete fPicture; - delete fGLCanvas; + delete fGpuCanvas; } static SkBitmap capture_bitmap(SkCanvas* canvas) { @@ -284,6 +319,7 @@ static bool bitmap_diff(SkCanvas* canvas, const SkBitmap& orig, void SampleWindow::draw(SkCanvas* canvas) { // update the animation time + gAnimTimePrev = gAnimTime; gAnimTime = SkTime::GetMSecs(); if (fNClip) { @@ -346,11 +382,17 @@ static void reverseRedAndBlue(const SkBitmap& bm) { } SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { + SkIPoint viewport; + bool alreadyGPU = canvas->getViewport(&viewport); + + if (kGPU_CanvasType != fCanvasType) { #ifdef SK_SUPPORT_GL -#ifndef USE_OFFSCREEN - aglSetWindowRef(gAGLContext, NULL); -#endif -#endif + detachGL(); +#elif defined(SK_SUPPORT_D3D9) + detachD3D9(); +#endif + } + switch (fCanvasType) { case kRaster_CanvasType: canvas = this->INHERITED::beforeChildren(canvas); @@ -359,20 +401,35 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) { fPicture = new SkPicture; canvas = fPicture->beginRecording(9999, 9999); break; -#ifdef SK_SUPPORT_GL - case kOpenGL_CanvasType: { - //SkGLCanvas::DeleteAllTextures(); // just for testing - SkDevice* device = canvas->getDevice(); - const SkBitmap& bitmap = device->accessBitmap(true); - // first clear the raster bitmap, so we don't see any leftover bits - bitmap.eraseColor(0); - // now setup our glcanvas - setup_offscreen_gl(bitmap, (WindowRef)this->getHWND()); - fGLCanvas = new SkGLCanvas; - fGLCanvas->setViewport(bitmap.width(), bitmap.height()); - canvas = fGLCanvas; +#ifdef SUPPORT_GPU + case kGPU_CanvasType: + if (!alreadyGPU) { + SkDevice* device = canvas->getDevice(); + const SkBitmap& bitmap = device->accessBitmap(true); +#ifdef SK_SUPPORT_GL + #ifdef USE_OFFSCREEN + // first clear the raster bitmap, so we don't see any leftover bits + bitmap.eraseColor(0); + // now setup our glcanvas + attachGL(&bitmap); + #else + attachGL(NULL); + #endif + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +#elif defined(SK_SUPPORT_D3D9) + // now setup our canvas + attachD3D9(); +#endif + SkBitmap viewport; + viewport.setConfig(SkBitmap::kARGB_8888_Config, bitmap.width(), bitmap.height()); + fGpuCanvas = new SkGpuCanvas(get_global_grctx(this)); + fGpuCanvas->setBitmapDevice(viewport); + canvas = fGpuCanvas; + + } else { + canvas = this->INHERITED::beforeChildren(canvas); + } break; - } #endif } @@ -395,6 +452,22 @@ static void paint_rgn(const SkBitmap& bm, const SkIRect& r, } void SampleWindow::afterChildren(SkCanvas* orig) { + if (fRequestGrabImage) { + fRequestGrabImage = false; + + SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig; + SkDevice* device = canvas->getDevice(); + SkBitmap bitmap; + SkIRect bounds = { 0, 0, this->width(), this->height() }; + if (device->readPixels(bounds, &bitmap)) { + static int gSampleGrabCounter; + SkString name; + name.printf("sample_grab_%d", gSampleGrabCounter++); + SkImageEncoder::EncodeFile(name.c_str(), bitmap, + SkImageEncoder::kPNG_Type, 100); + } + } + switch (fCanvasType) { case kRaster_CanvasType: break; @@ -419,19 +492,27 @@ void SampleWindow::afterChildren(SkCanvas* orig) { fPicture = NULL; break; #ifdef SK_SUPPORT_GL - case kOpenGL_CanvasType: - glFlush(); - delete fGLCanvas; - fGLCanvas = NULL; + case kGPU_CanvasType: + delete fGpuCanvas; + fGpuCanvas = NULL; + presentGL(); #ifdef USE_OFFSCREEN reverseRedAndBlue(orig->getDevice()->accessBitmap(true)); #endif break; +#elif defined(SK_SUPPORT_D3D9) + case kGPU_CanvasType: { + delete fGpuCanvas; + fGpuCanvas = NULL; + presentD3D9(); + break; + } #endif + } // if ((fScrollTestX | fScrollTestY) != 0) - { + if (false) { const SkBitmap& bm = orig->getDevice()->accessBitmap(true); int dx = fScrollTestX * 7; int dy = fScrollTestY * 7; @@ -501,6 +582,27 @@ bool SampleWindow::onEvent(const SkEvent& evt) { return this->INHERITED::onEvent(evt); } +bool SampleWindow::onQuery(SkEvent* query) { + if (query->isType("get-slide-count")) { + query->setFast32(fSamples.count()); + return true; + } + if (query->isType("get-slide-title")) { + SkView* view = fSamples[query->getFast32()](); + SkEvent evt(gTitleEvtName); + if (view->doQuery(&evt)) { + query->setString("title", evt.findString(gTitleEvtName)); + } + SkSafeUnref(view); + return true; + } + if (query->isType("use-fast-text")) { + SkEvent evt(gFastTextEvtName); + return curr_view(this)->doQuery(&evt); + } + return this->INHERITED::onQuery(query); +} + static void cleanup_for_filename(SkString* name) { char* str = name->writable_str(); for (size_t i = 0; i < name->size(); i++) { @@ -514,6 +616,17 @@ static void cleanup_for_filename(SkString* name) { } bool SampleWindow::onHandleChar(SkUnichar uni) { + { + SkView* view = curr_view(this); + if (view) { + SkEvent evt(gCharEvtName); + evt.setFast32(uni); + if (view->doQuery(&evt)) { + return true; + } + } + } + int dx = 0xFF; int dy = 0xFF; @@ -573,6 +686,13 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { this->inval(NULL); this->updateTitle(); return true; + case 'd': + SkGraphics::SetFontCacheUsed(0); + return true; + case 'g': + fRequestGrabImage = true; + this->inval(NULL); + break; default: break; } @@ -583,6 +703,17 @@ bool SampleWindow::onHandleChar(SkUnichar uni) { #include "SkDumpCanvas.h" bool SampleWindow::onHandleKey(SkKey key) { + { + SkView* view = curr_view(this); + if (view) { + SkEvent evt(gKeyEvtName); + evt.setFast32(key); + if (view->doQuery(&evt)) { + return true; + } + } + } + switch (key) { case kRight_SkKey: if (this->nextSample()) { @@ -604,7 +735,7 @@ bool SampleWindow::onHandleKey(SkKey key) { this->updateTitle(); return true; case kOK_SkKey: - if (true) { + if (false) { SkDebugfDumper dumper; SkDumpCanvas dc(&dumper); this->draw(&dc); @@ -635,6 +766,7 @@ void SampleWindow::loadView(SkView* view) { view = create_overview(fSamples.count(), fSamples.begin()); } view->setVisibleP(true); + view->setClipToBounds(false); this->attachChildToFront(view)->unref(); view->setSize(this->width(), this->height()); @@ -728,7 +860,108 @@ void SampleWindow::onSizeChange() { /////////////////////////////////////////////////////////////////////////////// +template <typename T> void SkTBSort(T array[], int count) { + for (int i = 1; i < count - 1; i++) { + bool didSwap = false; + for (int j = count - 1; j > i; --j) { + if (array[j] < array[j-1]) { + T tmp(array[j-1]); + array[j-1] = array[j]; + array[j] = tmp; + didSwap = true; + } + } + if (!didSwap) { + break; + } + } + + for (int k = 0; k < count - 1; k++) { + SkASSERT(!(array[k+1] < array[k])); + } +} + +#include "SkRandom.h" + +static void rand_rect(SkIRect* rect, SkRandom& rand) { + int bits = 8; + int shift = 32 - bits; + rect->set(rand.nextU() >> shift, rand.nextU() >> shift, + rand.nextU() >> shift, rand.nextU() >> shift); + rect->sort(); +} + +static void dumpRect(const SkIRect& r) { + SkDebugf(" { %d, %d, %d, %d },\n", + r.fLeft, r.fTop, + r.fRight, r.fBottom); +} + +static void test_rects(const SkIRect rect[], int count) { + SkRegion rgn0, rgn1; + + for (int i = 0; i < count; i++) { + rgn0.op(rect[i], SkRegion::kUnion_Op); + // dumpRect(rect[i]); + } + rgn1.setRects(rect, count); + + if (rgn0 != rgn1) { + SkDebugf("\n"); + for (int i = 0; i < count; i++) { + dumpRect(rect[i]); + } + SkDebugf("\n"); + } +} + +static void test() { + size_t i; + + const SkIRect r0[] = { + { 0, 0, 1, 1 }, + { 2, 2, 3, 3 }, + }; + const SkIRect r1[] = { + { 0, 0, 1, 3 }, + { 1, 1, 2, 2 }, + { 2, 0, 3, 3 }, + }; + const SkIRect r2[] = { + { 0, 0, 1, 2 }, + { 2, 1, 3, 3 }, + { 4, 0, 5, 1 }, + { 6, 0, 7, 4 }, + }; + + static const struct { + const SkIRect* fRects; + int fCount; + } gRecs[] = { + { r0, SK_ARRAY_COUNT(r0) }, + { r1, SK_ARRAY_COUNT(r1) }, + { r2, SK_ARRAY_COUNT(r2) }, + }; + + for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) { + test_rects(gRecs[i].fRects, gRecs[i].fCount); + } + + SkRandom rand; + for (i = 0; i < 10000; i++) { + SkRegion rgn0, rgn1; + + const int N = 8; + SkIRect rect[N]; + for (int j = 0; j < N; j++) { + rand_rect(&rect[j], rand); + } + test_rects(rect, N); + } +} + SkOSWindow* create_sk_window(void* hwnd) { +// test(); return new SampleWindow(hwnd); } |