Add MSAA option to SampleApp

Review URL: http://codereview.appspot.com/5969049


git-svn-id: http://skia.googlecode.com/svn/trunk@3627 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/views/unix/SkOSWindow_Unix.cpp b/src/views/unix/SkOSWindow_Unix.cpp
index 66b1694..c8fc2c7 100644
--- a/src/views/unix/SkOSWindow_Unix.cpp
+++ b/src/views/unix/SkOSWindow_Unix.cpp
@@ -34,53 +34,109 @@
 
 SkOSWindow::SkOSWindow(void* unused)
     : INHERITED()
-    , fVi(0) {
-    fUnixWindow.fDisplay = XOpenDisplay(NULL);
+    , fVi(NULL)
+    , fMSAASampleCount(0) {
+    fUnixWindow.fDisplay = NULL;
     fUnixWindow.fGLContext = NULL;
-    Display* dsp = fUnixWindow.fDisplay;
-    if (dsp) {
-        // Attempt to create a window that supports GL
-        GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER,
-                GLX_STENCIL_SIZE, 8, None };
-        fVi = glXChooseVisual(dsp, DefaultScreen(dsp), att);
-        if (fVi) {
-            Colormap colorMap = XCreateColormap(dsp, RootWindow(dsp, fVi->screen),
-                fVi->visual, AllocNone);
-            XSetWindowAttributes swa;
-            swa.colormap = colorMap;
-            swa.event_mask = EVENT_MASK;
-            fUnixWindow.fWin = XCreateWindow(dsp, RootWindow(dsp, fVi->screen),
-                    0, 0, WIDTH, HEIGHT, 0, fVi->depth,
-                    InputOutput, fVi->visual, CWEventMask | CWColormap, &swa);
-
-        } else {
-            // Create a simple window instead.  We will not be able to
-            // show GL
-            fUnixWindow.fWin = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp),
-                    0, 0, WIDTH, HEIGHT, 0, 0, 0);
-        }
-        mapWindowAndWait();
-        fUnixWindow.fGc = XCreateGC(dsp, fUnixWindow.fWin, 0, NULL);
-    }
+    this->initWindow(0);
     this->resize(WIDTH, HEIGHT);
 }
 
 SkOSWindow::~SkOSWindow() {
+    this->closeWindow();
+}
+
+void SkOSWindow::closeWindow() {
     if (NULL != fUnixWindow.fDisplay) {
-        if (NULL != fUnixWindow.fGLContext) {
-            glXMakeCurrent(fUnixWindow.fDisplay, None, NULL);
-            glXDestroyContext(fUnixWindow.fDisplay, fUnixWindow.fGLContext);
-        }
+        this->detach();
+        SkASSERT(NULL != fUnixWindow.fGc);
         XFreeGC(fUnixWindow.fDisplay, fUnixWindow.fGc);
+        fUnixWindow.fGc = NULL;
         XDestroyWindow(fUnixWindow.fDisplay, fUnixWindow.fWin);
+        fVi = NULL;
         XCloseDisplay(fUnixWindow.fDisplay);
-        fUnixWindow.fDisplay = 0;
+        fUnixWindow.fDisplay = NULL;
+        fMSAASampleCount = 0;
     }
 }
 
