Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / experimental / iOSSampleApp / SkSampleUIView.mm
1 #import "SkSampleUIView.h"
2
3 #define SKGL_CONFIG         kEAGLColorFormatRGB565
4 //#define SKGL_CONFIG         kEAGLColorFormatRGBA8
5
6 #define FORCE_REDRAW
7
8 #include "SkCanvas.h"
9 #include "SkCGUtils.h"
10 #include "SkSurface.h"
11 #include "SampleApp.h"
12
13 #if SK_SUPPORT_GPU
14 //#define USE_GL_1
15 #define USE_GL_2
16
17 #include "gl/GrGLInterface.h"
18 #include "GrContext.h"
19 #include "SkGpuDevice.h"
20 #endif
21
22 class SkiOSDeviceManager : public SampleWindow::DeviceManager {
23 public:
24     SkiOSDeviceManager(GLint layerFBO) {
25 #if SK_SUPPORT_GPU
26         fCurContext = NULL;
27         fCurIntf = NULL;
28         fCurRenderTarget = NULL;
29         fMSAASampleCount = 0;
30         fLayerFBO = layerFBO;
31 #endif
32         fBackend = SkOSWindow::kNone_BackEndType;
33     }
34     
35     virtual ~SkiOSDeviceManager() {
36 #if SK_SUPPORT_GPU
37         SkSafeUnref(fCurContext);
38         SkSafeUnref(fCurIntf);
39         SkSafeUnref(fCurRenderTarget);
40 #endif
41     }
42     
43     virtual void setUpBackend(SampleWindow* win, int msaaSampleCount) SK_OVERRIDE {
44         SkASSERT(SkOSWindow::kNone_BackEndType == fBackend);
45         
46         fBackend = SkOSWindow::kNone_BackEndType;
47         
48 #if SK_SUPPORT_GPU
49         switch (win->getDeviceType()) {
50             // these two don't use GL
51             case SampleWindow::kRaster_DeviceType:
52             case SampleWindow::kPicture_DeviceType:
53                 break;
54             // these guys use the native backend
55             case SampleWindow::kGPU_DeviceType:
56             case SampleWindow::kNullGPU_DeviceType:
57                 fBackend = SkOSWindow::kNativeGL_BackEndType;
58                 break;
59             default:
60                 SkASSERT(false);
61                 break;
62         }
63         SkOSWindow::AttachmentInfo info;
64         bool result = win->attach(fBackend, msaaSampleCount, &info);
65         if (!result) {
66             SkDebugf("Failed to initialize GL");
67             return;
68         }
69         fMSAASampleCount = msaaSampleCount;
70         
71         SkASSERT(NULL == fCurIntf);
72         switch (win->getDeviceType()) {
73             // these two don't use GL
74             case SampleWindow::kRaster_DeviceType:
75             case SampleWindow::kPicture_DeviceType:
76                 fCurIntf = NULL;
77                 break;
78             case SampleWindow::kGPU_DeviceType:
79                 fCurIntf = GrGLCreateNativeInterface();
80                 break;
81             case SampleWindow::kNullGPU_DeviceType:
82                 fCurIntf = GrGLCreateNullInterface();
83                 break;
84             default:
85                 SkASSERT(false);
86                 break;
87         }
88         
89         SkASSERT(NULL == fCurContext);
90         if (SkOSWindow::kNone_BackEndType != fBackend) {
91             fCurContext = GrContext::Create(kOpenGL_GrBackend,
92                                             (GrBackendContext) fCurIntf);
93         }
94         
95         if ((NULL == fCurContext || NULL == fCurIntf) &&
96             SkOSWindow::kNone_BackEndType != fBackend) {
97             // We need some context and interface to see results if we're using a GL backend
98             SkSafeUnref(fCurContext);
99             SkSafeUnref(fCurIntf);
100             SkDebugf("Failed to setup 3D");
101             win->detach();
102         }
103 #endif // SK_SUPPORT_GPU
104         // call windowSizeChanged to create the render target
105         this->windowSizeChanged(win);
106     }
107     
108     virtual void tearDownBackend(SampleWindow *win) SK_OVERRIDE {
109 #if SK_SUPPORT_GPU
110         SkSafeUnref(fCurContext);
111         fCurContext = NULL;
112         
113         SkSafeUnref(fCurIntf);
114         fCurIntf = NULL;
115         
116         SkSafeUnref(fCurRenderTarget);
117         fCurRenderTarget = NULL;
118 #endif
119         win->detach();
120         fBackend = SampleWindow::kNone_BackEndType;
121     }
122
123     virtual SkSurface* createSurface(SampleWindow::DeviceType dType, SampleWindow* win) SK_OVERRIDE{
124 #if SK_SUPPORT_GPU
125         if (SampleWindow::IsGpuDeviceType(dType) && fCurContext) {
126             SkSurfaceProps props(win->getSurfaceProps());
127             return SkSurface::NewRenderTargetDirect(fCurRenderTarget, &props);
128         }
129 #endif
130         return NULL;
131     }
132
133     virtual void publishCanvas(SampleWindow::DeviceType dType,
134                                SkCanvas* canvas,
135                                SampleWindow* win) SK_OVERRIDE {
136 #if SK_SUPPORT_GPU
137         if (NULL != fCurContext) {
138             fCurContext->flush();
139         }
140 #endif
141         win->present();
142     }
143     
144     virtual void windowSizeChanged(SampleWindow* win) SK_OVERRIDE {
145 #if SK_SUPPORT_GPU
146         if (NULL != fCurContext) {
147             SkOSWindow::AttachmentInfo info;
148
149             win->attach(fBackend, fMSAASampleCount, &info);
150             
151             glBindFramebuffer(GL_FRAMEBUFFER, fLayerFBO);
152             GrBackendRenderTargetDesc desc;
153             desc.fWidth = SkScalarRoundToInt(win->width());
154             desc.fHeight = SkScalarRoundToInt(win->height());
155             desc.fConfig = kSkia8888_GrPixelConfig;
156             desc.fRenderTargetHandle = fLayerFBO;
157             desc.fSampleCnt = info.fSampleCount;
158             desc.fStencilBits = info.fStencilBits;
159
160             SkSafeUnref(fCurRenderTarget);
161             fCurRenderTarget = fCurContext->wrapBackendRenderTarget(desc);
162         }
163 #endif
164     }
165     
166     virtual GrContext* getGrContext() SK_OVERRIDE {
167 #if SK_SUPPORT_GPU
168         return fCurContext;
169 #else
170         return NULL;
171 #endif
172     }
173     
174     virtual GrRenderTarget* getGrRenderTarget() SK_OVERRIDE {
175 #if SK_SUPPORT_GPU
176         return fCurRenderTarget;
177 #else
178         return NULL;
179 #endif
180     }
181     
182     bool isUsingGL() const { return SkOSWindow::kNone_BackEndType != fBackend; }
183     
184 private:
185    
186 #if SK_SUPPORT_GPU
187     GrContext*              fCurContext;
188     const GrGLInterface*    fCurIntf;
189     GrRenderTarget*         fCurRenderTarget;
190     int                     fMSAASampleCount;
191     GLint                   fLayerFBO;
192 #endif
193     
194     SkOSWindow::SkBackEndTypes fBackend;
195     
196     typedef SampleWindow::DeviceManager INHERITED;
197 };
198
199 ////////////////////////////////////////////////////////////////////////////////
200 @implementation SkSampleUIView
201
202 @synthesize fTitle, fRasterLayer, fGLLayer;
203
204 #include "SkApplication.h"
205 #include "SkEvent.h"
206 #include "SkWindow.h"
207
208 struct FPSState {
209     static const int FRAME_COUNT = 60;
210     
211     CFTimeInterval fNow0, fNow1;
212     CFTimeInterval fTime0, fTime1, fTotalTime;
213     int fFrameCounter;
214     SkString str;
215     FPSState() {
216         fTime0 = fTime1 = fTotalTime = 0;
217         fFrameCounter = 0;
218     }
219     
220     void startDraw() {
221         fNow0 = CACurrentMediaTime();
222     }
223     
224     void endDraw() {
225         fNow1 = CACurrentMediaTime();
226     }
227     
228     void flush(SkOSWindow* hwnd) {
229         CFTimeInterval now2 = CACurrentMediaTime();
230         
231         fTime0 += fNow1 - fNow0;
232         fTime1 += now2 - fNow1;
233         
234         if (++fFrameCounter == FRAME_COUNT) {
235             CFTimeInterval totalNow = CACurrentMediaTime();
236             fTotalTime = totalNow - fTotalTime;
237             
238             //SkMSec ms0 = (int)(1000 * fTime0 / FRAME_COUNT);
239             //SkMSec msTotal = (int)(1000 * fTotalTime / FRAME_COUNT);
240             //str.printf(" ms: %d [%d], fps: %3.1f", msTotal, ms0,
241             //           FRAME_COUNT / fTotalTime);
242             str.printf(" fps:%3.1f", FRAME_COUNT / fTotalTime);
243             hwnd->setTitle(NULL);
244             fTotalTime = totalNow;
245             fTime0 = fTime1 = 0;
246             fFrameCounter = 0;
247         }
248     }
249 };
250
251 static FPSState gFPS;
252
253 #define FPS_StartDraw() gFPS.startDraw()
254 #define FPS_EndDraw()   gFPS.endDraw()
255 #define FPS_Flush(wind) gFPS.flush(wind)
256
257 ///////////////////////////////////////////////////////////////////////////////
258
259 - (id)initWithDefaults {
260     if (self = [super initWithDefaults]) {
261         fRedrawRequestPending = false;
262         fFPSState = new FPSState;
263         
264 #ifdef USE_GL_1
265         fGL.fContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
266 #else
267         fGL.fContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
268 #endif
269         
270         if (!fGL.fContext || ![EAGLContext setCurrentContext:fGL.fContext])
271         {
272             [self release];
273             return nil;
274         }
275         
276         // Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
277         glGenFramebuffers(1, &fGL.fFramebuffer);
278         glBindFramebuffer(GL_FRAMEBUFFER, fGL.fFramebuffer);
279         
280         glGenRenderbuffers(1, &fGL.fRenderbuffer);
281         glGenRenderbuffers(1, &fGL.fStencilbuffer);
282         
283         glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer);
284         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fGL.fRenderbuffer);
285         
286         glBindRenderbuffer(GL_RENDERBUFFER, fGL.fStencilbuffer);
287         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fGL.fStencilbuffer);
288         
289         self.fGLLayer = [CAEAGLLayer layer];
290         fGLLayer.bounds = self.bounds;
291         fGLLayer.anchorPoint = CGPointMake(0, 0);
292         fGLLayer.opaque = TRUE;
293         [self.layer addSublayer:fGLLayer];
294         fGLLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
295                                        [NSNumber numberWithBool:NO],
296                                        kEAGLDrawablePropertyRetainedBacking,
297                                        SKGL_CONFIG,
298                                        kEAGLDrawablePropertyColorFormat,
299                                        nil];
300         
301         self.fRasterLayer = [CALayer layer];
302         fRasterLayer.anchorPoint = CGPointMake(0, 0);
303         fRasterLayer.opaque = TRUE;
304         [self.layer addSublayer:fRasterLayer];
305         
306         NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"onOrderIn",
307                                            [NSNull null], @"onOrderOut",
308                                            [NSNull null], @"sublayers",
309                                            [NSNull null], @"contents",
310                                            [NSNull null], @"bounds",
311                                            nil];
312         fGLLayer.actions = newActions;
313         fRasterLayer.actions = newActions;
314         [newActions release];
315         
316         fDevManager = new SkiOSDeviceManager(fGL.fFramebuffer);
317         static char* kDummyArgv = const_cast<char*>("dummyExecutableName");
318         fWind = new SampleWindow(self, 1, &kDummyArgv, fDevManager);
319
320         fWind->resize(self.frame.size.width, self.frame.size.height,
321                       kN32_SkColorType);
322     }
323     return self;
324 }
325
326 - (void)dealloc {
327     delete fDevManager;
328     delete fFPSState;
329     self.fRasterLayer = nil;
330     self.fGLLayer = nil;
331     [fGL.fContext release];
332     [super dealloc];
333 }
334
335 - (void)layoutSubviews {
336     int W, H;
337     
338     // Allocate color buffer backing based on the current layer size
339     glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer);
340     [fGL.fContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:fGLLayer];
341     
342     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &fGL.fWidth);
343     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &fGL.fHeight);
344     
345     glBindRenderbuffer(GL_RENDERBUFFER, fGL.fStencilbuffer);
346     glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fGL.fWidth, fGL.fHeight);
347     
348     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
349         NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
350     }
351     
352     if (fDevManager->isUsingGL()) {
353         W = fGL.fWidth;
354         H = fGL.fHeight;
355         CGRect rect = CGRectMake(0, 0, W, H);
356         fGLLayer.bounds = rect;
357     }
358     else {
359         CGRect rect = self.bounds;
360         W = (int)CGRectGetWidth(rect);
361         H = (int)CGRectGetHeight(rect);
362         fRasterLayer.bounds = rect;
363     }
364     
365     printf("---- layoutSubviews %d %d\n", W, H);
366     fWind->resize(W, H);
367     fWind->inval(NULL);
368 }
369
370 ///////////////////////////////////////////////////////////////////////////////
371
372 - (void)drawWithCanvas:(SkCanvas*)canvas {
373     fRedrawRequestPending = false;
374     fFPSState->startDraw();
375     fWind->draw(canvas);
376     fFPSState->endDraw();
377 #ifdef FORCE_REDRAW
378     fWind->inval(NULL);
379 #endif
380     fFPSState->flush(fWind);
381 }
382
383 - (void)drawInGL {
384     // This application only creates a single context which is already set current at this point.
385     // This call is redundant, but needed if dealing with multiple contexts.
386     [EAGLContext setCurrentContext:fGL.fContext];
387     
388     // This application only creates a single default framebuffer which is already bound at this point.
389     // This call is redundant, but needed if dealing with multiple framebuffers.
390     glBindFramebuffer(GL_FRAMEBUFFER, fGL.fFramebuffer);
391     
392     GLint scissorEnable;
393     glGetIntegerv(GL_SCISSOR_TEST, &scissorEnable);
394     glDisable(GL_SCISSOR_TEST);
395     glClearColor(0,0,0,0);
396     glClear(GL_COLOR_BUFFER_BIT);
397     if (scissorEnable) {
398         glEnable(GL_SCISSOR_TEST);
399     }
400     glViewport(0, 0, fGL.fWidth, fGL.fHeight);
401     
402    
403     SkAutoTUnref<SkSurface> surface(fWind->createSurface());
404     SkCanvas* canvas = surface->getCanvas();
405
406     // if we're not "retained", then we have to always redraw everything.
407     // This call forces us to ignore the fDirtyRgn, and draw everywhere.
408     // If we are "retained", we can skip this call (as the raster case does)
409     fWind->forceInvalAll();
410
411     [self drawWithCanvas:canvas];
412
413     // This application only creates a single color renderbuffer which is already bound at this point.
414     // This call is redundant, but needed if dealing with multiple renderbuffers.
415     glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer);
416     [fGL.fContext presentRenderbuffer:GL_RENDERBUFFER];
417 }
418
419 - (void)drawInRaster {
420     SkAutoTUnref<SkSurface> surface(fWind->createSurface());
421     SkCanvas* canvas = surface->getCanvas();
422     [self drawWithCanvas:canvas];
423     CGImageRef cgimage = SkCreateCGImageRef(fWind->getBitmap());
424     fRasterLayer.contents = (id)cgimage;
425     CGImageRelease(cgimage);
426 }
427
428 - (void)forceRedraw {
429     if (fDevManager->isUsingGL())
430         [self drawInGL];
431     else 
432         [self drawInRaster];
433 }
434
435 ///////////////////////////////////////////////////////////////////////////////
436
437 - (void)setSkTitle:(const char *)title {
438     NSString* text = [NSString stringWithUTF8String:title];
439     if ([text length] > 0)
440         self.fTitle = text;
441     
442     if (fTitleItem && fTitle) {
443         fTitleItem.title = [NSString stringWithFormat:@"%@%@", fTitle, 
444                             [NSString stringWithUTF8String:fFPSState->str.c_str()]];
445     }
446 }
447
448 - (void)postInvalWithRect:(const SkIRect*)r {
449     if (!fRedrawRequestPending) {
450         fRedrawRequestPending = true;
451         bool gl = fDevManager->isUsingGL();
452         [CATransaction begin];
453         [CATransaction setAnimationDuration:0];
454         fRasterLayer.hidden = gl;
455         fGLLayer.hidden = !gl;
456         [CATransaction commit];
457         if (gl) {
458             [self performSelector:@selector(drawInGL) withObject:nil afterDelay:0];
459         }
460         else {
461             [self performSelector:@selector(drawInRaster) withObject:nil afterDelay:0];
462             [self setNeedsDisplay];
463         }
464     }
465 }
466
467 - (void)getAttachmentInfo:(SkOSWindow::AttachmentInfo*)info {
468     glBindRenderbuffer(GL_RENDERBUFFER, fGL.fRenderbuffer);
469     glGetRenderbufferParameteriv(GL_RENDERBUFFER,
470                                  GL_RENDERBUFFER_STENCIL_SIZE,
471                                  &info->fStencilBits);
472     glGetRenderbufferParameteriv(GL_RENDERBUFFER,
473                                  GL_RENDERBUFFER_SAMPLES_APPLE,
474                                  &info->fSampleCount);
475 }
476
477 @end