зеркало из https://github.com/mozilla/moz-skia.git
Add GL context creation for X so that gm can run GPU on Linux.
http://codereview.appspot.com/4548047/ git-svn-id: http://skia.googlecode.com/svn/trunk@1343 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
1dd17a133f
Коммит
16bab87a78
12
Makefile
12
Makefile
|
@ -115,19 +115,19 @@ ifeq ($(SKIA_BUILD_FOR),mac)
|
|||
|
||||
SRC_LIST += gpu/src/mac/GrGLDefaultInterface_mac.cpp
|
||||
else
|
||||
LINKER_OPTS += -lpng -lfreetype -lGL
|
||||
LINKER_OPTS += -lpng -lfreetype -lGL -lGLU -lX11
|
||||
DEFINES += -DSK_BUILD_FOR_UNIX -DSK_ENABLE_LIBPNG -DGR_LINUX_BUILD=1
|
||||
|
||||
ifeq ($(SKIA_SAMPLES_FOR_X),true)
|
||||
DEFINES += -DSK_SAMPLES_FOR_X
|
||||
endif
|
||||
#Assume the color order for now.
|
||||
DEFINES += -DSK_SAMPLES_FOR_X
|
||||
|
||||
# needed for freetype support
|
||||
C_INCLUDES += -I/usr/include/freetype2
|
||||
SRC_LIST += src/ports/SkFontHost_linux.cpp
|
||||
SRC_LIST += src/ports/SkFontHost_gamma_none.cpp
|
||||
SRC_LIST += src/ports/SkFontHost_FreeType.cpp
|
||||
SRC_LIST += src/ports/SkFontHost_FreeType_Subpixel.cpp
|
||||
SRC_LIST += src/utils/SkEGLContext_none.cpp
|
||||
SRC_LIST += src/utils/unix/SkEGLContext_Unix.cpp
|
||||
# these are our registry-based factories
|
||||
SRC_LIST += src/images/SkImageDecoder_Factory.cpp
|
||||
SRC_LIST += src/images/SkImageEncoder_Factory.cpp
|
||||
|
@ -135,7 +135,7 @@ else
|
|||
# support files
|
||||
SRC_LIST += src/images/SkScaledBitmapSampler.cpp
|
||||
|
||||
SRC_LIST += gpu/src/GrGLDefaultInterface_none.cpp
|
||||
SRC_LIST += gpu/src/unix/GrGLDefaultInterface_unix.cpp
|
||||
endif
|
||||
|
||||
# For these files, and these files only, compile with -msse2.
|
||||
|
|
|
@ -1,20 +1,36 @@
|
|||
#ifndef SkEGLContext_DEFINED
|
||||
#define SkEGLContext_DEFINED
|
||||
|
||||
#include "SkTypes.h"
|
||||
#if defined(SK_BUILD_FOR_MAC)
|
||||
#include <AGL/agl.h>
|
||||
#elif defined(SK_BUILD_FOR_UNIX)
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/glx.h>
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create an offscreen opengl context
|
||||
*/
|
||||
class SkEGLContext {
|
||||
public:
|
||||
SkEGLContext();
|
||||
~SkEGLContext();
|
||||
SkEGLContext();
|
||||
~SkEGLContext();
|
||||
|
||||
bool init(int width, int height);
|
||||
bool init(int width, int height);
|
||||
|
||||
private:
|
||||
void* fContext;
|
||||
#if defined(SK_BUILD_FOR_MAC)
|
||||
AGLContext context;
|
||||
#elif defined(SK_BUILD_FOR_UNIX)
|
||||
GLXContext context;
|
||||
Display *display;
|
||||
Pixmap pixmap;
|
||||
GLXPixmap glxPixmap;
|
||||
#else
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,59 +1,60 @@
|
|||
#include "SkEGLContext.h"
|
||||
//#include "SkTypes.h"
|
||||
#include <AGL/agl.h>
|
||||
|
||||
SkEGLContext::SkEGLContext() : fContext(NULL) {
|
||||
SkEGLContext::SkEGLContext() : context(NULL) {
|
||||
}
|
||||
|
||||
SkEGLContext::~SkEGLContext() {
|
||||
if (fContext) {
|
||||
aglDestroyContext((AGLContext)fContext);
|
||||
}
|
||||
if (this->context) {
|
||||
aglDestroyContext(this->context);
|
||||
}
|
||||
}
|
||||
|
||||
bool SkEGLContext::init(int width, int height) {
|
||||
GLint major, minor;
|
||||
AGLContext ctx;
|
||||
GLint major, minor;
|
||||
AGLContext ctx;
|
||||
|
||||
aglGetVersion(&major, &minor);
|
||||
// SkDebugf("---- agl version %d %d\n", major, minor);
|
||||
aglGetVersion(&major, &minor);
|
||||
//SkDebugf("---- agl version %d %d\n", major, minor);
|
||||
|
||||
const GLint pixelAttrs[] = {
|
||||
AGL_RGBA,
|
||||
AGL_STENCIL_SIZE, 8,
|
||||
const GLint pixelAttrs[] = {
|
||||
AGL_RGBA,
|
||||
AGL_STENCIL_SIZE, 8,
|
||||
/*
|
||||
AGL_SAMPLE_BUFFERS_ARB, 1,
|
||||
AGL_MULTISAMPLE,
|
||||
AGL_SAMPLES_ARB, 2,
|
||||
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);
|
||||
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);
|
||||
static const GLint interval = 1;
|
||||
aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval);
|
||||
*/
|
||||
|
||||
aglSetCurrentContext(ctx);
|
||||
fContext = (void*)ctx;
|
||||
aglSetCurrentContext(ctx);
|
||||
this->context = ctx;
|
||||
|
||||
// Now create our FBO render target
|
||||
// Now create our FBO render target
|
||||
|
||||
GLuint fboID;
|
||||
GLuint cbID;
|
||||
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);
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
Загрузка…
Ссылка в новой задаче