aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
authorDerek Sollenberger <djsollen@google.com>2011-06-06 17:02:24 -0400
committerDerek Sollenberger <djsollen@google.com>2011-06-07 14:00:04 -0400
commit0b15698a8c76bb8abc1b555c1d91892669b4118f (patch)
tree08732d5fbb7484ce7e10c65c96fb56294053073a /src/utils
parent9770b0f3d2b5d512daac50c2c9561d2c073cd8d2 (diff)
downloadexternal_skia-0b15698a8c76bb8abc1b555c1d91892669b4118f.zip
external_skia-0b15698a8c76bb8abc1b555c1d91892669b4118f.tar.gz
external_skia-0b15698a8c76bb8abc1b555c1d91892669b4118f.tar.bz2
Skia Merge (revision 1510)
This CL includes bug fixes and closely mirrors the version of Skia used in Chrome M13, which is likely to be our baseline for ICS. The CL also adds source files for the SampleApp which will allow us to execute basic skia tests. The SampleApp requires the utils/views directory in order to run. Finally, we have included the PDF backend for Skia in order to experiment with using it to generate PDF files for certain applications. Note: The SampleApp and PDF code are not built as part of libskia. Change-Id: I1895ccfbd8074e25f19148cc7bd1b4af571fb307
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/SkEGLContext_none.cpp2
-rw-r--r--src/utils/mac/SkBitmap_Mac.cpp142
-rw-r--r--src/utils/mac/SkCreateCGImageRef.cpp129
-rw-r--r--src/utils/mac/SkEGLContext_mac.cpp68
-rw-r--r--src/utils/mac/SkOSWindow_Mac.cpp534
-rw-r--r--src/utils/mac/skia_mac.cpp43
-rw-r--r--src/utils/mesa/SkEGLContext_Mesa.cpp128
-rw-r--r--src/utils/unix/SkEGLContext_Unix.cpp264
-rw-r--r--src/utils/unix/SkOSWindow_Unix.cpp2
9 files changed, 1310 insertions, 2 deletions
diff --git a/src/utils/SkEGLContext_none.cpp b/src/utils/SkEGLContext_none.cpp
index 1c55c95..cb08f40 100644
--- a/src/utils/SkEGLContext_none.cpp
+++ b/src/utils/SkEGLContext_none.cpp
@@ -1,6 +1,6 @@
#include "SkEGLContext.h"
-SkEGLContext::SkEGLContext() : fContext(NULL) {
+SkEGLContext::SkEGLContext() {
}
SkEGLContext::~SkEGLContext() {
diff --git a/src/utils/mac/SkBitmap_Mac.cpp b/src/utils/mac/SkBitmap_Mac.cpp
new file mode 100644
index 0000000..06c2b27
--- /dev/null
+++ b/src/utils/mac/SkBitmap_Mac.cpp
@@ -0,0 +1,142 @@
+#include "SkBitmap.h"
+#include "SkColorPriv.h"
+#include "SkMath.h"
+
+#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#ifndef __ppc__
+ #define SWAP_16BIT
+#endif
+
+static void convertGL32_to_Mac32(uint32_t dst[], const SkBitmap& bm) {
+ memcpy(dst, bm.getPixels(), bm.getSize());
+ return;
+
+ uint32_t* stop = dst + (bm.getSize() >> 2);
+ const uint8_t* src = (const uint8_t*)bm.getPixels();
+ while (dst < stop) {
+ *dst++ = src[2] << 24 | src[1] << 16 | src[0] << 8 | src[3] << 0;
+ src += sizeof(uint32_t);
+ }
+}
+
+static void convert565_to_32(uint32_t dst[], const SkBitmap& bm) {
+ for (int y = 0; y < bm.height(); y++) {
+ const uint16_t* src = bm.getAddr16(0, y);
+ const uint16_t* stop = src + bm.width();
+ while (src < stop) {
+ unsigned c = *src++;
+ unsigned r = SkPacked16ToR32(c);
+ unsigned g = SkPacked16ToG32(c);
+ unsigned b = SkPacked16ToB32(c);
+
+ *dst++ = (b << 24) | (g << 16) | (r << 8) | 0xFF;
+ }
+ }
+}
+
+static void convert4444_to_555(uint16_t dst[], const uint16_t src[], int count)
+{
+ const uint16_t* stop = src + count;
+
+ while (src < stop)
+ {
+ unsigned c = *src++;
+
+ unsigned r = SkGetPackedR4444(c);
+ unsigned g = SkGetPackedG4444(c);
+ unsigned b = SkGetPackedB4444(c);
+ // convert to 5 bits
+ r = (r << 1) | (r >> 3);
+ g = (g << 1) | (g >> 3);
+ b = (b << 1) | (b >> 3);
+ // build the 555
+ c = (r << 10) | (g << 5) | b;
+
+#ifdef SWAP_16BIT
+ c = (c >> 8) | (c << 8);
+#endif
+ *dst++ = c;
+ }
+}
+
+#include "SkTemplates.h"
+
+static CGImageRef bitmap2imageref(const SkBitmap& bm) {
+ size_t bitsPerComp;
+ size_t bitsPerPixel;
+ CGBitmapInfo info;
+ CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+ CGDataProviderRef data = CGDataProviderCreateWithData(NULL,
+ bm.getPixels(),
+ bm.getSize(),
+ NULL);
+ SkAutoTCallVProc<CGDataProvider, CGDataProviderRelease> acp(data);
+ SkAutoTCallVProc<CGColorSpace, CGColorSpaceRelease> acp2(cs);
+
+ switch (bm.config()) {
+ case SkBitmap::kARGB_8888_Config:
+ bitsPerComp = 8;
+ bitsPerPixel = 32;
+ info = kCGImageAlphaPremultipliedLast;
+ break;
+ case SkBitmap::kARGB_4444_Config:
+ bitsPerComp = 4;
+ bitsPerPixel = 16;
+ info = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder16Little;
+ break;
+#if 0 // not supported by quartz !!!
+ case SkBitmap::kRGB_565_Config:
+ bitsPerComp = 5;
+ bitsPerPixel = 16;
+ info = kCGImageAlphaNone | kCGBitmapByteOrder16Little;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ return CGImageCreate(bm.width(), bm.height(), bitsPerComp, bitsPerPixel,
+ bm.rowBytes(), cs, info, data,
+ NULL, false, kCGRenderingIntentDefault);
+}
+
+void SkBitmap::drawToPort(WindowRef wind, CGContextRef cg) const {
+ if (fPixels == NULL || fWidth == 0 || fHeight == 0) {
+ return;
+ }
+
+ bool useQD = false;
+ if (NULL == cg) {
+ SetPortWindowPort(wind);
+ QDBeginCGContext(GetWindowPort(wind), &cg);
+ useQD = true;
+ }
+
+ SkBitmap bm;
+ if (this->config() == kRGB_565_Config) {
+ this->copyTo(&bm, kARGB_8888_Config);
+ } else {
+ bm = *this;
+ }
+ bm.lockPixels();
+
+ CGImageRef image = bitmap2imageref(bm);
+ if (image) {
+ CGRect rect;
+ rect.origin.x = rect.origin.y = 0;
+ rect.size.width = bm.width();
+ rect.size.height = bm.height();
+
+ CGContextDrawImage(cg, rect, image);
+ CGImageRelease(image);
+ }
+
+ if (useQD) {
+ QDEndCGContext(GetWindowPort(wind), &cg);
+ }
+}
+
+#endif
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
new file mode 100644
index 0000000..f4bda45
--- /dev/null
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -0,0 +1,129 @@
+#include "SkCGUtils.h"
+#include "SkBitmap.h"
+#include "SkColorPriv.h"
+
+static void SkBitmap_ReleaseInfo(void* info, const void* pixelData, size_t size) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(info);
+ delete bitmap;
+}
+
+#define HAS_ARGB_SHIFTS(a, r, g, b) \
+ (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
+ && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
+
+static SkBitmap* prepareForImageRef(const SkBitmap& bm,
+ size_t* bitsPerComponent,
+ CGBitmapInfo* info) {
+ bool upscaleTo32 = false;
+
+ switch (bm.config()) {
+ case SkBitmap::kRGB_565_Config:
+ upscaleTo32 = true;
+ // fall through
+ case SkBitmap::kARGB_8888_Config:
+ *bitsPerComponent = 8;
+#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \
+ || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8)
+ *info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
+#elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \
+ || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
+ // Matches the CGBitmapInfo that Apple recommends for best
+ // performance, used by google chrome.
+ *info = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;
+#else
+// ...add more formats as required...
+#warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
+ This will probably not work.
+ // Legacy behavior. Perhaps turn this into an error at some
+ // point.
+ *info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
+#endif
+ break;
+#if 0
+ case SkBitmap::kRGB_565_Config:
+ // doesn't see quite right. Are they thinking 1555?
+ *bitsPerComponent = 5;
+ *info = kCGBitmapByteOrder16Little;
+ break;
+#endif
+ case SkBitmap::kARGB_4444_Config:
+ *bitsPerComponent = 4;
+ *info = kCGBitmapByteOrder16Little | kCGImageAlphaPremultipliedLast;
+ break;
+ default:
+ return NULL;
+ }
+
+ SkBitmap* copy;
+ if (upscaleTo32) {
+ copy = new SkBitmap;
+ // here we make a ceep copy of the pixels, since CG won't take our
+ // 565 directly
+ bm.copyTo(copy, SkBitmap::kARGB_8888_Config);
+ } else {
+ copy = new SkBitmap(bm);
+ }
+ return copy;
+}
+
+#undef HAS_ARGB_SHIFTS
+
+CGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,
+ CGColorSpaceRef colorSpace) {
+ size_t bitsPerComponent SK_INIT_TO_AVOID_WARNING;
+ CGBitmapInfo info SK_INIT_TO_AVOID_WARNING;
+
+ SkBitmap* bitmap = prepareForImageRef(bm, &bitsPerComponent, &info);
+ if (NULL == bitmap) {
+ return NULL;
+ }
+
+ const int w = bitmap->width();
+ const int h = bitmap->height();
+ const size_t s = bitmap->getSize();
+
+ // our provider "owns" the bitmap*, and will take care of deleting it
+ // we initially lock it, so we can access the pixels. The bitmap will be deleted in the release
+ // proc, which will in turn unlock the pixels
+ bitmap->lockPixels();
+ CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
+ SkBitmap_ReleaseInfo);
+
+ bool releaseColorSpace = false;
+ if (NULL == colorSpace) {
+ colorSpace = CGColorSpaceCreateDeviceRGB();
+ releaseColorSpace = true;
+ }
+
+ CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
+ bitmap->bytesPerPixel() * 8,
+ bitmap->rowBytes(), colorSpace, info, dataRef,
+ NULL, false, kCGRenderingIntentDefault);
+
+ if (releaseColorSpace) {
+ CGColorSpaceRelease(colorSpace);
+ }
+ CGDataProviderRelease(dataRef);
+ return ref;
+}
+
+void SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
+ CGImageRef img = SkCreateCGImageRef(bm);
+
+ if (img) {
+ CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
+
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, x, r.size.height + y);
+ CGContextScaleCTM(cg, 1, -1);
+
+ CGContextDrawImage(cg, r, img);
+
+ CGContextRestoreGState(cg);
+
+ CGImageRelease(img);
+ }
+}
+
+
+
diff --git a/src/utils/mac/SkEGLContext_mac.cpp b/src/utils/mac/SkEGLContext_mac.cpp
new file mode 100644
index 0000000..e601f35
--- /dev/null
+++ b/src/utils/mac/SkEGLContext_mac.cpp
@@ -0,0 +1,68 @@
+#include "SkEGLContext.h"
+//#include "SkTypes.h"
+#include <AGL/agl.h>
+
+SkEGLContext::SkEGLContext() : context(NULL) {
+}
+
+SkEGLContext::~SkEGLContext() {
+ if (this->context) {
+ aglDestroyContext(this->context);
+ }
+}
+
+bool SkEGLContext::init(int width, int height) {
+ GLint major, minor;
+ AGLContext ctx;
+
+ aglGetVersion(&major, &minor);
+ //SkDebugf("---- agl version %d %d\n", major, minor);
+
+ const GLint pixelAttrs[] = {
+ AGL_RGBA,
+ AGL_STENCIL_SIZE, 8,
+/*
+ AGL_SAMPLE_BUFFERS_ARB, 1,
+ AGL_MULTISAMPLE,
+ AGL_SAMPLES_ARB, 2,
+*/
+ AGL_ACCELERATED,
+ AGL_NONE
+ };
+ AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs);
+ //AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
+ //SkDebugf("----- agl format %p\n", format);
+ ctx = aglCreateContext(format, NULL);
+ //SkDebugf("----- agl context %p\n", ctx);
+ aglDestroyPixelFormat(format);
+
+/*
+ static const GLint interval = 1;
+ aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval);
+*/
+
+ aglSetCurrentContext(ctx);
+ this->context = ctx;
+
+ // Now create our FBO render target
+
+ GLuint fboID;
+ GLuint cbID;
+ GLuint dsID;
+ glGenFramebuffersEXT(1, &fboID);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
+ glGenRenderbuffers(1, &cbID);
+ glBindRenderbuffer(GL_RENDERBUFFER, cbID);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cbID);
+ glGenRenderbuffers(1, &dsID);
+ glBindRenderbuffer(GL_RENDERBUFFER, dsID);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, dsID);
+ glViewport(0, 0, width, height);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ return GL_FRAMEBUFFER_COMPLETE == status;
+}
diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp
new file mode 100644
index 0000000..f1a2926
--- /dev/null
+++ b/src/utils/mac/SkOSWindow_Mac.cpp
@@ -0,0 +1,534 @@
+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
+
+#include <AGL/agl.h>
+
+#include <Carbon/Carbon.h>
+#include "SkCGUtils.h"
+
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+
+#include "SkGraphics.h"
+#include <new.h>
+
+static void (*gPrevNewHandler)();
+
+extern "C" {
+ static void sk_new_handler()
+ {
+ if (SkGraphics::SetFontCacheUsed(0))
+ return;
+ if (gPrevNewHandler)
+ gPrevNewHandler();
+ else
+ sk_throw();
+ }
+}
+
+static SkOSWindow* gCurrOSWin;
+static EventTargetRef gEventTarget;
+static EventQueueRef gCurrEventQ;
+
+static OSStatus MyDrawEventHandler(EventHandlerCallRef myHandler,
+ EventRef event, void *userData) {
+ // NOTE: GState is save/restored by the HIView system doing the callback,
+ // so the draw handler doesn't need to do it
+
+ OSStatus status = noErr;
+ CGContextRef context;
+ HIRect bounds;
+
+ // Get the CGContextRef
+ status = GetEventParameter (event, kEventParamCGContextRef,
+ typeCGContextRef, NULL,
+ sizeof (CGContextRef),
+ NULL,
+ &context);
+
+ if (status != noErr) {
+ SkDebugf("Got error %d getting the context!\n", status);
+ return status;
+ }
+
+ // Get the bounding rectangle
+ HIViewGetBounds ((HIViewRef) userData, &bounds);
+
+ gCurrOSWin->doPaint(context);
+ return status;
+}
+
+#define SK_MacEventClass FOUR_CHAR_CODE('SKec')
+#define SK_MacEventKind FOUR_CHAR_CODE('SKek')
+#define SK_MacEventParamName FOUR_CHAR_CODE('SKev')
+#define SK_MacEventSinkIDParamName FOUR_CHAR_CODE('SKes')
+
+static void set_bindingside(HISideBinding* side, HIViewRef parent, HIBindingKind kind) {
+ side->toView = parent;
+ side->kind = kind;
+ side->offset = 0;
+}
+
+static void set_axisscale(HIAxisScale* axis, HIViewRef parent) {
+ axis->toView = parent;
+ axis->kind = kHILayoutScaleAbsolute;
+ axis->ratio = 1;
+}
+
+static void set_axisposition(HIAxisPosition* pos, HIViewRef parent, HIPositionKind kind) {
+ pos->toView = parent;
+ pos->kind = kind;
+ pos->offset = 0;
+}
+
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), fAGLCtx(NULL)
+{
+ OSStatus result;
+ WindowRef wr = (WindowRef)hWnd;
+
+ HIViewRef imageView, parent;
+ HIViewRef rootView = HIViewGetRoot(wr);
+ HIViewFindByID(rootView, kHIViewWindowContentID, &parent);
+ result = HIImageViewCreate(NULL, &imageView);
+ SkASSERT(result == noErr);
+
+ result = HIViewAddSubview(parent, imageView);
+ SkASSERT(result == noErr);
+
+ fHVIEW = imageView;
+
+ HIViewSetVisible(imageView, true);
+ HIViewPlaceInSuperviewAt(imageView, 0, 0);
+
+ if (true) {
+ HILayoutInfo layout;
+ layout.version = kHILayoutInfoVersionZero;
+ set_bindingside(&layout.binding.left, parent, kHILayoutBindLeft);
+ set_bindingside(&layout.binding.top, parent, kHILayoutBindTop);
+ set_bindingside(&layout.binding.right, parent, kHILayoutBindRight);
+ set_bindingside(&layout.binding.bottom, parent, kHILayoutBindBottom);
+ set_axisscale(&layout.scale.x, parent);
+ set_axisscale(&layout.scale.y, parent);
+ set_axisposition(&layout.position.x, parent, kHILayoutPositionLeft);
+ set_axisposition(&layout.position.y, rootView, kHILayoutPositionTop);
+ HIViewSetLayoutInfo(imageView, &layout);
+ }
+
+ HIImageViewSetOpaque(imageView, true);
+ HIImageViewSetScaleToFit(imageView, false);
+
+ static const EventTypeSpec gTypes[] = {
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
+ { kEventClassWindow, kEventWindowBoundsChanged },
+// { kEventClassWindow, kEventWindowDrawContent },
+ { SK_MacEventClass, SK_MacEventKind }
+ };
+
+ EventHandlerUPP handlerUPP = NewEventHandlerUPP(SkOSWindow::EventHandler);
+ int count = SK_ARRAY_COUNT(gTypes);
+
+ result = InstallEventHandler(GetWindowEventTarget(wr), handlerUPP,
+ count, gTypes, this, nil);
+ SkASSERT(result == noErr);
+
+ gCurrOSWin = this;
+ gCurrEventQ = GetCurrentEventQueue();
+ gEventTarget = GetWindowEventTarget(wr);
+
+ static bool gOnce = true;
+ if (gOnce) {
+ gOnce = false;
+ gPrevNewHandler = set_new_handler(sk_new_handler);
+ }
+}
+
+void SkOSWindow::doPaint(void* ctx)
+{
+#if 0
+ this->update(NULL);
+
+ const SkBitmap& bm = this->getBitmap();
+ CGImageRef img = SkCreateCGImageRef(bm);
+
+ if (img) {
+ CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
+
+ CGContextRef cg = reinterpret_cast<CGContextRef>(ctx);
+
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, 0, r.size.height);
+ CGContextScaleCTM(cg, 1, -1);
+
+ CGContextDrawImage(cg, r, img);
+
+ CGContextRestoreGState(cg);
+
+ CGImageRelease(img);
+ }
+#endif
+}
+
+void SkOSWindow::updateSize()
+{
+ Rect r;
+
+ GetWindowBounds((WindowRef)fHWND, kWindowContentRgn, &r);
+ this->resize(r.right - r.left, r.bottom - r.top);
+
+#if 0
+ HIRect frame;
+ HIViewRef imageView = (HIViewRef)getHVIEW();
+ HIViewRef parent = HIViewGetSuperview(imageView);
+
+ HIViewGetBounds(imageView, &frame);
+ SkDebugf("------ %d bounds %g %g %g %g\n", r.right - r.left,
+ frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+#endif
+}
+
+void SkOSWindow::onHandleInval(const SkIRect& r)
+{
+ SkEvent* evt = new SkEvent("inval-imageview");
+ evt->post(this->getSinkID());
+}
+
+bool SkOSWindow::onEvent(const SkEvent& evt) {
+ if (evt.isType("inval-imageview")) {
+ this->update(NULL);
+
+ const SkBitmap& bm = this->getBitmap();
+
+ CGImageRef img = SkCreateCGImageRef(bm);
+ HIImageViewSetImage((HIViewRef)getHVIEW(), img);
+ CGImageRelease(img);
+ return true;
+ }
+ return INHERITED::onEvent(evt);
+}
+
+void SkOSWindow::onSetTitle(const char title[])
+{
+ CFStringRef str = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
+ SetWindowTitleWithCFString((WindowRef)fHWND, str);
+ CFRelease(str);
+}
+
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
+{
+}
+
+static void getparam(EventRef inEvent, OSType name, OSType type, UInt32 size, void* data)
+{
+ EventParamType actualType;
+ UInt32 actualSize;
+ OSStatus status;
+
+ status = GetEventParameter(inEvent, name, type, &actualType, size, &actualSize, data);
+ SkASSERT(status == noErr);
+ SkASSERT(actualType == type);
+ SkASSERT(actualSize == size);
+}
+
+enum {
+ SK_MacReturnKey = 36,
+ SK_MacDeleteKey = 51,
+ SK_MacEndKey = 119,
+ SK_MacLeftKey = 123,
+ SK_MacRightKey = 124,
+ SK_MacDownKey = 125,
+ SK_MacUpKey = 126,
+
+ SK_Mac0Key = 0x52,
+ SK_Mac1Key = 0x53,
+ SK_Mac2Key = 0x54,
+ SK_Mac3Key = 0x55,
+ SK_Mac4Key = 0x56,
+ SK_Mac5Key = 0x57,
+ SK_Mac6Key = 0x58,
+ SK_Mac7Key = 0x59,
+ SK_Mac8Key = 0x5b,
+ SK_Mac9Key = 0x5c
+};
+
+static SkKey raw2key(UInt32 raw)
+{
+ static const struct {
+ UInt32 fRaw;
+ SkKey fKey;
+ } gKeys[] = {
+ { SK_MacUpKey, kUp_SkKey },
+ { SK_MacDownKey, kDown_SkKey },
+ { SK_MacLeftKey, kLeft_SkKey },
+ { SK_MacRightKey, kRight_SkKey },
+ { SK_MacReturnKey, kOK_SkKey },
+ { SK_MacDeleteKey, kBack_SkKey },
+ { SK_MacEndKey, kEnd_SkKey },
+ { SK_Mac0Key, k0_SkKey },
+ { SK_Mac1Key, k1_SkKey },
+ { SK_Mac2Key, k2_SkKey },
+ { SK_Mac3Key, k3_SkKey },
+ { SK_Mac4Key, k4_SkKey },
+ { SK_Mac5Key, k5_SkKey },
+ { SK_Mac6Key, k6_SkKey },
+ { SK_Mac7Key, k7_SkKey },
+ { SK_Mac8Key, k8_SkKey },
+ { SK_Mac9Key, k9_SkKey }
+ };
+
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
+ if (gKeys[i].fRaw == raw)
+ return gKeys[i].fKey;
+ return kNONE_SkKey;
+}
+
+static void post_skmacevent()
+{
+ EventRef ref;
+ OSStatus status = CreateEvent(nil, SK_MacEventClass, SK_MacEventKind, 0, 0, &ref);
+ SkASSERT(status == noErr);
+
+#if 0
+ status = SetEventParameter(ref, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt);
+ SkASSERT(status == noErr);
+ status = SetEventParameter(ref, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID);
+ SkASSERT(status == noErr);
+#endif
+
+ EventTargetRef target = gEventTarget;
+ SetEventParameter(ref, kEventParamPostTarget, typeEventTargetRef, sizeof(target), &target);
+ SkASSERT(status == noErr);
+
+ status = PostEventToQueue(gCurrEventQ, ref, kEventPriorityStandard);
+ SkASSERT(status == noErr);
+
+ ReleaseEvent(ref);
+}
+
+pascal OSStatus SkOSWindow::EventHandler( EventHandlerCallRef inHandler, EventRef inEvent, void* userData )
+{
+ SkOSWindow* win = (SkOSWindow*)userData;
+ OSStatus result = eventNotHandledErr;
+ UInt32 wClass = GetEventClass(inEvent);
+ UInt32 wKind = GetEventKind(inEvent);
+
+ gCurrOSWin = win; // will need to be in TLS. Set this so PostEvent will work
+
+ switch (wClass) {
+ case kEventClassMouse: {
+ Point pt;
+ getparam(inEvent, kEventParamMouseLocation, typeQDPoint, sizeof(pt), &pt);
+ SetPortWindowPort((WindowRef)win->getHWND());
+ GlobalToLocal(&pt);
+
+ switch (wKind) {
+ case kEventMouseDown:
+ if (win->handleClick(pt.h, pt.v, Click::kDown_State)) {
+ result = noErr;
+ }
+ break;
+ case kEventMouseMoved:
+ // fall through
+ case kEventMouseDragged:
+ (void)win->handleClick(pt.h, pt.v, Click::kMoved_State);
+ // result = noErr;
+ break;
+ case kEventMouseUp:
+ (void)win->handleClick(pt.h, pt.v, Click::kUp_State);
+ // result = noErr;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case kEventClassKeyboard:
+ if (wKind == kEventRawKeyDown) {
+ UInt32 raw;
+ getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw);
+ SkKey key = raw2key(raw);
+ if (key != kNONE_SkKey)
+ (void)win->handleKey(key);
+ } else if (wKind == kEventRawKeyUp) {
+ UInt32 raw;
+ getparam(inEvent, kEventParamKeyCode, typeUInt32, sizeof(raw), &raw);
+ SkKey key = raw2key(raw);
+ if (key != kNONE_SkKey)
+ (void)win->handleKeyUp(key);
+ }
+ break;
+ case kEventClassTextInput:
+ if (wKind == kEventTextInputUnicodeForKeyEvent) {
+ UInt16 uni;
+ getparam(inEvent, kEventParamTextInputSendText, typeUnicodeText, sizeof(uni), &uni);
+ win->handleChar(uni);
+ }
+ break;
+ case kEventClassWindow:
+ switch (wKind) {
+ case kEventWindowBoundsChanged:
+ win->updateSize();
+ break;
+ case kEventWindowDrawContent: {
+ CGContextRef cg;
+ result = GetEventParameter(inEvent,
+ kEventParamCGContextRef,
+ typeCGContextRef,
+ NULL,
+ sizeof (CGContextRef),
+ NULL,
+ &cg);
+ if (result != 0) {
+ cg = NULL;
+ }
+ win->doPaint(cg);
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ case SK_MacEventClass: {
+ SkASSERT(wKind == SK_MacEventKind);
+ if (SkEvent::ProcessEvent()) {
+ post_skmacevent();
+ }
+ #if 0
+ SkEvent* evt;
+ SkEventSinkID sinkID;
+ getparam(inEvent, SK_MacEventParamName, SK_MacEventParamName, sizeof(evt), &evt);
+ getparam(inEvent, SK_MacEventSinkIDParamName, SK_MacEventSinkIDParamName, sizeof(sinkID), &sinkID);
+ #endif
+ result = noErr;
+ break;
+ }
+ default:
+ break;
+ }
+ if (result == eventNotHandledErr) {
+ result = CallNextEventHandler(inHandler, inEvent);
+ }
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void SkEvent::SignalNonEmptyQueue()
+{
+ post_skmacevent();
+// SkDebugf("signal nonempty\n");
+}
+
+static TMTask gTMTaskRec;
+static TMTask* gTMTaskPtr;
+
+static void sk_timer_proc(TMTask* rec)
+{
+ SkEvent::ServiceQueueTimer();
+// SkDebugf("timer task fired\n");
+}
+
+void SkEvent::SignalQueueTimer(SkMSec delay)
+{
+ if (gTMTaskPtr)
+ {
+ RemoveTimeTask((QElem*)gTMTaskPtr);
+ DisposeTimerUPP(gTMTaskPtr->tmAddr);
+ gTMTaskPtr = nil;
+ }
+ if (delay)
+ {
+ gTMTaskPtr = &gTMTaskRec;
+ memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));
+ gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);
+ OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);
+// SkDebugf("installtimetask of %d returned %d\n", delay, err);
+ PrimeTimeTask((QElem*)gTMTaskPtr, delay);
+ }
+}
+
+#define USE_MSAA 0
+
+AGLContext create_gl(WindowRef wref)
+{
+ GLint major, minor;
+ AGLContext ctx;
+
+ aglGetVersion(&major, &minor);
+ SkDebugf("---- agl version %d %d\n", major, minor);
+
+ const GLint pixelAttrs[] = {
+ AGL_RGBA,
+ AGL_STENCIL_SIZE, 8,
+#if USE_MSAA
+ AGL_SAMPLE_BUFFERS_ARB, 1,
+ AGL_MULTISAMPLE,
+ AGL_SAMPLES_ARB, 8,
+#endif
+ AGL_ACCELERATED,
+ AGL_DOUBLEBUFFER,
+ AGL_NONE
+ };
+ AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs);
+ //AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
+ SkDebugf("----- agl format %p\n", format);
+ ctx = aglCreateContext(format, NULL);
+ SkDebugf("----- agl context %p\n", ctx);
+ aglDestroyPixelFormat(format);
+
+ static const GLint interval = 1;
+ aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval);
+ aglSetCurrentContext(ctx);
+ return ctx;
+}
+
+bool SkOSWindow::attachGL()
+{
+ if (NULL == fAGLCtx) {
+ fAGLCtx = create_gl((WindowRef)fHWND);
+ if (NULL == fAGLCtx) {
+ return false;
+ }
+ }
+
+ GLboolean success = true;
+
+ int width, height;
+
+ success = aglSetWindowRef((AGLContext)fAGLCtx, (WindowRef)fHWND);
+ width = this->width();
+ height = this->height();
+
+ GLenum err = aglGetError();
+ if (err) {
+ SkDebugf("---- aglSetWindowRef %d %d %s [%d %d]\n", success, err,
+ aglErrorString(err), width, height);
+ }
+
+ if (success) {
+ glViewport(0, 0, width, height);
+ glClearColor(0, 0, 0, 0);
+ glClearStencil(0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+ return success;
+}
+
+void SkOSWindow::detachGL() {
+ aglSetWindowRef((AGLContext)fAGLCtx, NULL);
+}
+
+void SkOSWindow::presentGL() {
+ aglSwapBuffers((AGLContext)fAGLCtx);
+}
+
+#endif
+
diff --git a/src/utils/mac/skia_mac.cpp b/src/utils/mac/skia_mac.cpp
new file mode 100644
index 0000000..a1345cf
--- /dev/null
+++ b/src/utils/mac/skia_mac.cpp
@@ -0,0 +1,43 @@
+#include <Carbon/Carbon.h>
+#include "SkApplication.h"
+#include "SkWindow.h"
+
+int main(int argc, char* argv[])
+{
+ WindowRef window;
+ OSStatus err = noErr;
+
+ Rect bounds = {100, 100, 500, 500};
+ WindowAttributes attrs = kWindowStandardHandlerAttribute |
+ kWindowLiveResizeAttribute |
+ kWindowInWindowMenuAttribute |
+ kWindowCompositingAttribute |
+ kWindowAsyncDragAttribute |
+ kWindowFullZoomAttribute |
+ kWindowFrameworkScaledAttribute;
+ //kWindowDoesNotCycleAttribute;
+ CreateNewWindow(kDocumentWindowClass, attrs, &bounds, &window);
+
+ MenuRef menu;
+ CreateNewMenu(0, 0, &menu);
+
+ // if we get here, we can start our normal Skia sequence
+ {
+ application_init();
+ (void)create_sk_window(window);
+ SizeWindow(window, 640, 480, false);
+ }
+
+ // The window was created hidden so show it.
+ ShowWindow( window );
+
+ // Call the event loop
+ RunApplicationEventLoop();
+
+ application_term();
+
+CantCreateWindow:
+CantGetNibRef:
+ return err;
+}
+
diff --git a/src/utils/mesa/SkEGLContext_Mesa.cpp b/src/utils/mesa/SkEGLContext_Mesa.cpp
new file mode 100644
index 0000000..ed1b7cd
--- /dev/null
+++ b/src/utils/mesa/SkEGLContext_Mesa.cpp
@@ -0,0 +1,128 @@
+#include "SkEGLContext.h"
+#include "SkTypes.h"
+
+#include "GL/osmesa.h"
+#include "GL/glu.h"
+
+#define SK_GL_DECL_PROC(T, F) T F ## _func = NULL;
+#define SK_GL_GET_PROC(T, F) F ## _func = (T)OSMesaGetProcAddress(#F);
+#define SK_GL_GET_EXT_PROC(T, F) F ## _func = (T)OSMesaGetProcAddress(#F "EXT");
+
+SkEGLContext::SkEGLContext() : context(NULL), image(NULL) {
+}
+
+SkEGLContext::~SkEGLContext() {
+ if (this->image)
+ free(this->image);
+
+ if (this->context)
+ OSMesaDestroyContext(this->context);
+}
+
+#if SK_B32_SHIFT < SK_G32_SHIFT &&\
+ SK_G32_SHIFT < SK_R32_SHIFT &&\
+ SK_R32_SHIFT < SK_A32_SHIFT
+ #define SK_OSMESA_COLOR_ORDER OSMESA_BGRA
+#elif SK_R32_SHIFT < SK_G32_SHIFT &&\
+ SK_G32_SHIFT < SK_B32_SHIFT &&\
+ SK_B32_SHIFT < SK_A32_SHIFT
+ #define SK_OSMESA_COLOR_ORDER OSMESA_RGBA
+#elif SK_A32_SHIFT < SK_R32_SHIFT && \
+ SK_R32_SHIFT < SK_G32_SHIFT && \
+ SK_G32_SHIFT < SK_B32_SHIFT
+ #define SK_OSMESA_COLOR_ORDER OSMESA_ARGB
+#else
+ //Color order (rgba) SK_R32_SHIFT SK_G32_SHIFT SK_B32_SHIFT SK_A32_SHIFT
+ #define SK_OSMESA_COLOR_ORDER OSMESA_RGBA
+#endif
+
+bool SkEGLContext::init(const int width, const int height) {
+ /* Create an RGBA-mode context */
+#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
+ /* specify Z, stencil, accum sizes */
+ OSMesaContext ctx = OSMesaCreateContextExt(SK_OSMESA_COLOR_ORDER, 16, 0, 0, NULL);
+#else
+ OSMesaContext ctx = OSMesaCreateContext(SK_OSMESA_COLOR_ORDER, NULL);
+#endif
+ if (!ctx) {
+ SkDebugf("OSMesaCreateContext failed!\n");
+ return false;
+ }
+ this->context = ctx;
+
+ // Allocate the image buffer
+ GLfloat *buffer = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
+ if (!buffer) {
+ SkDebugf("Alloc image buffer failed!\n");
+ return false;
+ }
+ this->image = buffer;
+
+ // Bind the buffer to the context and make it current
+ if (!OSMesaMakeCurrent(ctx, buffer, GL_FLOAT, width, height)) {
+ SkDebugf("OSMesaMakeCurrent failed!\n");
+ return false;
+ }
+
+ //Setup the framebuffers
+ SK_GL_DECL_PROC(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffers)
+ SK_GL_DECL_PROC(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebuffer)
+ SK_GL_DECL_PROC(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers)
+ SK_GL_DECL_PROC(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer)
+ SK_GL_DECL_PROC(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage)
+ SK_GL_DECL_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer)
+ SK_GL_DECL_PROC(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatus)
+
+ const GLubyte* glExts = glGetString(GL_EXTENSIONS);
+ if (gluCheckExtension(
+ reinterpret_cast<const GLubyte*>("GL_ARB_framebuffer_object")
+ , glExts))
+ {
+ SK_GL_GET_PROC(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffers)
+ SK_GL_GET_PROC(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebuffer)
+ SK_GL_GET_PROC(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers)
+ SK_GL_GET_PROC(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer)
+ SK_GL_GET_PROC(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage)
+ SK_GL_GET_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer)
+ SK_GL_GET_PROC(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatus)
+
+ //osmesa on mac currently only supports EXT
+ } else if (gluCheckExtension(
+ reinterpret_cast<const GLubyte*>("GL_EXT_framebuffer_object")
+ , glExts))
+ {
+ SK_GL_GET_EXT_PROC(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffers)
+ SK_GL_GET_EXT_PROC(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebuffer)
+ SK_GL_GET_EXT_PROC(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers)
+ SK_GL_GET_EXT_PROC(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer)
+ SK_GL_GET_EXT_PROC(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage)
+ SK_GL_GET_EXT_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer)
+ SK_GL_GET_EXT_PROC(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatus)
+ } else {
+ SkDebugf("GL_ARB_framebuffer_object not found.\n");
+ return false;
+ }
+
+ GLuint fboID;
+ GLuint cbID;
+ GLuint dsID;
+ glGenFramebuffers_func(1, &fboID);
+ glBindFramebuffer_func(GL_FRAMEBUFFER, fboID);
+
+ glGenRenderbuffers_func(1, &cbID);
+ glBindRenderbuffer_func(GL_RENDERBUFFER, cbID);
+ glRenderbufferStorage_func(GL_RENDERBUFFER, OSMESA_RGBA, width, height);
+ glFramebufferRenderbuffer_func(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cbID);
+
+ glGenRenderbuffers_func(1, &dsID);
+ glBindRenderbuffer_func(GL_RENDERBUFFER_EXT, dsID);
+ glRenderbufferStorage_func(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
+ glFramebufferRenderbuffer_func(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, dsID);
+
+ glViewport(0, 0, width, height);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ GLenum status = glCheckFramebufferStatus_func(GL_FRAMEBUFFER);
+ return GL_FRAMEBUFFER_COMPLETE == status;
+}
diff --git a/src/utils/unix/SkEGLContext_Unix.cpp b/src/utils/unix/SkEGLContext_Unix.cpp
new file mode 100644
index 0000000..7921b8a
--- /dev/null
+++ b/src/utils/unix/SkEGLContext_Unix.cpp
@@ -0,0 +1,264 @@
+#include "SkEGLContext.h"
+#include "SkTypes.h"
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+
+#define SK_GL_GET_PROC(T, F) T F = NULL; \
+ F = (T) glXGetProcAddressARB(reinterpret_cast<const GLubyte*>(#F));
+
+static bool ctxErrorOccurred = false;
+static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) {
+ ctxErrorOccurred = true;
+ return 0;
+}
+
+SkEGLContext::SkEGLContext() : context(NULL), display(NULL), pixmap(0), glxPixmap(0) {
+}
+
+SkEGLContext::~SkEGLContext() {
+ if (this->display) {
+ glXMakeCurrent(this->display, 0, 0);
+
+ if (this->context)
+ glXDestroyContext(this->display, this->context);
+
+ if (this->glxPixmap)
+ glXDestroyGLXPixmap(this->display, this->glxPixmap);
+
+ if (this->pixmap)
+ XFreePixmap(this->display, this->pixmap);
+
+ XCloseDisplay(this->display);
+ }
+}
+
+bool SkEGLContext::init(const int width, const int height) {
+ Display *display = XOpenDisplay(0);
+ this->display = display;
+
+ if (!display) {
+ SkDebugf("Failed to open X display.\n");
+ return false;
+ }
+
+ // Get a matching FB config
+ static int visual_attribs[] = {
+ GLX_X_RENDERABLE , True,
+ GLX_DRAWABLE_TYPE , GLX_PIXMAP_BIT,
+ GLX_RENDER_TYPE , GLX_RGBA_BIT,
+ GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
+ GLX_RED_SIZE , 8,
+ GLX_GREEN_SIZE , 8,
+ GLX_BLUE_SIZE , 8,
+ GLX_ALPHA_SIZE , 8,
+ GLX_DEPTH_SIZE , 24,
+ GLX_STENCIL_SIZE , 8,
+ GLX_DOUBLEBUFFER , True,
+ //GLX_SAMPLE_BUFFERS , 1,
+ //GLX_SAMPLES , 4,
+ None
+ };
+
+ int glx_major, glx_minor;
+
+ // FBConfigs were added in GLX version 1.3.
+ if (!glXQueryVersion( display, &glx_major, &glx_minor) ||
+ ( (glx_major == 1) && (glx_minor < 3) ) || (glx_major < 1))
+ {
+ SkDebugf("Invalid GLX version.");
+ return false;
+ }
+
+ //SkDebugf("Getting matching framebuffer configs.\n");
+ int fbcount;
+ GLXFBConfig *fbc = glXChooseFBConfig(display, DefaultScreen(display),
+ visual_attribs, &fbcount);
+ if (!fbc) {
+ SkDebugf("Failed to retrieve a framebuffer config.\n");
+ return false;
+ }
+ //SkDebugf("Found %d matching FB configs.\n", fbcount);
+
+ // Pick the FB config/visual with the most samples per pixel
+ //SkDebugf("Getting XVisualInfos.\n");
+ int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
+
+ int i;
+ for (i = 0; i < fbcount; ++i) {
+ XVisualInfo *vi = glXGetVisualFromFBConfig(display, fbc[i]);
+ if (vi) {
+ int samp_buf, samples;
+ glXGetFBConfigAttrib(display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
+ glXGetFBConfigAttrib(display, fbc[i], GLX_SAMPLES, &samples);
+
+ //SkDebugf(" Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
+ // " SAMPLES = %d\n",
+ // i, (unsigned int)vi->visualid, samp_buf, samples);
+
+ if (best_fbc < 0 || (samp_buf && samples > best_num_samp))
+ best_fbc = i, best_num_samp = samples;
+ if (worst_fbc < 0 || !samp_buf || samples < worst_num_samp)
+ worst_fbc = i, worst_num_samp = samples;
+ }
+ XFree(vi);
+ }
+
+ GLXFBConfig bestFbc = fbc[best_fbc];
+
+ // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
+ XFree(fbc);
+
+ // Get a visual
+ XVisualInfo *vi = glXGetVisualFromFBConfig(display, bestFbc);
+ //SkDebugf("Chosen visual ID = 0x%x\n", (unsigned int)vi->visualid);
+
+ Pixmap pixmap = XCreatePixmap(
+ display, RootWindow(display, vi->screen), width, height, vi->depth
+ );
+
+ this->pixmap = pixmap;
+ if (!pixmap) {
+ SkDebugf("Failed to create pixmap.\n");
+ return false;
+ }
+
+ GLXPixmap glxPixmap = glXCreateGLXPixmap(display, vi, pixmap);
+ this->glxPixmap = glxPixmap;
+
+ // Done with the visual info data
+ XFree(vi);
+
+ // Create the context
+ GLXContext ctx = 0;
+
+ // Install an X error handler so the application won't exit if GL 3.0
+ // context allocation fails.
+ //
+ // Note this error handler is global.
+ // All display connections in all threads of a process use the same
+ // error handler, so be sure to guard against other threads issuing
+ // X commands while this code is running.
+ ctxErrorOccurred = false;
+ int (*oldHandler)(Display*, XErrorEvent*) =
+ XSetErrorHandler(&ctxErrorHandler);
+
+ // Get the default screen's GLX extension list
+ const char *glxExts = glXQueryExtensionsString(
+ display, DefaultScreen(display)
+ );
+ // Check for the GLX_ARB_create_context extension string and the function.
+ // If either is not present, use GLX 1.3 context creation method.
+ if (!gluCheckExtension(
+ reinterpret_cast<const GLubyte*>("GLX_ARB_create_context")
+ , reinterpret_cast<const GLubyte*>(glxExts)))
+ {
+ //SkDebugf("GLX_ARB_create_context not found."
+ // " Using old-style GLX context.\n");
+ ctx = glXCreateNewContext(display, bestFbc, GLX_RGBA_TYPE, 0, True);
+
+ } else {
+ //SkDebugf("Creating context.\n");
+
+ SK_GL_GET_PROC(PFNGLXCREATECONTEXTATTRIBSARBPROC, glXCreateContextAttribsARB)
+ int context_attribs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+ //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ None
+ };
+ ctx = glXCreateContextAttribsARB(
+ display, bestFbc, 0, True, context_attribs
+ );
+
+ // Sync to ensure any errors generated are processed.
+ XSync(display, False);
+ if (!ctxErrorOccurred && ctx) {
+ //SkDebugf( "Created GL 3.0 context.\n" );
+ } else {
+ // Couldn't create GL 3.0 context.
+ // Fall back to old-style 2.x context.
+ // When a context version below 3.0 is requested,
+ // implementations will return the newest context version compatible
+ // with OpenGL versions less than version 3.0.
+
+ // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
+ context_attribs[1] = 1;
+ // GLX_CONTEXT_MINOR_VERSION_ARB = 0
+ context_attribs[3] = 0;
+
+ ctxErrorOccurred = false;
+
+ //SkDebugf("Failed to create GL 3.0 context."
+ // " Using old-style GLX context.\n");
+ ctx = glXCreateContextAttribsARB(
+ display, bestFbc, 0, True, context_attribs
+ );
+ }
+ }
+
+ // Sync to ensure any errors generated are processed.
+ XSync(display, False);
+
+ // Restore the original error handler
+ XSetErrorHandler(oldHandler);
+
+ if (ctxErrorOccurred || !ctx) {
+ SkDebugf("Failed to create an OpenGL context.\n");
+ return false;
+ }
+ this->context = ctx;
+
+ // Verify that context is a direct context
+ if (!glXIsDirect(display, ctx)) {
+ //SkDebugf("Indirect GLX rendering context obtained.\n");
+ } else {
+ //SkDebugf("Direct GLX rendering context obtained.\n");
+ }
+
+ //SkDebugf("Making context current.\n");
+ if (!glXMakeCurrent(display, glxPixmap, ctx)) {
+ SkDebugf("Could not set the context.\n");
+ return false;
+ }
+
+ //Setup the framebuffers
+ const GLubyte* glExts = glGetString(GL_EXTENSIONS);
+ if (!gluCheckExtension(
+ reinterpret_cast<const GLubyte*>("GL_EXT_framebuffer_object")
+ , glExts))
+ {
+ SkDebugf("GL_EXT_framebuffer_object not found.\n");
+ return false;
+ }
+ SK_GL_GET_PROC(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT)
+ SK_GL_GET_PROC(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT)
+ SK_GL_GET_PROC(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffersEXT)
+ SK_GL_GET_PROC(PFNGLBINDRENDERBUFFERPROC, glBindRenderbufferEXT)
+ SK_GL_GET_PROC(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorageEXT)
+ SK_GL_GET_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbufferEXT)
+ SK_GL_GET_PROC(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT)
+
+ GLuint fboID;
+ GLuint cbID;
+ GLuint dsID;
+ glGenFramebuffersEXT(1, &fboID);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
+ glGenRenderbuffersEXT(1, &cbID);
+ glBindRenderbufferEXT(GL_RENDERBUFFER, cbID);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA, width, height);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cbID);
+ glGenRenderbuffersEXT(1, &dsID);
+ glBindRenderbufferEXT(GL_RENDERBUFFER, dsID);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_STENCIL, width, height);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, dsID);
+ glViewport(0, 0, width, height);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+
+ GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER);
+ return GL_FRAMEBUFFER_COMPLETE == status;
+}
diff --git a/src/utils/unix/SkOSWindow_Unix.cpp b/src/utils/unix/SkOSWindow_Unix.cpp
index 4ec0c74..ae881d5 100644
--- a/src/utils/unix/SkOSWindow_Unix.cpp
+++ b/src/utils/unix/SkOSWindow_Unix.cpp
@@ -76,7 +76,7 @@ void SkOSWindow::post_linuxevent()
long event_mask = NoEventMask;
XClientMessageEvent event;
event.type = ClientMessage;
- Atom myAtom;
+ Atom myAtom(0);
event.message_type = myAtom;
event.format = 32;
event.data.l[0] = 0;