git-svn-id: http://skia.googlecode.com/svn/trunk@1135 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Scroggo 2011-04-15 14:48:08 +00:00
Родитель f5dbe2f00f
Коммит 9df214e836
6 изменённых файлов: 388 добавлений и 122 удалений

Просмотреть файл

@ -0,0 +1,170 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "GrGLInterface.h"
#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glu.h>
#define GR_GL_GET_PROC(F) gDefaultInterface.f ## F = (GrGLInterface::GrGL ## F ## Proc) \
glXGetProcAddress(reinterpret_cast<const GLubyte*>("gl" #F));
#define GR_GL_GET_PROC_SUFFIX(F, S) gDefaultInterface.f ## F = (GrGLInterface::GrGL ## F ## Proc) \
glXGetProcAddress(reinterpret_cast<const GLubyte*>("gl" #F #S));
void GrGLSetDefaultGLInterface() {
static GrGLInterface gDefaultInterface;
static bool gDefaultInterfaceInit;
if (!gDefaultInterfaceInit && NULL != glXGetCurrentContext()) {
int major, minor;
const char* versionString = (const char*) glGetString(GL_VERSION);
const char* extString = (const char*) glGetString(GL_EXTENSIONS);
gl_version_from_string(&major, &minor, versionString);
if (major == 1 && minor < 5) {
// We must have array and element_array buffer objects.
return;
}
gDefaultInterface.fActiveTexture = glActiveTexture;
GR_GL_GET_PROC(AttachShader);
GR_GL_GET_PROC(BindAttribLocation);
GR_GL_GET_PROC(BindBuffer);
gDefaultInterface.fBindTexture = glBindTexture;
gDefaultInterface.fBlendColor = glBlendColor;
gDefaultInterface.fBlendFunc = glBlendFunc;
GR_GL_GET_PROC(BufferData);
GR_GL_GET_PROC(BufferSubData);
gDefaultInterface.fClear = glClear;
gDefaultInterface.fClearColor = glClearColor;
gDefaultInterface.fClearStencil = glClearStencil;
gDefaultInterface.fClientActiveTexture = glClientActiveTexture;
gDefaultInterface.fColorMask = glColorMask;
gDefaultInterface.fColorPointer = glColorPointer;
gDefaultInterface.fColor4ub = glColor4ub;
GR_GL_GET_PROC(CompileShader);
gDefaultInterface.fCompressedTexImage2D = glCompressedTexImage2D;
GR_GL_GET_PROC(CreateProgram);
GR_GL_GET_PROC(CreateShader);
gDefaultInterface.fCullFace = glCullFace;
GR_GL_GET_PROC(DeleteBuffers);
GR_GL_GET_PROC(DeleteProgram);
GR_GL_GET_PROC(DeleteShader);
gDefaultInterface.fDeleteTextures = glDeleteTextures;
gDefaultInterface.fDepthMask = glDepthMask;
gDefaultInterface.fDisable = glDisable;
gDefaultInterface.fDisableClientState = glDisableClientState;
GR_GL_GET_PROC(DisableVertexAttribArray);
gDefaultInterface.fDrawArrays = glDrawArrays;
gDefaultInterface.fDrawElements = glDrawElements;
gDefaultInterface.fEnable = glEnable;
gDefaultInterface.fEnableClientState = glEnableClientState;
GR_GL_GET_PROC(EnableVertexAttribArray);
gDefaultInterface.fFrontFace = glFrontFace;
GR_GL_GET_PROC(GenBuffers);
GR_GL_GET_PROC(GetBufferParameteriv);
gDefaultInterface.fGetError = glGetError;
gDefaultInterface.fGetIntegerv = glGetIntegerv;
GR_GL_GET_PROC(GetProgramInfoLog);
GR_GL_GET_PROC(GetProgramiv);
GR_GL_GET_PROC(GetShaderInfoLog);
GR_GL_GET_PROC(GetShaderiv);
gDefaultInterface.fGetString = glGetString;
gDefaultInterface.fGenTextures = glGenTextures;
GR_GL_GET_PROC(GetUniformLocation);
gDefaultInterface.fLineWidth = glLineWidth;
GR_GL_GET_PROC(LinkProgram);
gDefaultInterface.fLoadMatrixf = glLoadMatrixf;
GR_GL_GET_PROC(MapBuffer);
gDefaultInterface.fMatrixMode = glMatrixMode;
gDefaultInterface.fPointSize = glPointSize;
gDefaultInterface.fPixelStorei = glPixelStorei;
gDefaultInterface.fReadPixels = glReadPixels;
gDefaultInterface.fScissor = glScissor;
gDefaultInterface.fShadeModel = glShadeModel;
GR_GL_GET_PROC(ShaderSource);
gDefaultInterface.fStencilFunc = glStencilFunc;
GR_GL_GET_PROC(StencilFuncSeparate);
gDefaultInterface.fStencilMask = glStencilMask;
GR_GL_GET_PROC(StencilMaskSeparate);
gDefaultInterface.fStencilOp = glStencilOp;
GR_GL_GET_PROC(StencilOpSeparate);
gDefaultInterface.fTexCoordPointer = glTexCoordPointer;
gDefaultInterface.fTexEnvi = glTexEnvi;
// mac uses GLenum for internalFormat param (non-standard)
// amounts to int vs. uint.
gDefaultInterface.fTexImage2D =
(GrGLInterface::GrGLTexImage2DProc)glTexImage2D;
gDefaultInterface.fTexParameteri = glTexParameteri;
gDefaultInterface.fTexSubImage2D = glTexSubImage2D;
GR_GL_GET_PROC(Uniform1fv);
GR_GL_GET_PROC(Uniform1i);
GR_GL_GET_PROC(Uniform4fv);
GR_GL_GET_PROC(UniformMatrix3fv);
GR_GL_GET_PROC(UnmapBuffer);
GR_GL_GET_PROC(UseProgram);
GR_GL_GET_PROC(VertexAttrib4fv);
GR_GL_GET_PROC(VertexAttribPointer);
gDefaultInterface.fVertexPointer = glVertexPointer;
gDefaultInterface.fViewport = glViewport;
// First look for GL3.0 FBO or GL_ARB_framebuffer_object (same since
// GL_ARB_framebuffer_object doesn't use ARB suffix.)
if (major >= 3 || has_gl_extension("GL_ARB_framebuffer_object")) {
GR_GL_GET_PROC(GenFramebuffers);
GR_GL_GET_PROC(BindFramebuffer);
GR_GL_GET_PROC(FramebufferTexture2D);
GR_GL_GET_PROC(CheckFramebufferStatus);
GR_GL_GET_PROC(DeleteFramebuffers);
GR_GL_GET_PROC(RenderbufferStorage);
GR_GL_GET_PROC(GenRenderbuffers);
GR_GL_GET_PROC(DeleteRenderbuffers);
GR_GL_GET_PROC(FramebufferRenderbuffer);
GR_GL_GET_PROC(BindRenderbuffer);
GR_GL_GET_PROC(RenderbufferStorageMultisample);
GR_GL_GET_PROC(BlitFramebuffer);
} else if (has_gl_extension_from_string("GL_EXT_framebuffer_object",
extString)) {
GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample",
extString)) {
GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
}
if (has_gl_extension_from_string("GL_EXT_framebuffer_blit",
extString)) {
GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
}
} else {
// we must have FBOs
return;
}
gDefaultInterface.fBindingsExported = kDesktop_GrGLBinding;
gDefaultInterfaceInit = true;
}
if (gDefaultInterfaceInit)
GrGLSetGLInterface(&gDefaultInterface);
}

Просмотреть файл

@ -997,6 +997,8 @@
'../gpu/src/mac/GrGLDefaultInterface_mac.cpp',
'../gpu/src/win/GrGLDefaultInterface_win.cpp',
'../gpu/src/unix/GrGLDefaultInterface_unix.cpp',
],
'defines': [
'GR_IMPLEMENTATION=1',
@ -1006,6 +1008,9 @@
'defines': [
'GR_LINUX_BUILD=1',
],
'sources!': [
'../gpu/src/GrGLDefaultInterface_none.cpp',
],
'link_settings': {
'libraries': [
'-lGL',
@ -1045,6 +1050,11 @@
'../gpu/src/mac/GrGLDefaultInterface_mac.cpp',
],
}],
[ 'OS != "linux"', {
'sources!': [
'../gpu/src/unix/GrGLDefaultInterface_unix.cpp',
],
}],
],
'direct_dependent_settings': {
'conditions': [

Просмотреть файл

@ -19,6 +19,7 @@
#include "SkWindow.h"
#include <X11/Xlib.h>
#include <GL/glx.h>
class SkBitmap;
class SkEvent;
@ -28,6 +29,8 @@ struct SkUnixWindow {
Window fWin;
size_t fOSWin;
GC fGc;
GLXContext fGLContext;
bool fGLCreated;
};
class SkOSWindow : public SkWindow {
@ -38,7 +41,8 @@ public:
void* getHWND() const { return (void*)fUnixWindow.fWin; }
void* getDisplay() const { return (void*)fUnixWindow.fDisplay; }
void* getUnixWindow() const { return (void*)&fUnixWindow; }
void setUnixWindow(Display*, Window, size_t, GC);
void loop();
void post_linuxevent();
bool attachGL();
void detachGL();
void presentGL();
@ -58,8 +62,15 @@ protected:
private:
SkUnixWindow fUnixWindow;
bool fGLAttached;
bool fRestart;
// Needed for GL
XVisualInfo* fVi;
void doPaint();
void restartLoop();
void mapWindowAndWait();
typedef SkWindow INHERITED;
};

Просмотреть файл

@ -2,6 +2,8 @@
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <GL/glx.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "SkWindow.h"
@ -9,37 +11,210 @@
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkEvent.h"
#include "SkKey.h"
#include "SkWindow.h"
#include "XkeysToSkKeys.h"
extern "C" {
#include "keysym2ucs.h"
}
const int WIDTH = 1000;
const int HEIGHT = 1000;
// Determine which events to listen for.
const long EVENT_MASK = StructureNotifyMask|ButtonPressMask|ButtonReleaseMask
|ExposureMask|PointerMotionMask|KeyPressMask|KeyReleaseMask;
SkOSWindow::SkOSWindow(void* unused)
{
fUnixWindow.fDisplay = NULL;
fUnixWindow.fDisplay = XOpenDisplay(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, 0, att);
if (fVi) {
XSetWindowAttributes swa;
swa.event_mask = EVENT_MASK;
fUnixWindow.fWin = XCreateWindow(dsp, DefaultRootWindow(dsp),
0, 0, WIDTH, HEIGHT, 0, fVi->depth,
InputOutput, fVi->visual, CWEventMask, &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->resize(WIDTH, HEIGHT);
fRestart = false;
fUnixWindow.fGLCreated = false;
}
SkOSWindow::~SkOSWindow()
{
if (fUnixWindow.fDisplay) {
if (fGLAttached)
glXMakeCurrent(fUnixWindow.fDisplay, None, NULL);
XFreeGC(fUnixWindow.fDisplay, fUnixWindow.fGc);
if (fUnixWindow.fGLCreated)
glXDestroyContext(fUnixWindow.fDisplay, fUnixWindow.fGLContext);
XDestroyWindow(fUnixWindow.fDisplay, fUnixWindow.fWin);
XCloseDisplay(fUnixWindow.fDisplay);
fUnixWindow.fDisplay = 0;
}
}
void SkOSWindow::setUnixWindow(Display* dsp, Window win, size_t screenNumber, GC gc)
void SkOSWindow::post_linuxevent()
{
fUnixWindow.fDisplay = dsp;
fUnixWindow.fWin = win;
fUnixWindow.fOSWin = screenNumber;
fUnixWindow.fGc = gc;
// Put an event in the X queue to fire an SkEvent.
if (!fUnixWindow.fDisplay) return;
long event_mask = NoEventMask;
XClientMessageEvent event;
event.type = ClientMessage;
Atom myAtom;
event.message_type = myAtom;
event.format = 32;
event.data.l[0] = 0;
XSendEvent(fUnixWindow.fDisplay, fUnixWindow.fWin, false, 0,
(XEvent*) &event);
}
void SkOSWindow::restartLoop()
{
// We have a new window, so we need to set the title again and restart the
// loop.
this->setTitle(this->getTitle());
fRestart = true;
}
void SkOSWindow::loop()
{
Display* dsp = fUnixWindow.fDisplay;
XSelectInput(dsp, fUnixWindow.fWin, EVENT_MASK);
bool loop = true;
XEvent evt;
while (loop) {
if (fRestart) {
fRestart = false;
this->loop();
return;
}
XNextEvent(dsp, &evt);
switch (evt.type) {
case Expose:
if (evt.xexpose.count == 0)
this->inval(NULL);
break;
case ConfigureNotify:
this->resize(evt.xconfigure.width, evt.xconfigure.height);
break;
case ButtonPress:
if (evt.xbutton.button == Button1)
this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kDown_State);
break;
case ButtonRelease:
if (evt.xbutton.button == Button1)
this->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kUp_State);
break;
case MotionNotify:
this->handleClick(evt.xmotion.x, evt.xmotion.y, SkView::Click::kMoved_State);
break;
case KeyPress:
{
KeySym keysym = XKeycodeToKeysym(dsp, evt.xkey.keycode, 0);
//SkDebugf("pressed key %i!\n\tKeySym:%i\n", evt.xkey.keycode, XKeycodeToKeysym(dsp, evt.xkey.keycode, 0));
if (keysym == XK_Escape) {
loop = false;
break;
}
this->handleKey(XKeyToSkKey(keysym));
long uni = keysym2ucs(keysym);
if (uni != -1) {
this->handleChar((SkUnichar) uni);
}
break;
}
case KeyRelease:
//SkDebugf("released key %i\n", evt.xkey.keycode);
this->handleKeyUp(XKeyToSkKey(XKeycodeToKeysym(dsp, evt.xkey.keycode, 0)));
break;
case ClientMessage:
if (SkEvent::ProcessEvent()) {
this->post_linuxevent();
}
break;
default:
// Do nothing for other events
break;
}
}
}
void SkOSWindow::mapWindowAndWait()
{
Display* dsp = fUnixWindow.fDisplay;
Window win = fUnixWindow.fWin;
XMapWindow(dsp, win);
long eventMask = StructureNotifyMask;
XSelectInput(dsp, win, eventMask);
// Wait until screen is ready.
XEvent evt;
do {
XNextEvent(dsp, &evt);
} while(evt.type != MapNotify);
}
bool SkOSWindow::attachGL()
{
return false;
if (fGLAttached) return true;
Display* dsp = fUnixWindow.fDisplay;
if (!dsp || !fVi) return false;
if (!fUnixWindow.fGLCreated) {
fUnixWindow.fGLContext = glXCreateContext(dsp, fVi, NULL, GL_TRUE);
fUnixWindow.fGLCreated = true;
glXMakeCurrent(dsp, fUnixWindow.fWin, fUnixWindow.fGLContext);
glViewport(0, 0, SkScalarRound(this->width()), SkScalarRound(this->height()));
glClearColor(0, 0, 0, 0);
glClearStencil(0);
glStencilMask(0xffffffff);
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
else
glXMakeCurrent(dsp, fUnixWindow.fWin, fUnixWindow.fGLContext);
fGLAttached = true;
this->restartLoop();
return true;
}
void SkOSWindow::detachGL()
{
if (!fUnixWindow.fDisplay || !fGLAttached) return;
fGLAttached = false;
// Returns back to normal drawing.
glXMakeCurrent(fUnixWindow.fDisplay, None, NULL);
this->restartLoop();
// Ensure that we redraw when switching back to raster.
this->inval(NULL);
}
void SkOSWindow::presentGL()
{
if (fUnixWindow.fDisplay && fGLAttached) {
glXSwapBuffers(fUnixWindow.fDisplay, fUnixWindow.fWin);
}
}
void SkOSWindow::onSetTitle(const char title[])
@ -63,7 +238,8 @@ bool SkOSWindow::onEvent(const SkEvent& evt)
{
if (evt.isType("inval-imageview")) {
update(NULL);
doPaint();
if (!fGLAttached)
doPaint();
return true;
}
return INHERITED::onEvent(evt);

Просмотреть файл

@ -2,37 +2,14 @@
#include "X11/keysym.h"
#include "SkApplication.h"
#include "SkKey.h"
#include "SkView.h"
#include "SkEvent.h"
#include "SkWindow.h"
#include "XkeysToSkKeys.h"
extern "C" {
#include "keysym2ucs.h"
}
#include "SkTypes.h"
//#include <signal.h>
//#include <sys/time.h>
// Globals for access to the window
Display* dsp = 0;
Window win;
const int WIDTH = 1000;
const int HEIGHT = 1000;
// Put an event in the X queue to fire an SkEvent.
static void post_linuxevent()
{
if (!dsp) return;
long event_mask = NoEventMask;
XClientMessageEvent event;
event.type = ClientMessage;
Atom myAtom;
event.message_type = myAtom;
event.format = 32;
event.data.l[0] = 0;
XSendEvent(dsp, win, false, 0, (XEvent*) &event);
}
SkOSWindow* gWindow;
#if 0
static void catch_alarm(int sig)
@ -43,94 +20,13 @@ static void catch_alarm(int sig)
#endif
int main(){
dsp = XOpenDisplay(NULL);
if(!dsp) {
return 1;
}
// signal(SIGALRM, catch_alarm);
win = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, WIDTH, HEIGHT, 0, 0, 0);
XMapWindow(dsp, win);
long eventMask = StructureNotifyMask;
XSelectInput(dsp, win, eventMask);
// Wait until screen is ready.
XEvent evt;
do {
XNextEvent(dsp, &evt);
} while(evt.type != MapNotify);
GC gc = XCreateGC(dsp, win, 0, NULL);
gWindow = create_sk_window(NULL);
// Start normal Skia sequence
application_init();
SkOSWindow* window = create_sk_window(NULL);
window->setUnixWindow(dsp, win, DefaultScreen(dsp), gc);
window->resize(WIDTH, HEIGHT);
// Determine which events to listen for.
eventMask = StructureNotifyMask|ButtonPressMask|ButtonReleaseMask
|ExposureMask|PointerMotionMask|KeyPressMask|KeyReleaseMask;
XSelectInput(dsp, win, eventMask);
bool loop = true;
while (loop) {
XNextEvent(dsp, &evt);
switch (evt.type) {
case Expose:
if (evt.xexpose.count == 0)
window->inval(NULL);
break;
case ConfigureNotify:
window->resize(evt.xconfigure.width, evt.xconfigure.height);
break;
case ButtonPress:
if (evt.xbutton.button == Button1)
window->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kDown_State);
break;
case ButtonRelease:
if (evt.xbutton.button == Button1)
window->handleClick(evt.xbutton.x, evt.xbutton.y, SkView::Click::kUp_State);
break;
case MotionNotify:
window->handleClick(evt.xmotion.x, evt.xmotion.y, SkView::Click::kMoved_State);
break;
case KeyPress:
{
KeySym keysym = XKeycodeToKeysym(dsp, evt.xkey.keycode, 0);
//SkDebugf("pressed key %i!\n\tKeySym:%i\n", evt.xkey.keycode, XKeycodeToKeysym(dsp, evt.xkey.keycode, 0));
if (keysym == XK_Escape) {
loop = false;
break;
}
window->handleKey(XKeyToSkKey(keysym));
long uni = keysym2ucs(keysym);
if (uni != -1) {
window->handleChar((SkUnichar) uni);
}
break;
}
case KeyRelease:
//SkDebugf("released key %i\n", evt.xkey.keycode);
window->handleKeyUp(XKeyToSkKey(XKeycodeToKeysym(dsp, evt.xkey.keycode, 0)));
break;
case ClientMessage:
if (SkEvent::ProcessEvent()) {
post_linuxevent();
}
break;
default:
// Do nothing for other events
break;
}
}
XFreeGC(dsp, gc);
XDestroyWindow(dsp, win);
XCloseDisplay(dsp);
gWindow->loop();
application_term();
return 0;
@ -140,7 +36,10 @@ int main(){
void SkEvent::SignalNonEmptyQueue()
{
post_linuxevent();
if (gWindow)
gWindow->post_linuxevent();
else
while (SkEvent::ProcessEvent());
}
void SkEvent::SignalQueueTimer(SkMSec delay)

Просмотреть файл

@ -17,7 +17,7 @@ VPATH = libs:../src/ports:../samplecode:../src/core:../src/utils/unix
#generate debugging info
CFLAGS = -g
SRC_LIST := main.cpp SkOSWindow_Unix.cpp SkXMLParser_empty.cpp SkDebug.cpp
SRC_LIST := main.cpp SkOSWindow_Unix.cpp SkXMLParser_empty.cpp SkDebug.cpp ../gpu/src/unix/GrGLDefaultInterface_unix.cpp
#views files
include ../src/views/views_files.mk