summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm')
-rw-r--r--chromium/third_party/skia/experimental/iOSSampleApp/SkSampleUIView.mm494
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