blob: 5ff8362b0ebb44f311de56804092214305e05549 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkCanvas.h"
2#include "SkDevice.h"
3#include "SkGLCanvas.h"
4#include "SkGraphics.h"
5#include "SkPaint.h"
6#include "SkPicture.h"
7#include "SkStream.h"
8#include "SkWindow.h"
9
10#include "SampleCode.h"
11
12#include <AGL/agl.h>
13#include <OpenGL/gl.h>
14
15#define ANIMATING_EVENTTYPE "nextSample"
16#define ANIMATING_DELAY 750
17
18#define USE_OFFSCREEN
19
20SkViewRegister* SkViewRegister::gHead;
21SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
22 static bool gOnce;
23 if (!gOnce) {
24 gHead = NULL;
25 gOnce = true;
26 }
27
28 fChain = gHead;
29 gHead = this;
30}
31
32static AGLContext gAGLContext;
33
34static void init_gl(WindowRef wref) {
35 GLint major, minor;
36
37 aglGetVersion(&major, &minor);
38 SkDebugf("---- agl version %d %d\n", major, minor);
39
40 const GLint pixelAttrs[] = {
41 AGL_RGBA,
42 AGL_DEPTH_SIZE, 32,
43 AGL_OFFSCREEN,
44 AGL_NONE
45 };
46
47 AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
48 SkDebugf("----- agl format %p\n", format);
49 gAGLContext = aglCreateContext(format, NULL);
50 SkDebugf("----- agl context %p\n", gAGLContext);
51 aglDestroyPixelFormat(format);
52
53 aglEnable(gAGLContext, GL_BLEND);
54 aglEnable(gAGLContext, GL_LINE_SMOOTH);
55 aglEnable(gAGLContext, GL_POINT_SMOOTH);
56 aglEnable(gAGLContext, GL_POLYGON_SMOOTH);
57
58 aglSetCurrentContext(gAGLContext);
59}
60
61static void setup_offscreen_gl(const SkBitmap& offscreen, WindowRef wref) {
62 GLboolean success = true;
63
64#ifdef USE_OFFSCREEN
65 success = aglSetOffScreen(gAGLContext,
66 offscreen.width(),
67 offscreen.height(),
68 offscreen.rowBytes(),
69 offscreen.getPixels());
70#else
71 success = aglSetWindowRef(gAGLContext, wref);
72#endif
73
74 GLenum err = aglGetError();
75 if (err) {
76 SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err,
77 aglErrorString(err), offscreen.width(), offscreen.height());
78 }
79
80 glEnable(GL_BLEND);
81 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
82 glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
83 glEnable(GL_TEXTURE_2D);
84
85 glClearColor(0, 0, 0, 0);
86 glClear(GL_COLOR_BUFFER_BIT);
87}
88
89//////////////////////////////////////////////////////////////////////////////
90
91static const char gTitleEvtName[] = "SampleCode_Title_Event";
92static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
93
94bool SampleCode::TitleQ(const SkEvent& evt) {
95 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
96}
97
98void SampleCode::TitleR(SkEvent* evt, const char title[]) {
99 SkASSERT(evt && TitleQ(*evt));
100 evt->setString(gTitleEvtName, title);
101}
102
103bool SampleCode::PrefSizeQ(const SkEvent& evt) {
104 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
105}
106
107void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
108 SkASSERT(evt && PrefSizeQ(*evt));
109 SkScalar size[2];
110 size[0] = width;
111 size[1] = height;
112 evt->setScalars(gPrefSizeEvtName, 2, size);
113}
114
115//////////////////////////////////////////////////////////////////////////////
116
117class SampleWindow : public SkOSWindow {
118public:
119 SampleWindow(void* hwnd);
120 virtual ~SampleWindow();
121
122protected:
123 virtual void onDraw(SkCanvas* canvas);
124 virtual bool onHandleKey(SkKey key);
125 virtual bool onHandleChar(SkUnichar);
126 virtual void onSizeChange();
127
128 virtual SkCanvas* beforeChildren(SkCanvas*);
129 virtual void afterChildren(SkCanvas*);
130
131 virtual bool onEvent(const SkEvent& evt);
132
133#if 0
134 virtual bool handleChar(SkUnichar uni);
135 virtual bool handleEvent(const SkEvent& evt);
136 virtual bool handleKey(SkKey key);
137 virtual bool handleKeyUp(SkKey key);
138
139 virtual bool onClick(Click* click);
140 virtual Click* onFindClickHandler(SkScalar x, SkScalar y);
141 virtual bool onHandleKeyUp(SkKey key);
142#endif
143private:
144 const SkViewRegister* fCurr;
145
146 SkPicture* fPicture;
147 SkGLCanvas* fGLCanvas;
148 SkPath fClipPath;
149
150 enum CanvasType {
151 kRaster_CanvasType,
152 kPicture_CanvasType,
153 kOpenGL_CanvasType
154 };
155 CanvasType fCanvasType;
156
157 bool fUseClip;
158 bool fRepeatDrawing;
159 bool fAnimating;
160
161 int fScrollTestX, fScrollTestY;
162
163 void loadView(SkView*);
164 void updateTitle();
165 bool nextSample();
166
167 void postAnimatingEvent() {
168 if (fAnimating) {
169 SkEvent* evt = new SkEvent(ANIMATING_EVENTTYPE);
170 evt->post(this->getSinkID(), ANIMATING_DELAY);
171 }
172 }
173
174
175 static CanvasType cycle_canvastype(CanvasType);
176
177 typedef SkOSWindow INHERITED;
178};
179
180SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
181 static const CanvasType gCT[] = {
182 kPicture_CanvasType,
183 kOpenGL_CanvasType,
184 kRaster_CanvasType
185 };
186 return gCT[ct];
187}
188
189SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
190 init_gl((WindowRef)hwnd);
191
192 fPicture = NULL;
193 fGLCanvas = NULL;
194
195 fCanvasType = kRaster_CanvasType;
196 fUseClip = false;
197 fRepeatDrawing = false;
198 fAnimating = false;
199
200 fScrollTestX = fScrollTestY = 0;
201
202// this->setConfig(SkBitmap::kRGB_565_Config);
203 this->setConfig(SkBitmap::kARGB_8888_Config);
204 this->setVisibleP(true);
205
206 fCurr = SkViewRegister::Head();
207 this->loadView(fCurr->factory()());
208}
209
210SampleWindow::~SampleWindow() {
211 delete fPicture;
212 delete fGLCanvas;
213}
214
215void SampleWindow::onDraw(SkCanvas* canvas) {
216 if (fRepeatDrawing) {
217 this->inval(NULL);
218 }
219}
220
221#include "SkColorPriv.h"
222
223static void reverseRedAndBlue(const SkBitmap& bm) {
224 SkASSERT(bm.config() == SkBitmap::kARGB_8888_Config);
225 uint8_t* p = (uint8_t*)bm.getPixels();
226 uint8_t* stop = p + bm.getSize();
227 while (p < stop) {
228 // swap red/blue (to go from ARGB(int) to RGBA(memory) and premultiply
229 unsigned scale = SkAlpha255To256(p[3]);
230 unsigned r = p[2];
231 unsigned b = p[0];
232 p[0] = SkAlphaMul(r, scale);
233 p[1] = SkAlphaMul(p[1], scale);
234 p[2] = SkAlphaMul(b, scale);
235 p += 4;
236 }
237}
238
239SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
240#ifndef USE_OFFSCREEN
241 aglSetWindowRef(gAGLContext, NULL);
242#endif
243 switch (fCanvasType) {
244 case kRaster_CanvasType:
245 canvas = this->INHERITED::beforeChildren(canvas);
246 break;
247 case kPicture_CanvasType:
248 fPicture = new SkPicture;
249 canvas = fPicture->beginRecording(9999, 9999);
250 break;
251 case kOpenGL_CanvasType: {
252 //SkGLCanvas::DeleteAllTextures(); // just for testing
253 SkDevice* device = canvas->getDevice();
254 const SkBitmap& bitmap = device->accessBitmap(true);
255 // first clear the raster bitmap, so we don't see any leftover bits
256 bitmap.eraseColor(0);
257 // now setup our glcanvas
258 setup_offscreen_gl(bitmap, (WindowRef)this->getHWND());
259 fGLCanvas = new SkGLCanvas;
260 fGLCanvas->setViewport(bitmap.width(), bitmap.height());
261 canvas = fGLCanvas;
262 break;
263 }
264 }
265
266 if (fUseClip) {
267 canvas->drawColor(0xFFFF88FF);
268 canvas->clipPath(fClipPath);
269 }
270
271 return canvas;
272}
273
274static void paint_rgn(const SkBitmap& bm, const SkIRect& r,
275 const SkRegion& rgn) {
276 SkCanvas canvas(bm);
277 SkRegion inval(rgn);
278
279 inval.translate(r.fLeft, r.fTop);
280 canvas.clipRegion(inval);
281 canvas.drawColor(0xFFFF8080);
282}
283
284void SampleWindow::afterChildren(SkCanvas* orig) {
285 switch (fCanvasType) {
286 case kRaster_CanvasType:
287 break;
288 case kPicture_CanvasType:
289 if (false) {
290 SkPicture* pict = new SkPicture(*fPicture);
291 fPicture->unref();
292 orig->drawPicture(*pict);
293 pict->unref();
294 } if (true) {
295 SkDynamicMemoryWStream ostream;
296 fPicture->serialize(&ostream);
297 fPicture->unref();
298
299 SkMemoryStream istream(ostream.getStream(), ostream.getOffset());
300 SkPicture pict(&istream);
301 orig->drawPicture(pict);
302 } else {
303 fPicture->draw(orig);
304 fPicture->unref();
305 }
306 fPicture = NULL;
307 break;
308 case kOpenGL_CanvasType:
309 glFlush();
310 delete fGLCanvas;
311 fGLCanvas = NULL;
312#ifdef USE_OFFSCREEN
313 reverseRedAndBlue(orig->getDevice()->accessBitmap(true));
314#endif
315 break;
316 }
317
318// if ((fScrollTestX | fScrollTestY) != 0)
319 {
320 const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
321 int dx = fScrollTestX * 7;
322 int dy = fScrollTestY * 7;
323 SkIRect r;
324 SkRegion inval;
325
326 r.set(50, 50, 50+100, 50+100);
327 bm.scrollRect(&r, dx, dy, &inval);
328 paint_rgn(bm, r, inval);
329 }
330}
331
332static SkBitmap::Config gConfigCycle[] = {
333 SkBitmap::kNo_Config, // none -> none
334 SkBitmap::kNo_Config, // a1 -> none
335 SkBitmap::kNo_Config, // a8 -> none
336 SkBitmap::kNo_Config, // index8 -> none
337 SkBitmap::kARGB_4444_Config, // 565 -> 4444
338 SkBitmap::kARGB_8888_Config, // 4444 -> 8888
339 SkBitmap::kRGB_565_Config // 8888 -> 565
340};
341
342static SkBitmap::Config cycle_configs(SkBitmap::Config c) {
343 return gConfigCycle[c];
344}
345
346bool SampleWindow::nextSample() {
347 if (fCurr) {
348 fCurr = fCurr->next();
349 if (NULL == fCurr) {
350 fCurr = SkViewRegister::Head();
351 }
352 this->loadView(fCurr->factory()());
353 return true;
354 }
355 return false;
356}
357
358bool SampleWindow::onEvent(const SkEvent& evt) {
359 if (evt.isType(ANIMATING_EVENTTYPE)) {
360 if (fAnimating) {
361 this->nextSample();
362 this->postAnimatingEvent();
363 }
364 return true;
365 }
366 return this->INHERITED::onEvent(evt);
367}
368
369
370bool SampleWindow::onHandleChar(SkUnichar uni) {
371 int dx = 0xFF;
372 int dy = 0xFF;
373
374 switch (uni) {
375 case '5': dx = 0; dy = 0; break;
376 case '8': dx = 0; dy = -1; break;
377 case '6': dx = 1; dy = 0; break;
378 case '2': dx = 0; dy = 1; break;
379 case '4': dx = -1; dy = 0; break;
380 case '7': dx = -1; dy = -1; break;
381 case '9': dx = 1; dy = -1; break;
382 case '3': dx = 1; dy = 1; break;
383 case '1': dx = -1; dy = 1; break;
384
385 default:
386 break;
387 }
388
389 if (0xFF != dx && 0xFF != dy) {
390 if ((dx | dy) == 0) {
391 fScrollTestX = fScrollTestY = 0;
392 } else {
393 fScrollTestX += dx;
394 fScrollTestY += dy;
395 }
396 this->inval(NULL);
397 return true;
398 }
399
400 if ('a' == uni) {
401 fAnimating = !fAnimating;
402 this->postAnimatingEvent();
403 this->updateTitle();
404 }
405
406 return this->INHERITED::onHandleChar(uni);
407}
408
409#include "SkDumpCanvas.h"
410
411bool SampleWindow::onHandleKey(SkKey key) {
412 switch (key) {
413 case kRight_SkKey:
414 if (this->nextSample()) {
415 return true;
416 }
417 break;
418 case kLeft_SkKey:
419 fCanvasType = cycle_canvastype(fCanvasType);
420 this->updateTitle();
421 this->inval(NULL);
422 return true;
423 case kUp_SkKey:
424 fUseClip = !fUseClip;
425 this->updateTitle();
426 this->inval(NULL);
427 return true;
428 case kDown_SkKey:
429 this->setConfig(cycle_configs(this->getBitmap().config()));
430 this->updateTitle();
431 return true;
432 case kOK_SkKey:
433 if (true) {
434 SkDebugfDumper dumper;
435 SkDumpCanvas dc(&dumper);
436 this->draw(&dc);
437 } else {
438 fRepeatDrawing = !fRepeatDrawing;
439 if (fRepeatDrawing) {
440 this->inval(NULL);
441 }
442 }
443 return true;
444 default:
445 break;
446 }
447 return this->INHERITED::onHandleKey(key);
448}
449
450void SampleWindow::loadView(SkView* view) {
451 SkView::F2BIter iter(this);
452 SkView* prev = iter.next();
453 if (prev) {
454 prev->detachFromParent();
455 }
456 view->setVisibleP(true);
457 this->attachChildToFront(view)->unref();
458 view->setSize(this->width(), this->height());
459
460 this->updateTitle();
461}
462
463static const char* gConfigNames[] = {
464 "unknown config",
465 "A1",
466 "A8",
467 "Index8",
468 "565",
469 "4444",
470 "8888"
471};
472
473static const char* configToString(SkBitmap::Config c) {
474 return gConfigNames[c];
475}
476
477static const char* gCanvasTypePrefix[] = {
478 "raster: ",
479 "picture: ",
480 "opengl: "
481};
482
483void SampleWindow::updateTitle() {
484 SkString title;
485
486 SkView::F2BIter iter(this);
487 SkView* view = iter.next();
488 SkEvent evt(gTitleEvtName);
489 if (view->doQuery(&evt)) {
490 title.set(evt.findString(gTitleEvtName));
491 }
492 if (title.size() == 0) {
493 title.set("<unknown>");
494 }
495
496 title.prepend(gCanvasTypePrefix[fCanvasType]);
497
498 title.prepend(" ");
499 title.prepend(configToString(this->getBitmap().config()));
500
501 if (fAnimating) {
502 title.prepend("<A> ");
503 }
504
505 this->setTitle(title.c_str());
506}
507
508void SampleWindow::onSizeChange() {
509 this->INHERITED::onSizeChange();
510
511 SkView::F2BIter iter(this);
512 SkView* view = iter.next();
513 view->setSize(this->width(), this->height());
514
515 // rebuild our clippath
516 {
517 const SkScalar W = this->width();
518 const SkScalar H = this->height();
519
520 fClipPath.reset();
521#if 0
522 for (SkScalar y = SK_Scalar1; y < H; y += SkIntToScalar(32)) {
523 SkRect r;
524 r.set(SK_Scalar1, y, SkIntToScalar(30), y + SkIntToScalar(30));
525 for (; r.fLeft < W; r.offset(SkIntToScalar(32), 0))
526 fClipPath.addRect(r);
527 }
528#else
529 SkRect r;
530 r.set(0, 0, W, H);
531 fClipPath.addRect(r, SkPath::kCCW_Direction);
532 r.set(W/4, H/4, W*3/4, H*3/4);
533 fClipPath.addRect(r, SkPath::kCW_Direction);
534#endif
535 }
536
537 this->updateTitle(); // to refresh our config
538}
539
540///////////////////////////////////////////////////////////////////////////////
541
542SkOSWindow* create_sk_window(void* hwnd) {
543 return new SampleWindow(hwnd);
544}
545
546void get_preferred_size(int* x, int* y, int* width, int* height) {
547 *x = 10;
548 *y = 50;
549 *width = 640;
550 *height = 480;
551}
552
553void application_init() {
554// setenv("ANDROID_ROOT", "../../../data", 0);
555 setenv("ANDROID_ROOT", "/android/device/data", 0);
556 SkGraphics::Init(true);
557 SkEvent::Init();
558}
559
560void application_term() {
561 SkEvent::Term();
562 SkGraphics::Term();
563}