diff options
author | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-05-19 17:47:02 +0000 |
---|---|---|
committer | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-05-19 17:47:02 +0000 |
commit | 0e45441994a36a78a7a14681799ac519a2b8aae7 (patch) | |
tree | 9bcce5f1cb1e448525054ec9af693c019c500f09 | |
parent | 65245ade841a7aa4d71b1760c081959c71cb4560 (diff) |
Add Mesa as a GL backend.
http://codereview.appspot.com/4545055/
git-svn-id: http://skia.googlecode.com/svn/trunk@1382 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | Makefile | 51 | ||||
-rw-r--r-- | gpu/src/mesa/GrGLDefaultInterface_mesa.cpp | 183 | ||||
-rw-r--r-- | include/utils/SkEGLContext.h | 11 | ||||
-rw-r--r-- | src/utils/mesa/SkEGLContext_Mesa.cpp | 128 |
4 files changed, 359 insertions, 14 deletions
@@ -96,27 +96,48 @@ ifeq ($(SKIA_BUILD_FOR),mac) # CC := gcc-4.0 $(SDK_OPTS) C_INCLUDES += -I/opt/local/include - LINKER_OPTS += -L/opt/local/lib -framework Carbon -lpng -framework OpenGL -framework AGL + LINKER_OPTS += -L/opt/local/lib -framework Carbon -lpng DEFINES += -DSK_BUILD_FOR_MAC -DSK_ENABLE_LIBPNG - + ifeq ($(SKIA_MESA),true) + C_INCLUDES += -I/usr/X11/include + LINKER_OPTS += -L/usr/X11/lib -lOSMesa -lGLU + DEFINES += -DSK_MESA + else + LINKER_OPTS += -framework OpenGL -framework AGL + endif C_INCLUDES += -Iinclude/utils/mac # SRC_LIST += src/ports/SkImageDecoder_CG.cpp SRC_LIST += src/utils/mac/SkCreateCGImageRef.cpp - SRC_LIST += src/utils/mac/SkEGLContext_mac.cpp + ifeq ($(SKIA_MESA),true) + SRC_LIST += src/utils/mesa/SkEGLContext_Mesa.cpp + else + SRC_LIST += src/utils/mac/SkEGLContext_mac.cpp + endif SRC_LIST += src/core/SkTypefaceCache.cpp SRC_LIST += src/ports/SkFontHost_mac_coretext.cpp - # these are our registry-based factories + # these are our registry-based factories SRC_LIST += src/images/SkImageDecoder_Factory.cpp SRC_LIST += src/images/SkImageEncoder_Factory.cpp SRC_LIST += src/images/SkImageDecoder_libpng.cpp - # support files + # support files SRC_LIST += src/images/SkScaledBitmapSampler.cpp - SRC_LIST += gpu/src/mac/GrGLDefaultInterface_mac.cpp + ifeq ($(SKIA_MESA),true) + SRC_LIST += gpu/src/mesa/GrGLDefaultInterface_mesa.cpp + else + SRC_LIST += gpu/src/mac/GrGLDefaultInterface_mac.cpp + endif + else - LINKER_OPTS += -lpng -lfreetype -lGL -lGLU -lX11 + LINKER_OPTS += -lpng -lfreetype DEFINES += -DSK_BUILD_FOR_UNIX -DSK_ENABLE_LIBPNG -DGR_LINUX_BUILD=1 + ifeq ($(SKIA_MESA),true) + LINKER_OPTS += -lOSMesa -lGLU + DEFINES += -DSK_MESA + else + LINKER_OPTS += -lGL -lGLU -lX11 + endif #Assume the color order for now. DEFINES += -DSK_SAMPLES_FOR_X @@ -127,15 +148,23 @@ else 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/unix/SkEGLContext_Unix.cpp - # these are our registry-based factories + ifeq ($(SKIA_MESA),true) + SRC_LIST += src/utils/mesa/SkEGLContext_Mesa.cpp + else + SRC_LIST += src/utils/unix/SkEGLContext_Unix.cpp + endif + # these are our registry-based factories SRC_LIST += src/images/SkImageDecoder_Factory.cpp SRC_LIST += src/images/SkImageEncoder_Factory.cpp SRC_LIST += src/images/SkImageDecoder_libpng.cpp - # support files + # support files SRC_LIST += src/images/SkScaledBitmapSampler.cpp - SRC_LIST += gpu/src/unix/GrGLDefaultInterface_unix.cpp + ifeq ($(SKIA_MESA),true) + SRC_LIST += gpu/src/mesa/GrGLDefaultInterface_mesa.cpp + else + SRC_LIST += gpu/src/unix/GrGLDefaultInterface_unix.cpp + endif endif # For these files, and these files only, compile with -msse2. diff --git a/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp b/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp new file mode 100644 index 0000000000..b494d76baa --- /dev/null +++ b/gpu/src/mesa/GrGLDefaultInterface_mesa.cpp @@ -0,0 +1,183 @@ +/* + 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/osmesa.h" +#include <GL/glext.h> +#include <GL/glu.h> + +#define GR_GL_GET_PROC(F) gDefaultInterface.f ## F = (GrGL ## F ## Proc) \ + OSMesaGetProcAddress("gl" #F); +#define GR_GL_GET_PROC_SUFFIX(F, S) gDefaultInterface.f ## F = (GrGL ## F ## Proc) \ + OSMesaGetProcAddress("gl" #F #S); + +void GrGLSetDefaultGLInterface() { + static GrGLInterface gDefaultInterface; + static bool gDefaultInterfaceInit; + if (!gDefaultInterfaceInit && NULL != OSMesaGetCurrentContext()) { + 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; + //OSMesa on Mac's glTexImage2D takes a GLenum for internalFormat rather than a GLint. + gDefaultInterface.fTexImage2D = reinterpret_cast<GrGLTexImage2DProc>(glTexImage2D); + gDefaultInterface.fTexParameteri = glTexParameteri; + gDefaultInterface.fTexSubImage2D = glTexSubImage2D; + GR_GL_GET_PROC(Uniform1f); + GR_GL_GET_PROC(Uniform1i); + GR_GL_GET_PROC(Uniform1fv); + GR_GL_GET_PROC(Uniform1iv); + GR_GL_GET_PROC(Uniform2f); + GR_GL_GET_PROC(Uniform2i); + GR_GL_GET_PROC(Uniform2fv); + GR_GL_GET_PROC(Uniform2iv); + GR_GL_GET_PROC(Uniform3f); + GR_GL_GET_PROC(Uniform3i); + GR_GL_GET_PROC(Uniform3fv); + GR_GL_GET_PROC(Uniform3iv); + GR_GL_GET_PROC(Uniform4f); + GR_GL_GET_PROC(Uniform4i); + GR_GL_GET_PROC(Uniform4fv); + GR_GL_GET_PROC(Uniform4iv); + GR_GL_GET_PROC(UniformMatrix2fv); + GR_GL_GET_PROC(UniformMatrix3fv); + GR_GL_GET_PROC(UniformMatrix4fv); + 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_from_string( + "GL_ARB_framebuffer_object", extString)) { + 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); +} diff --git a/include/utils/SkEGLContext.h b/include/utils/SkEGLContext.h index 6aa8518e53..d67cf0c317 100644 --- a/include/utils/SkEGLContext.h +++ b/include/utils/SkEGLContext.h @@ -1,7 +1,9 @@ #ifndef SkEGLContext_DEFINED #define SkEGLContext_DEFINED -#if defined(SK_BUILD_FOR_MAC) +#if defined(SK_MESA) + #include "GL/osmesa.h" +#elif defined(SK_BUILD_FOR_MAC) #include <AGL/agl.h> #elif defined(SK_BUILD_FOR_UNIX) #include <X11/Xlib.h> @@ -18,10 +20,13 @@ public: SkEGLContext(); ~SkEGLContext(); - bool init(int width, int height); + bool init(const int width, const int height); private: -#if defined(SK_BUILD_FOR_MAC) +#if defined(SK_MESA) + OSMesaContext context; + GLfloat *image; +#elif defined(SK_BUILD_FOR_MAC) AGLContext context; #elif defined(SK_BUILD_FOR_UNIX) GLXContext context; diff --git a/src/utils/mesa/SkEGLContext_Mesa.cpp b/src/utils/mesa/SkEGLContext_Mesa.cpp new file mode 100644 index 0000000000..ed1b7cd451 --- /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; +} |