diff options
Diffstat (limited to 'chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm')
-rw-r--r-- | chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm b/chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm new file mode 100644 index 00000000000..a9defbe610f --- /dev/null +++ b/chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm @@ -0,0 +1,494 @@ +#import "SkSampleUIView.h" + +#define SKGL_CONFIG kEAGLColorFormatRGB565 +//#define SKGL_CONFIG kEAGLColorFormatRGBA8 + +#define FORCE_REDRAW + +#include "SkCanvas.h" +#include "SkCGUtils.h" +#include "SampleApp.h" + +#if SK_SUPPORT_GPU +//#define USE_GL_1 +#define USE_GL_2 + +#include "gl/GrGLInterface.h" +#include "GrContext.h" +#include "SkGpuDevice.h" +#endif + +class SkiOSDeviceManager : public SampleWindow::DeviceManager { +public: + SkiOSDeviceManager(GLint layerFBO) { +#if SK_SUPPORT_GPU + fCurContext = NULL; + fCurIntf = NULL; + fCurRenderTarget = NULL; + fMSAASampleCount = 0; + fLayerFBO = layerFBO; +#endif + fBackend = SkOSWindow::kNone_BackEndType; + } + + virtual ~SkiOSDeviceManager() { +#if SK_SUPPORT_GPU + SkSafeUnref(fCurContext); + SkSafeUnref(fCurIntf); + SkSafeUnref(fCurRenderTarget); +#endif + } + + virtual void setUpBackend(SampleWindow* win, int msaaSampleCount) SK_OVERRIDE { + SkASSERT(SkOSWindow::kNone_BackEndType == fBackend); + + fBackend = SkOSWindow::kNone_BackEndType; + +#if SK_SUPPORT_GPU + switch (win->getDeviceType()) { + // these two don't use GL + case SampleWindow::kRaster_DeviceType: + case SampleWindow::kPicture_DeviceType: + break; + // these guys use the native backend + case SampleWindow::kGPU_DeviceType: + case SampleWindow::kNullGPU_DeviceType: + fBackend = SkOSWindow::kNativeGL_BackEndType; + break; + default: + SkASSERT(false); + break; + } + SkOSWindow::AttachmentInfo info; + bool result = win->attach(fBackend, msaaSampleCount, &info); + if (!result) { + SkDebugf("Failed to initialize GL"); + return; + } + fMSAASampleCount = msaaSampleCount; + + SkASSERT(NULL == fCurIntf); + switch (win->getDeviceType()) { + // these two don't use GL + case SampleWindow::kRaster_DeviceType: + case SampleWindow::kPicture_DeviceType: + fCurIntf = NULL; + break; + case SampleWindow::kGPU_DeviceType: + fCurIntf = GrGLCreateNativeInterface(); + break; + case SampleWindow::kNullGPU_DeviceType: + fCurIntf = GrGLCreateNullInterface(); + break; + default: + SkASSERT(false); + break; + } + + SkASSERT(NULL == fCurContext); + if (SkOSWindow::kNone_BackEndType != fBackend) { + fCurContext = GrContext::Create(kOpenGL_GrBackend, + (GrBackendContext) fCurIntf); + } + + if ((NULL == fCurContext || NULL == fCurIntf) && + SkOSWindow::kNone_BackEndType != fBackend) { + // We need some context and interface to see results if we're using a GL backend + SkSafeUnref(fCurContext); + SkSafeUnref(fCurIntf); + SkDebugf("Failed to setup 3D"); + win->detach(); + } +#endif // SK_SUPPORT_GPU + // call windowSizeChanged to create the render target + this->windowSizeChanged(win); + } + + virtual void tearDownBackend(SampleWindow *win) SK_OVERRIDE { +#if SK_SUPPORT_GPU + SkSafeUnref(fCurContext); + fCurContext = NULL; + + SkSafeUnref(fCurIntf); + fCurIntf = NULL; + + SkSafeUnref(fCurRenderTarget); + fCurRenderTarget = NULL; +#endif + win->detach(); + fBackend = SampleWindow::kNone_BackEndType; + } + + virtual SkCanvas* createCanvas(SampleWindow::DeviceType dType, + SampleWindow* win) { + switch (dType) { + case SampleWindow::kRaster_DeviceType: + // fallthrough + case SampleWindow::kPicture_DeviceType: + // fallthrough +#if SK_ANGLE + case SampleWindow::kANGLE_DeviceType: +#endif + break; +#if SK_SUPPORT_GPU + case SampleWindow::kGPU_DeviceType: + case SampleWindow::kNullGPU_DeviceType: + if (fCurContext) { + SkAutoTUnref<SkBaseDevice> device(new SkGpuDevice(fCurContext, + fCurRenderTarget)); + return new SkCanvas(device); + } else { + return NULL; + } + break; +#endif + default: + SkASSERT(false); + return NULL; + } + return NULL; + } + + virtual void publishCanvas(SampleWindow::DeviceType dType, + SkCanvas* canvas, + SampleWindow* win) SK_OVERRIDE { +#if SK_SUPPORT_GPU + if (NULL != fCurContext) { + fCurContext->flush(); + } +#endif + win->present(); + } + + virtual void windowSizeChanged(SampleWindow* win) SK_OVERRIDE { +#if SK_SUPPORT_GPU + if (NULL != fCurContext) { + SkOSWindow::AttachmentInfo info; + + win->attach(fBackend, fMSAASampleCount, &info); + + glBindFramebuffer(GL_FRAMEBUFFER, fLayerFBO); + GrBackendRenderTargetDesc desc; + desc.fWidth = SkScalarRoundToInt(win->width()); + desc.fHeight = SkScalarRoundToInt(win->height()); + desc.fConfig = kSkia8888_GrPixelConfig; + desc.fRenderTargetHandle = fLayerFBO; + desc.fSampleCnt = info.fSampleCount; + desc.fStencilBits = info.fStencilBits; + + SkSafeUnref(fCurRenderTarget); + fCurRenderTarget = fCurContext->wrapBackendRenderTarget(desc); + } +#endif + } + + virtual GrContext* getGrContext() SK_OVERRIDE { +#if SK_SUPPORT_GPU + return fCurContext; +#else + return NULL; +#endif + } + + virtual GrRenderTarget* getGrRenderTarget() SK_OVERRIDE { +#if SK_SUPPORT_GPU + return fCurRenderTarget; +#else + return NULL; +#endif + } + + bool isUsingGL() const { return SkOSWindow::kNone_BackEndType != fBackend; } + +private: + +#if SK_SUPPORT_GPU + GrContext* fCurContext; + const GrGLInterface* fCurIntf; + GrRenderTarget* fCurRenderTarget; + int fMSAASampleCount; + GLint fLayerFBO; +#endif + + SkOSWindow::SkBackEndTypes fBackend; + + typedef SampleWindow::DeviceManager INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////// +@implementation SkSampleUIView + +@synthesize fTitle, fRasterLayer, fGLLayer; + +#include "SkApplication.h" +#include "SkEvent.h" +#include "SkWindow.h" + +struct FPSState { + static const int FRAME_COUNT = 60; + + CFTimeInterval fNow0, fNow1; + CFTimeInterval fTime0, fTime1, fTotalTime; + int fFrameCounter; + SkString str; + FPSState() { + fTime0 = fTime1 = fTotalTime = 0; + fFrameCounter = 0; + } + + void startDraw() { + fNow0 = CACurrentMediaTime(); + } + + void endDraw() { + fNow1 = CACurrentMediaTime(); + } + + void flush(SkOSWindow* hwnd) { + CFTimeInterval now2 = CACurrentMediaTime(); + + fTime0 += fNow1 - fNow0; + fTime1 += now2 - fNow1; + + if (++fFrameCounter == FRAME_COUNT) { + CFTimeInterval totalNow = CACurrentMediaTime(); + fTotalTime = totalNow - fTotalTime; + + //SkMSec ms0 = (int)(1000 * fTime0 / FRAME_COUNT); + //SkMSec msTotal = (int)(1000 * fTotalTime / FRAME_COUNT); + //str.printf(" ms: %d [%d], fps: %3.1f", msTotal, ms0, + // FRAME_COUNT / fTotalTime); + str.printf(" fps:%3.1f", FRAME_COUNT / fTotalTime); + hwnd->setTitle(NULL); + fTotalTime = totalNow; + fTime0 = fTime1 = 0; + fFrameCounter = 0; + } + } +}; + +static FPSState gFPS; + +#define FPS_StartDraw() gFPS.startDraw() +#define FPS_EndDraw() gFPS.endDraw() +#define FPS_Flush(wind) gFPS.flush(wind) + +/////////////////////////////////////////////////////////////////////////////// + +- (id)initWithDefaults { + if (self = [super initWithDefaults]) { + fRedrawRequestPending = false; + fFPSState = new FPSState; + +#ifdef USE_GL_1 + fGL.fContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; +#else + fGL.fContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; +#endif + + if (!fGL.fContext || ![EAGLContext setCurrentContext:fGL.fContext]) + { + [self release]; + return nil; + } + + // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer + glGenFramebuffers(1, &fGL.fFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, fGL.fFramebuffer); + + glGenRenderbuffers(1, &fGL.fRenderbuffer); + glGenRenderbuffers(1, &fGL.fStencilbuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fGL.fRenderbuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, fGL.fStencilbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fGL.fStencilbuffer); + + self.fGLLayer = [CAEAGLLayer layer]; + fGLLayer.bounds = self.bounds; + fGLLayer.anchorPoint = CGPointMake(0, 0); + fGLLayer.opaque = TRUE; + [self.layer addSublayer:fGLLayer]; + fGLLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], + kEAGLDrawablePropertyRetainedBacking, + SKGL_CONFIG, + kEAGLDrawablePropertyColorFormat, + nil]; + + self.fRasterLayer = [CALayer layer]; + fRasterLayer.anchorPoint = CGPointMake(0, 0); + fRasterLayer.opaque = TRUE; + [self.layer addSublayer:fRasterLayer]; + + NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"onOrderIn", + [NSNull null], @"onOrderOut", + [NSNull null], @"sublayers", + [NSNull null], @"contents", + [NSNull null], @"bounds", + nil]; + fGLLayer.actions = newActions; + fRasterLayer.actions = newActions; + [newActions release]; + + fDevManager = new SkiOSDeviceManager(fGL.fFramebuffer); + static char* kDummyArgv = const_cast<char*>("dummyExecutableName"); + fWind = new SampleWindow(self, 1, &kDummyArgv, fDevManager); + + fWind->resize(self.frame.size.width, self.frame.size.height, + kN32_SkColorType); + } + return self; +} + +- (void)dealloc { + delete fDevManager; + delete fFPSState; + self.fRasterLayer = nil; + self.fGLLayer = nil; + [fGL.fContext release]; + [super dealloc]; +} + +- (void)layoutSubviews { + int W, H; + + // Allocate color buffer backing based on the current layer size + glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer); + [fGL.fContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:fGLLayer]; + + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &fGL.fWidth); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &fGL.fHeight); + + glBindRenderbuffer(GL_RENDERBUFFER, fGL.fStencilbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fGL.fWidth, fGL.fHeight); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } + + if (fDevManager->isUsingGL()) { + W = fGL.fWidth; + H = fGL.fHeight; + CGRect rect = CGRectMake(0, 0, W, H); + fGLLayer.bounds = rect; + } + else { + CGRect rect = self.bounds; + W = (int)CGRectGetWidth(rect); + H = (int)CGRectGetHeight(rect); + fRasterLayer.bounds = rect; + } + + printf("---- layoutSubviews %d %d\n", W, H); + fWind->resize(W, H); + fWind->inval(NULL); +} + +/////////////////////////////////////////////////////////////////////////////// + +- (void)drawWithCanvas:(SkCanvas*)canvas { + fRedrawRequestPending = false; + fFPSState->startDraw(); + fWind->draw(canvas); + fFPSState->endDraw(); +#ifdef FORCE_REDRAW + fWind->inval(NULL); +#endif + fFPSState->flush(fWind); +} + +- (void)drawInGL { + // This application only creates a single context which is already set current at this point. + // This call is redundant, but needed if dealing with multiple contexts. + [EAGLContext setCurrentContext:fGL.fContext]; + + // This application only creates a single default framebuffer which is already bound at this point. + // This call is redundant, but needed if dealing with multiple framebuffers. + glBindFramebuffer(GL_FRAMEBUFFER, fGL.fFramebuffer); + + GLint scissorEnable; + glGetIntegerv(GL_SCISSOR_TEST, &scissorEnable); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + if (scissorEnable) { + glEnable(GL_SCISSOR_TEST); + } + glViewport(0, 0, fGL.fWidth, fGL.fHeight); + + + SkAutoTUnref<SkCanvas> canvas(fWind->createCanvas()); + // if we're not "retained", then we have to always redraw everything. + // This call forces us to ignore the fDirtyRgn, and draw everywhere. + // If we are "retained", we can skip this call (as the raster case does) + fWind->forceInvalAll(); + + [self drawWithCanvas:canvas]; + + // This application only creates a single color renderbuffer which is already bound at this point. + // This call is redundant, but needed if dealing with multiple renderbuffers. + glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer); + [fGL.fContext presentRenderbuffer:GL_RENDERBUFFER]; + +} + +- (void)drawInRaster { + SkAutoTUnref<SkCanvas> canvas(fWind->createCanvas()); + [self drawWithCanvas:canvas]; + CGImageRef cgimage = SkCreateCGImageRef(fWind->getBitmap()); + fRasterLayer.contents = (id)cgimage; + CGImageRelease(cgimage); +} + +- (void)forceRedraw { + if (fDevManager->isUsingGL()) + [self drawInGL]; + else + [self drawInRaster]; +} + +/////////////////////////////////////////////////////////////////////////////// + +- (void)setSkTitle:(const char *)title { + NSString* text = [NSString stringWithUTF8String:title]; + if ([text length] > 0) + self.fTitle = text; + + if (fTitleItem && fTitle) { + fTitleItem.title = [NSString stringWithFormat:@"%@%@", fTitle, + [NSString stringWithUTF8String:fFPSState->str.c_str()]]; + } +} + +- (void)postInvalWithRect:(const SkIRect*)r { + if (!fRedrawRequestPending) { + fRedrawRequestPending = true; + bool gl = fDevManager->isUsingGL(); + [CATransaction begin]; + [CATransaction setAnimationDuration:0]; + fRasterLayer.hidden = gl; + fGLLayer.hidden = !gl; + [CATransaction commit]; + if (gl) { + [self performSelector:@selector(drawInGL) withObject:nil afterDelay:0]; + } + else { + [self performSelector:@selector(drawInRaster) withObject:nil afterDelay:0]; + [self setNeedsDisplay]; + } + } +} + +- (void)getAttachmentInfo:(SkOSWindow::AttachmentInfo*)info { + glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, + GL_RENDERBUFFER_STENCIL_SIZE, + &info->fStencilBits); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, + GL_RENDERBUFFER_SAMPLES_APPLE, + &info->fSampleCount); +} + +@end |