+void SkOSWindow::initWindow(int requestedMSAASampleCount) {
+    if (fMSAASampleCount != requestedMSAASampleCount) {
+        this->closeWindow();
+    }
+    // presence of fDisplay means we already have a window
+    if (NULL != fUnixWindow.fDisplay) {
+        return;
+    }
+    fUnixWindow.fDisplay = XOpenDisplay(NULL);
+    Display* dsp = fUnixWindow.fDisplay;
+    if (NULL == dsp) {
+        SkDebugf("Could not open an X Display");
+        return;
+    }
+    // Attempt to create a window that supports GL
+    GLint att[] = {
+        GLX_RGBA,
+        GLX_DEPTH_SIZE, 24,
+        GLX_DOUBLEBUFFER,
+        GLX_STENCIL_SIZE, 8,
+        None
+    };
+    SkASSERT(NULL == fVi);
+    if (requestedMSAASampleCount > 0) {
+        static const GLint kAttCount = SK_ARRAY_COUNT(att);
+        GLint msaaAtt[kAttCount + 4];
+        memcpy(msaaAtt, att, sizeof(att));
+        SkASSERT(None == msaaAtt[kAttCount - 1]);
+        msaaAtt[kAttCount - 1] = GLX_SAMPLE_BUFFERS_ARB;
+        msaaAtt[kAttCount + 0] = 1;
+        msaaAtt[kAttCount + 1] = GLX_SAMPLES_ARB;
+        msaaAtt[kAttCount + 2] = requestedMSAASampleCount;
+        msaaAtt[kAttCount + 3] = None;
+        fVi = glXChooseVisual(dsp, DefaultScreen(dsp), msaaAtt);
+        fMSAASampleCount = requestedMSAASampleCount;
+    }
+    if (NULL == fVi) {
+        fVi = glXChooseVisual(dsp, DefaultScreen(dsp), att);
+        fMSAASampleCount = 0;
+    }
+
+    if (fVi) {
+        Colormap colorMap = XCreateColormap(dsp,
+                                            RootWindow(dsp, fVi->screen),
+                                            fVi->visual,
+                                             AllocNone);
+        XSetWindowAttributes swa;
+        swa.colormap = colorMap;
+        swa.event_mask = EVENT_MASK;
+        fUnixWindow.fWin = XCreateWindow(dsp,
+                                         RootWindow(dsp, fVi->screen),
+                                         0, 0, // x, y
+                                         WIDTH, HEIGHT,
+                                         0, // border width
+                                         fVi->depth,
+                                         InputOutput,
+                                         fVi->visual,
+                                         CWEventMask | CWColormap,
+                                         &swa);
+    } else {
+        // Create a simple window instead.  We will not be able to show GL
+        fUnixWindow.fWin = XCreateSimpleWindow(dsp,
+                                               DefaultRootWindow(dsp),
+                                               0, 0,  // x, y
+                                               WIDTH, HEIGHT,
+                                               0,     // border width
+                                               0,     // border value
+                                               0);    // background value
+    }
+    this->mapWindowAndWait();
+    fUnixWindow.fGc = XCreateGC(dsp, fUnixWindow.fWin, 0, NULL);
+}
+
+
 void SkOSWindow::post_linuxevent() {
     // Put an event in the X queue to fire an SkEvent.
-    if (!fUnixWindow.fDisplay) {
+    if (NULL == fUnixWindow.fDisplay) {
         return;
     }
     long event_mask = NoEventMask;
@@ -97,6 +153,9 @@
 
 void SkOSWindow::loop() {
     Display* dsp = fUnixWindow.fDisplay;
+    if (NULL == dsp) {
+        return;
+    }
     XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK);
 
     bool loop = true;
@@ -153,6 +212,7 @@
 }
 
 void SkOSWindow::mapWindowAndWait() {
+    SkASSERT(NULL != fUnixWindow.fDisplay);
     Display* dsp = fUnixWindow.fDisplay;
     Window win = fUnixWindow.fWin;
     XMapWindow(dsp, win);
@@ -168,11 +228,13 @@
 
 }
 
-bool SkOSWindow::attach(SkBackEndTypes /* attachType */) {
+bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int msaaSampleCount) {
+    this->initWindow(msaaSampleCount);
+    if (NULL == fUnixWindow.fDisplay) {
+        return false;
+    } 
     if (NULL == fUnixWindow.fGLContext) {
-        if (NULL == fUnixWindow.fDisplay || NULL == fVi) {
-            return false;
-        }
+        SkASSERT(NULL != fVi);
 
         fUnixWindow.fGLContext = glXCreateContext(fUnixWindow.fDisplay,
                                                   fVi,
@@ -209,7 +271,7 @@
 }
 
 void SkOSWindow::onSetTitle(const char title[]) {
-    if (!fUnixWindow.fDisplay) {
+    if (NULL == fUnixWindow.fDisplay) {
         return;
     }
     XTextProperty textProp;
@@ -253,16 +315,26 @@
 }
 
 void SkOSWindow::doPaint() {
-    if (!fUnixWindow.fDisplay) return;
+    if (NULL == fUnixWindow.fDisplay) {
+        return;
+    }
     // Draw the bitmap to the screen.
     const SkBitmap& bitmap = getBitmap();
     int width = bitmap.width();
     int height = bitmap.height();
 
     XImage image;
-    if (!convertBitmapToXImage(image, bitmap)) return;
+    if (!convertBitmapToXImage(image, bitmap)) {
+        return;
+    }
 
-    XPutImage(fUnixWindow.fDisplay, fUnixWindow.fWin, fUnixWindow.fGc, &image, 0, 0, 0, 0, width, height);
+    XPutImage(fUnixWindow.fDisplay,
+              fUnixWindow.fWin,
+              fUnixWindow.fGc,
+              &image,
+              0, 0,     // src x,y
+              0, 0,     // dst x,y
+              width, height);
 }
 
 bool SkOSWindow::onHandleChar(SkUnichar) {