mirror of https://github.com/xemu-project/xemu.git
Changes to configure script and OpenGL for Win32
TODO: Need to implement gloffscreen_cgl for Mac.
This commit is contained in:
parent
6ec5ad1698
commit
59bc8d9539
|
@ -2445,6 +2445,17 @@ if test "$opengl" != "no" ; then
|
|||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <GLUT/glut.h>
|
||||
int main(void) { return GL_VERSION != 0; }
|
||||
EOF
|
||||
elif test "$mingw32" = "yes" ; then
|
||||
opengl_libs="-lglut32win -lOpenGL32 -lglu32 -lglew32 -lgdi32"
|
||||
cat > $TMPC << EOF
|
||||
#include <windows.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/wglext.h>
|
||||
#include <GL/glut.h>
|
||||
int main(void) { return GL_VERSION != 0; }
|
||||
EOF
|
||||
else
|
||||
opengl_libs="-lGL -lX11"
|
||||
|
|
62
hw/nv2a.c
62
hw/nv2a.c
|
@ -37,13 +37,22 @@
|
|||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <GLUT/glut.h>
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/wglext.h>
|
||||
#include <GL/glut.h>
|
||||
#else
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glut.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "nv2a.h"
|
||||
#include "gloffscreen.h"
|
||||
|
||||
//#define DEBUG_NV2A
|
||||
#ifdef DEBUG_NV2A
|
||||
|
@ -766,7 +775,7 @@ typedef struct GraphicsContext {
|
|||
uint32_t zstencil_clear_value;
|
||||
uint32_t color_clear_value;
|
||||
|
||||
CGLContextObj gl_context;
|
||||
GloContext *gl_context;
|
||||
|
||||
GLuint gl_framebuffer;
|
||||
GLuint gl_renderbuffer;
|
||||
|
@ -1433,6 +1442,28 @@ static void kelvin_bind_fragment_shader(NV2AState *d, KelvinState *kelvin)
|
|||
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* Need to define it since its not available in GLU 1.2 Windows*/
|
||||
GLboolean gluCheckExtension( const GLubyte *extName, const GLubyte *extString )
|
||||
{
|
||||
char *p = (char *) glGetString(GL_EXTENSIONS);
|
||||
char *end;
|
||||
if(p==NULL)
|
||||
return GL_FALSE;
|
||||
end = p + strlen(p);
|
||||
|
||||
while (p < end) {
|
||||
int n = strcspn(p, " ");
|
||||
if((strlen(extName) == n) && (strncmp(extName,p,n) == 0)) {
|
||||
return GL_TRUE;
|
||||
}
|
||||
p += (n + 1);
|
||||
}
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void kelvin_read_surface(NV2AState *d, KelvinState *kelvin)
|
||||
{
|
||||
/* read the renderbuffer into the set surface */
|
||||
|
@ -1485,20 +1516,10 @@ static void kelvin_read_surface(NV2AState *d, KelvinState *kelvin)
|
|||
|
||||
static void pgraph_context_init(GraphicsContext *context)
|
||||
{
|
||||
/* TODO: context creation on linux */
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFAAccelerated,
|
||||
(CGLPixelFormatAttribute)0
|
||||
};
|
||||
|
||||
CGLPixelFormatObj pix;
|
||||
GLint num;
|
||||
CGLChoosePixelFormat(attributes, &pix, &num);
|
||||
CGLCreateContext(pix, NULL, &context->gl_context);
|
||||
CGLDestroyPixelFormat(pix);
|
||||
|
||||
CGLSetCurrentContext(context->gl_context);
|
||||
context->gl_context = glo_context_create(GLO_FF_DEFAULT);
|
||||
|
||||
/* TODO: create glo functions for Mac */
|
||||
|
||||
/* Check context capabilities */
|
||||
const GLubyte *extensions;
|
||||
|
@ -1523,8 +1544,6 @@ static void pgraph_context_init(GraphicsContext *context)
|
|||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attributes);
|
||||
assert(max_vertex_attributes >= NV2A_VERTEXSHADER_ATTRIBUTES);
|
||||
|
||||
|
||||
|
||||
glGenFramebuffersEXT(1, &context->gl_framebuffer);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, context->gl_framebuffer);
|
||||
|
||||
|
@ -1545,29 +1564,28 @@ static void pgraph_context_init(GraphicsContext *context)
|
|||
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
|
||||
CGLSetCurrentContext(NULL);
|
||||
glo_set_current(NULL);
|
||||
}
|
||||
|
||||
static void pgraph_context_set_current(GraphicsContext *context)
|
||||
{
|
||||
if (context) {
|
||||
CGLSetCurrentContext(context->gl_context);
|
||||
glo_set_current(context->gl_context);
|
||||
} else {
|
||||
CGLSetCurrentContext(NULL);
|
||||
glo_set_current(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void pgraph_context_destroy(GraphicsContext *context)
|
||||
{
|
||||
CGLSetCurrentContext(context->gl_context);
|
||||
glo_set_current(context->gl_context);
|
||||
|
||||
glDeleteRenderbuffersEXT(1, &context->gl_renderbuffer);
|
||||
glDeleteFramebuffersEXT(1, &context->gl_framebuffer);
|
||||
|
||||
CGLSetCurrentContext(NULL);
|
||||
glo_set_current(NULL);
|
||||
|
||||
CGLDestroyContext(context->gl_context);
|
||||
glo_context_destroy(context->gl_context);
|
||||
}
|
||||
|
||||
static void pgraph_method(NV2AState *d,
|
||||
|
|
|
@ -6,3 +6,4 @@ obj-$(CONFIG_KVM) += kvm.o hyperv.o
|
|||
obj-$(CONFIG_NO_KVM) += kvm-stub.o
|
||||
obj-$(CONFIG_LINUX_USER) += ioport-user.o
|
||||
obj-$(CONFIG_BSD_USER) += ioport-user.o
|
||||
obj-$(CONFIG_XBOX) += gloffscreen_common.o gloffscreen_wgl.o gloffscreen_glx.o gloffscreen_cgl.o
|
|
@ -0,0 +1,586 @@
|
|||
/*
|
||||
* Offscreen OpenGL abstraction layer - WGL (windows) specific
|
||||
*
|
||||
* Copyright (c) 2010 Intel
|
||||
* Written by:
|
||||
* Gordon Williams <gordon.williams@collabora.co.uk>
|
||||
* Ian Molton <ian.molton@collabora.co.uk>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <GLUT/glut.h>
|
||||
|
||||
#include "gloffscreen.h"
|
||||
|
||||
/* In Windows, you must create a window *before* you can create a pbuffer or
|
||||
* get a context. So we create a hidden Window on startup (see glo_init/GloMain).
|
||||
*
|
||||
* Also, you can't share contexts that have different pixel formats, so we can't just
|
||||
* create a new context from the window. We must create a whole new PBuffer just for
|
||||
* a context :(
|
||||
*/
|
||||
|
||||
struct GloMain {
|
||||
int init;
|
||||
// Not needed for CGL?
|
||||
};
|
||||
struct GloMain glo;
|
||||
int glo_inited = 0;
|
||||
|
||||
struct _GloContext {
|
||||
CGLContextObj cglContext;
|
||||
};
|
||||
|
||||
struct _GloSurface {
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
|
||||
GloContext *context;
|
||||
};
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
//extern const char *glo_glXQueryExtensionsString(void);
|
||||
|
||||
extern void glo_surface_getcontents_readpixels(int formatFlags, int stride,
|
||||
int bpp, int width, int height, void *data);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
int glo_initialised(void) {
|
||||
return glo_inited;
|
||||
}
|
||||
|
||||
/* Initialise gloffscreen */
|
||||
void glo_init(void) {
|
||||
|
||||
// TODO: CGL Implementation.
|
||||
// Initialization needed for CGL?
|
||||
|
||||
if (glo_inited) {
|
||||
printf( "gloffscreen already inited\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
glo_inited = 1;
|
||||
}
|
||||
|
||||
/* Uninitialise gloffscreen */
|
||||
void glo_kill(void) {
|
||||
// TODO: CGL Implementation.
|
||||
}
|
||||
|
||||
|
||||
static const char *STANDARD_GL_FUNCTIONS ={
|
||||
/* Miscellaneous */
|
||||
"glClearIndex\0"
|
||||
"glClearColor\0"
|
||||
"glClear\0"
|
||||
"glIndexMask\0"
|
||||
"glColorMask\0"
|
||||
"glAlphaFunc\0"
|
||||
"glBlendFunc\0"
|
||||
"glLogicOp\0"
|
||||
"glCullFace\0"
|
||||
"glFrontFace\0"
|
||||
"glPointSize\0"
|
||||
"glLineWidth\0"
|
||||
"glLineStipple\0"
|
||||
"glPolygonMode\0"
|
||||
"glPolygonOffset\0"
|
||||
"glPolygonStipple\0"
|
||||
"glGetPolygonStipple\0"
|
||||
"glEdgeFlag\0"
|
||||
"glEdgeFlagv\0"
|
||||
"glScissor\0"
|
||||
"glClipPlane\0"
|
||||
"glGetClipPlane\0"
|
||||
"glDrawBuffer\0"
|
||||
"glReadBuffer\0"
|
||||
"glEnable\0"
|
||||
"glDisable\0"
|
||||
"glIsEnabled\0"
|
||||
"glEnableClientState\0"
|
||||
"glDisableClientState\0"
|
||||
"glGetBooleanv\0"
|
||||
"glGetDoublev\0"
|
||||
"glGetFloatv\0"
|
||||
"glGetIntegerv\0"
|
||||
"glPushAttrib\0"
|
||||
"glPopAttrib\0"
|
||||
"glPushClientAttrib\0"
|
||||
"glPopClientAttrib\0"
|
||||
"glRenderMode\0"
|
||||
"glGetError\0"
|
||||
"glGetString\0"
|
||||
"glFinish\0"
|
||||
"glFlush\0"
|
||||
"glHint\0"
|
||||
/* Depth Buffer */
|
||||
"glClearDepth\0"
|
||||
"glDepthFunc\0"
|
||||
"glDepthMask\0"
|
||||
"glDepthRange\0"
|
||||
/* Accumulation Buffer */
|
||||
"glClearAccum\0"
|
||||
"glAccum\0"
|
||||
/* Transformation */
|
||||
"glMatrixMode\0"
|
||||
"glOrtho\0"
|
||||
"glFrustum\0"
|
||||
"glViewport\0"
|
||||
"glPushMatrix\0"
|
||||
"glPopMatrix\0"
|
||||
"glLoadIdentity\0"
|
||||
"glLoadMatrixd\0"
|
||||
"glLoadMatrixf\0"
|
||||
"glMultMatrixd\0"
|
||||
"glMultMatrixf\0"
|
||||
"glRotated\0"
|
||||
"glRotatef\0"
|
||||
"glScaled\0"
|
||||
"glScalef\0"
|
||||
"glTranslated\0"
|
||||
"glTranslatef\0"
|
||||
/* Display Lists */
|
||||
"glIsList\0"
|
||||
"glDeleteLists\0"
|
||||
"glGenLists\0"
|
||||
"glNewList\0"
|
||||
"glEndList\0"
|
||||
"glCallList\0"
|
||||
"glCallLists\0"
|
||||
"glListBase\0"
|
||||
/* Drawing Functions */
|
||||
"glBegin\0"
|
||||
"glEnd\0"
|
||||
"glVertex2d\0"
|
||||
"glVertex2f\0"
|
||||
"glVertex2i\0"
|
||||
"glVertex2s\0"
|
||||
"glVertex3d\0"
|
||||
"glVertex3f\0"
|
||||
"glVertex3i\0"
|
||||
"glVertex3s\0"
|
||||
"glVertex4d\0"
|
||||
"glVertex4f\0"
|
||||
"glVertex4i\0"
|
||||
"glVertex4s\0"
|
||||
"glVertex2dv\0"
|
||||
"glVertex2fv\0"
|
||||
"glVertex2iv\0"
|
||||
"glVertex2sv\0"
|
||||
"glVertex3dv\0"
|
||||
"glVertex3fv\0"
|
||||
"glVertex3iv\0"
|
||||
"glVertex3sv\0"
|
||||
"glVertex4dv\0"
|
||||
"glVertex4fv\0"
|
||||
"glVertex4iv\0"
|
||||
"glVertex4sv\0"
|
||||
"glNormal3b\0"
|
||||
"glNormal3d\0"
|
||||
"glNormal3f\0"
|
||||
"glNormal3i\0"
|
||||
"glNormal3s\0"
|
||||
"glNormal3bv\0"
|
||||
"glNormal3dv\0"
|
||||
"glNormal3fv\0"
|
||||
"glNormal3iv\0"
|
||||
"glNormal3sv\0"
|
||||
"glIndexd\0"
|
||||
"glIndexf\0"
|
||||
"glIndexi\0"
|
||||
"glIndexs\0"
|
||||
"glIndexub\0"
|
||||
"glIndexdv\0"
|
||||
"glIndexfv\0"
|
||||
"glIndexiv\0"
|
||||
"glIndexsv\0"
|
||||
"glIndexubv\0"
|
||||
"glColor3b\0"
|
||||
"glColor3d\0"
|
||||
"glColor3f\0"
|
||||
"glColor3i\0"
|
||||
"glColor3s\0"
|
||||
"glColor3ub\0"
|
||||
"glColor3ui\0"
|
||||
"glColor3us\0"
|
||||
"glColor4b\0"
|
||||
"glColor4d\0"
|
||||
"glColor4f\0"
|
||||
"glColor4i\0"
|
||||
"glColor4s\0"
|
||||
"glColor4ub\0"
|
||||
"glColor4ui\0"
|
||||
"glColor4us\0"
|
||||
"glColor3bv\0"
|
||||
"glColor3dv\0"
|
||||
"glColor3fv\0"
|
||||
"glColor3iv\0"
|
||||
"glColor3sv\0"
|
||||
"glColor3ubv\0"
|
||||
"glColor3uiv\0"
|
||||
"glColor3usv\0"
|
||||
"glColor4bv\0"
|
||||
"glColor4dv\0"
|
||||
"glColor4fv\0"
|
||||
"glColor4iv\0"
|
||||
"glColor4sv\0"
|
||||
"glColor4ubv\0"
|
||||
"glColor4uiv\0"
|
||||
"glColor4usv\0"
|
||||
"glTexCoord1d\0"
|
||||
"glTexCoord1f\0"
|
||||
"glTexCoord1i\0"
|
||||
"glTexCoord1s\0"
|
||||
"glTexCoord2d\0"
|
||||
"glTexCoord2f\0"
|
||||
"glTexCoord2i\0"
|
||||
"glTexCoord2s\0"
|
||||
"glTexCoord3d\0"
|
||||
"glTexCoord3f\0"
|
||||
"glTexCoord3i\0"
|
||||
"glTexCoord3s\0"
|
||||
"glTexCoord4d\0"
|
||||
"glTexCoord4f\0"
|
||||
"glTexCoord4i\0"
|
||||
"glTexCoord4s\0"
|
||||
"glTexCoord1dv\0"
|
||||
"glTexCoord1fv\0"
|
||||
"glTexCoord1iv\0"
|
||||
"glTexCoord1sv\0"
|
||||
"glTexCoord2dv\0"
|
||||
"glTexCoord2fv\0"
|
||||
"glTexCoord2iv\0"
|
||||
"glTexCoord2sv\0"
|
||||
"glTexCoord3dv\0"
|
||||
"glTexCoord3fv\0"
|
||||
"glTexCoord3iv\0"
|
||||
"glTexCoord3sv\0"
|
||||
"glTexCoord4dv\0"
|
||||
"glTexCoord4fv\0"
|
||||
"glTexCoord4iv\0"
|
||||
"glTexCoord4sv\0"
|
||||
"glRasterPos2d\0"
|
||||
"glRasterPos2f\0"
|
||||
"glRasterPos2i\0"
|
||||
"glRasterPos2s\0"
|
||||
"glRasterPos3d\0"
|
||||
"glRasterPos3f\0"
|
||||
"glRasterPos3i\0"
|
||||
"glRasterPos3s\0"
|
||||
"glRasterPos4d\0"
|
||||
"glRasterPos4f\0"
|
||||
"glRasterPos4i\0"
|
||||
"glRasterPos4s\0"
|
||||
"glRasterPos2dv\0"
|
||||
"glRasterPos2fv\0"
|
||||
"glRasterPos2iv\0"
|
||||
"glRasterPos2sv\0"
|
||||
"glRasterPos3dv\0"
|
||||
"glRasterPos3fv\0"
|
||||
"glRasterPos3iv\0"
|
||||
"glRasterPos3sv\0"
|
||||
"glRasterPos4dv\0"
|
||||
"glRasterPos4fv\0"
|
||||
"glRasterPos4iv\0"
|
||||
"glRasterPos4sv\0"
|
||||
"glRectd\0"
|
||||
"glRectf\0"
|
||||
"glRecti\0"
|
||||
"glRects\0"
|
||||
"glRectdv\0"
|
||||
"glRectfv\0"
|
||||
"glRectiv\0"
|
||||
"glRectsv\0"
|
||||
/* Lighting */
|
||||
"glShadeModel\0"
|
||||
"glLightf\0"
|
||||
"glLighti\0"
|
||||
"glLightfv\0"
|
||||
"glLightiv\0"
|
||||
"glGetLightfv\0"
|
||||
"glGetLightiv\0"
|
||||
"glLightModelf\0"
|
||||
"glLightModeli\0"
|
||||
"glLightModelfv\0"
|
||||
"glLightModeliv\0"
|
||||
"glMaterialf\0"
|
||||
"glMateriali\0"
|
||||
"glMaterialfv\0"
|
||||
"glMaterialiv\0"
|
||||
"glGetMaterialfv\0"
|
||||
"glGetMaterialiv\0"
|
||||
"glColorMaterial\0"
|
||||
/* Raster functions */
|
||||
"glPixelZoom\0"
|
||||
"glPixelStoref\0"
|
||||
"glPixelStorei\0"
|
||||
"glPixelTransferf\0"
|
||||
"glPixelTransferi\0"
|
||||
"glPixelMapfv\0"
|
||||
"glPixelMapuiv\0"
|
||||
"glPixelMapusv\0"
|
||||
"glGetPixelMapfv\0"
|
||||
"glGetPixelMapuiv\0"
|
||||
"glGetPixelMapusv\0"
|
||||
"glBitmap\0"
|
||||
"glReadPixels\0"
|
||||
"glDrawPixels\0"
|
||||
"glCopyPixels\0"
|
||||
/* Stenciling */
|
||||
"glStencilFunc\0"
|
||||
"glStencilMask\0"
|
||||
"glStencilOp\0"
|
||||
"glClearStencil\0"
|
||||
/* Texture mapping */
|
||||
"glTexGend\0"
|
||||
"glTexGenf\0"
|
||||
"glTexGeni\0"
|
||||
"glTexGendv\0"
|
||||
"glTexGenfv\0"
|
||||
"glTexGeniv\0"
|
||||
"glGetTexGendv\0"
|
||||
"glGetTexGenfv\0"
|
||||
"glGetTexGeniv\0"
|
||||
"glTexEnvf\0"
|
||||
"glTexEnvi\0"
|
||||
"glTexEnvfv\0"
|
||||
"glTexEnviv\0"
|
||||
"glGetTexEnvfv\0"
|
||||
"glGetTexEnviv\0"
|
||||
"glTexParameterf\0"
|
||||
"glTexParameteri\0"
|
||||
"glTexParameterfv\0"
|
||||
"glTexParameteriv\0"
|
||||
"glGetTexParameterfv\0"
|
||||
"glGetTexParameteriv\0"
|
||||
"glGetTexLevelParameterfv\0"
|
||||
"glGetTexLevelParameteriv\0"
|
||||
"glTexImage1D\0"
|
||||
"glTexImage2D\0"
|
||||
"glGetTexImage\0"
|
||||
/* Evaluators */
|
||||
"glMap1d\0"
|
||||
"glMap1f\0"
|
||||
"glMap2d\0"
|
||||
"glMap2f\0"
|
||||
"glGetMapdv\0"
|
||||
"glGetMapfv\0"
|
||||
"glGetMapiv\0"
|
||||
"glEvalCoord1d\0"
|
||||
"glEvalCoord1f\0"
|
||||
"glEvalCoord1dv\0"
|
||||
"glEvalCoord1fv\0"
|
||||
"glEvalCoord2d\0"
|
||||
"glEvalCoord2f\0"
|
||||
"glEvalCoord2dv\0"
|
||||
"glEvalCoord2fv\0"
|
||||
"glMapGrid1d\0"
|
||||
"glMapGrid1f\0"
|
||||
"glMapGrid2d\0"
|
||||
"glMapGrid2f\0"
|
||||
"glEvalPoint1\0"
|
||||
"glEvalPoint2\0"
|
||||
"glEvalMesh1\0"
|
||||
"glEvalMesh2\0"
|
||||
/* Fog */
|
||||
"glFogf\0"
|
||||
"glFogi\0"
|
||||
"glFogfv\0"
|
||||
"glFogiv\0"
|
||||
/* Selection and Feedback */
|
||||
"glFeedbackBuffer\0"
|
||||
"glPassThrough\0"
|
||||
"glSelectBuffer\0"
|
||||
"glInitNames\0"
|
||||
"glLoadName\0"
|
||||
"glPushName\0"
|
||||
"glPopName\0"
|
||||
/* 1.1 functions */
|
||||
/* texture objects */
|
||||
"glGenTextures\0"
|
||||
"glDeleteTextures\0"
|
||||
"glBindTexture\0"
|
||||
"glPrioritizeTextures\0"
|
||||
"glAreTexturesResident\0"
|
||||
"glIsTexture\0"
|
||||
/* texture mapping */
|
||||
"glTexSubImage1D\0"
|
||||
"glTexSubImage2D\0"
|
||||
"glCopyTexImage1D\0"
|
||||
"glCopyTexImage2D\0"
|
||||
"glCopyTexSubImage1D\0"
|
||||
"glCopyTexSubImage2D\0"
|
||||
/* vertex arrays */
|
||||
"glVertexPointer\0"
|
||||
"glNormalPointer\0"
|
||||
"glColorPointer\0"
|
||||
"glIndexPointer\0"
|
||||
"glTexCoordPointer\0"
|
||||
"glEdgeFlagPointer\0"
|
||||
"glGetPointerv\0"
|
||||
"glArrayElement\0"
|
||||
"glDrawArrays\0"
|
||||
"glDrawElements\0"
|
||||
"glInterleavedArrays\0"
|
||||
/* GLX */
|
||||
"glXChooseVisual\0"
|
||||
"glXQueryExtensionsString\0"
|
||||
"glXQueryServerString\0"
|
||||
"glXGetClientString\0"
|
||||
"glXCreateContext\0"
|
||||
"glXCreateNewContext\0"
|
||||
"glXCopyContext\0"
|
||||
"glXDestroyContext\0"
|
||||
"glXQueryVersion\0"
|
||||
"glXMakeCurrent\0"
|
||||
"glXSwapBuffers\0"
|
||||
"glXGetConfig\0"
|
||||
"glXQueryExtension\0"
|
||||
"glXChooseFBConfig\0"
|
||||
"glXGetFBConfigs\0"
|
||||
"glXGetFBConfigAttrib\0"
|
||||
"glXQueryContext\0"
|
||||
"glXQueryDrawable\0"
|
||||
"glXGetVisualFromFBConfig\0"
|
||||
"glXIsDirect\0"
|
||||
"\0"
|
||||
};
|
||||
|
||||
/* Like wglGetProcAddress/glxGetProcAddress */
|
||||
void *glo_getprocaddress(const char *procName) {
|
||||
|
||||
// TODO: CGL Implementation.
|
||||
|
||||
void *procAddr = 0;
|
||||
|
||||
return procAddr;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */
|
||||
GloContext *glo_context_create(int formatFlags) {
|
||||
GloContext *context;
|
||||
|
||||
context = (GloContext*)malloc(sizeof(GloContext));
|
||||
memset(context, 0, sizeof(GloContext));
|
||||
|
||||
// pixel format attributes
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFAAccelerated,
|
||||
(CGLPixelFormatAttribute)0
|
||||
};
|
||||
|
||||
CGLPixelFormatObj pix;
|
||||
GLint num;
|
||||
CGLChoosePixelFormat(attributes, &pix, &num);
|
||||
CGLCreateContext(pix, NULL, &context->cglContext);
|
||||
CGLDestroyPixelFormat(pix);
|
||||
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
|
||||
glo_set_current(context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/* Set current context */
|
||||
void glo_set_current(GloContext *context)
|
||||
{
|
||||
if(context == NULL)
|
||||
CGLSetCurrentContext(NULL);
|
||||
else
|
||||
CGLSetCurrentContext(context->cglContext);
|
||||
}
|
||||
|
||||
/* Destroy a previously created OpenGL context */
|
||||
void glo_context_destroy(GloContext *context) {
|
||||
if (!context) return;
|
||||
glo_set_current( NULL );
|
||||
|
||||
// TODO: CGL Implementation.
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Create a surface with given width and height, formatflags are from the
|
||||
* GLO_ constants */
|
||||
GloSurface *glo_surface_create(int width, int height, GloContext *context) {
|
||||
GloSurface *surface;
|
||||
surface = (GloSurface*)malloc(sizeof(GloSurface));
|
||||
|
||||
// TODO: CGL Implementation.
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
/* Destroy the given surface */
|
||||
void glo_surface_destroy(GloSurface *surface) {
|
||||
if (!surface) return;
|
||||
// TODO: CGL Implementation.
|
||||
|
||||
}
|
||||
|
||||
/* Make the given surface current */
|
||||
int glo_surface_makecurrent(GloSurface *surface) {
|
||||
// TODO: CGL Implementation.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the contents of the given surface */
|
||||
void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *data) {
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
// Compatible / fallback method.
|
||||
glo_surface_getcontents_readpixels(surface->context->formatFlags,
|
||||
stride, bpp, surface->width,
|
||||
surface->height, data);
|
||||
// TODO: CGL Implementation.
|
||||
}
|
||||
|
||||
/* Return the width and height of the given surface */
|
||||
void glo_surface_get_size(GloSurface *surface, int *width, int *height) {
|
||||
if (width)
|
||||
*width = surface->width;
|
||||
if (height)
|
||||
*height = surface->height;
|
||||
}
|
||||
|
||||
/* Fake glXQueryExtensionsString() */
|
||||
const char *glo_glXQueryExtensionsString(void) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,360 @@
|
|||
/*
|
||||
* Offscreen OpenGL abstraction layer - Common utilities
|
||||
*
|
||||
* Copyright (c) 2010 Intel
|
||||
* Written by:
|
||||
* Gordon Williams <gordon.williams@collabora.co.uk>
|
||||
* Ian Molton <ian.molton@collabora.co.uk>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "gloffscreen.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// ---------------------------------------------------
|
||||
// Copied from glx.h as we need them in windows too
|
||||
/*
|
||||
* Tokens for glXChooseVisual and glXGetConfig:
|
||||
*/
|
||||
#define GLX_USE_GL 1
|
||||
#define GLX_BUFFER_SIZE 2
|
||||
#define GLX_LEVEL 3
|
||||
#define GLX_RGBA 4
|
||||
#define GLX_DOUBLEBUFFER 5
|
||||
#define GLX_STEREO 6
|
||||
#define GLX_AUX_BUFFERS 7
|
||||
#define GLX_RED_SIZE 8
|
||||
#define GLX_GREEN_SIZE 9
|
||||
#define GLX_BLUE_SIZE 10
|
||||
#define GLX_ALPHA_SIZE 11
|
||||
#define GLX_DEPTH_SIZE 12
|
||||
#define GLX_STENCIL_SIZE 13
|
||||
#define GLX_ACCUM_RED_SIZE 14
|
||||
#define GLX_ACCUM_GREEN_SIZE 15
|
||||
#define GLX_ACCUM_BLUE_SIZE 16
|
||||
#define GLX_ACCUM_ALPHA_SIZE 17
|
||||
// ---------------------------------------------------
|
||||
|
||||
extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, int bpp,
|
||||
int width, int height, void *data);
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
int glo_flags_get_depth_bits(int formatFlags) {
|
||||
switch ( formatFlags & GLO_FF_DEPTH_MASK ) {
|
||||
case GLO_FF_DEPTH_16: return 16;
|
||||
case GLO_FF_DEPTH_24: return 24;
|
||||
case GLO_FF_DEPTH_32: return 32;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int glo_flags_get_stencil_bits(int formatFlags) {
|
||||
switch ( formatFlags & GLO_FF_STENCIL_MASK ) {
|
||||
case GLO_FF_STENCIL_8: return 8;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void glo_flags_get_rgba_bits(int formatFlags, int *rgba) {
|
||||
int alpha = (formatFlags & GLO_FF_ALPHA) != 0;
|
||||
switch ( formatFlags & GLO_FF_BITS_MASK ) {
|
||||
case GLO_FF_BITS_16:
|
||||
rgba[0] = alpha ? 4 : 5;
|
||||
rgba[1] = alpha ? 4 : 6;
|
||||
rgba[2] = alpha ? 4 : 5;
|
||||
rgba[3] = alpha ? 4 : 0;
|
||||
break;
|
||||
case GLO_FF_BITS_24:
|
||||
// ignore alpha
|
||||
rgba[0] = 8;
|
||||
rgba[1] = 8;
|
||||
rgba[2] = 8;
|
||||
rgba[3] = 0;
|
||||
break;
|
||||
case GLO_FF_BITS_32:
|
||||
rgba[0] = 8;
|
||||
rgba[1] = 8;
|
||||
rgba[2] = 8;
|
||||
rgba[3] = 8;
|
||||
break;
|
||||
default:
|
||||
rgba[0] = 8;
|
||||
rgba[1] = 8;
|
||||
rgba[2] = 8;
|
||||
rgba[3] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int glo_flags_get_bytes_per_pixel(int formatFlags) {
|
||||
switch ( formatFlags & GLO_FF_BITS_MASK ) {
|
||||
case GLO_FF_BITS_16: return 2;
|
||||
case GLO_FF_BITS_24: return 3;
|
||||
case GLO_FF_BITS_32: return 4;
|
||||
default: return 3;
|
||||
}
|
||||
}
|
||||
|
||||
void glo_flags_get_readpixel_type(int formatFlags, int *glFormat, int *glType) {
|
||||
GLenum gFormat, gType;
|
||||
|
||||
if (formatFlags & GLO_FF_ALPHA) {
|
||||
switch ( formatFlags & GLO_FF_BITS_MASK ) {
|
||||
case GLO_FF_BITS_16:
|
||||
gFormat = GL_RGBA;
|
||||
gType = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||
break;
|
||||
case GLO_FF_BITS_24:
|
||||
case GLO_FF_BITS_32:
|
||||
default:
|
||||
gFormat = GL_BGRA;
|
||||
gType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch ( formatFlags & GLO_FF_BITS_MASK ) {
|
||||
case GLO_FF_BITS_16:
|
||||
gFormat = GL_RGB;
|
||||
gType = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case GLO_FF_BITS_24:
|
||||
case GLO_FF_BITS_32:
|
||||
default:
|
||||
gFormat = GL_BGR;
|
||||
gType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (glFormat) *glFormat = gFormat;
|
||||
if (glType) *glType = gType;
|
||||
}
|
||||
|
||||
int glo_flags_score(int formatFlagsExpected, int formatFlagsReal) {
|
||||
if (formatFlagsExpected == formatFlagsReal) return 0;
|
||||
int score = 1;
|
||||
// we wanted alpha, but we didn't get it
|
||||
if ((formatFlagsExpected&GLO_FF_ALPHA_MASK) <
|
||||
(formatFlagsReal&GLO_FF_ALPHA_MASK))
|
||||
score++;
|
||||
// less bits than we expected
|
||||
if ((formatFlagsExpected&GLO_FF_BITS_MASK) <
|
||||
!(formatFlagsReal&GLO_FF_BITS_MASK))
|
||||
score++;
|
||||
// less depth bits than we expected
|
||||
if ((formatFlagsExpected&GLO_FF_DEPTH_MASK) <
|
||||
!(formatFlagsReal&GLO_FF_DEPTH_MASK))
|
||||
score++;
|
||||
// less stencil bits than we expected
|
||||
if ((formatFlagsExpected&GLO_FF_STENCIL_MASK) <
|
||||
!(formatFlagsReal&GLO_FF_STENCIL_MASK))
|
||||
score++;
|
||||
return score;
|
||||
}
|
||||
|
||||
int glo_flags_get_from_glx(const int *fbConfig, int assumeBooleans) {
|
||||
int bufferSize = 0;
|
||||
int depthSize = 0;
|
||||
int stencilSize = 0;
|
||||
int rgbaSize[] = {0,0,0,0};
|
||||
int flags = 0;
|
||||
|
||||
while (*fbConfig) {
|
||||
int isSingle = 0;
|
||||
switch (*fbConfig) {
|
||||
case GLX_USE_GL:
|
||||
isSingle = 1;
|
||||
break;
|
||||
case GLX_BUFFER_SIZE:
|
||||
bufferSize = fbConfig[1];
|
||||
break;
|
||||
case GLX_LEVEL:
|
||||
break;
|
||||
case GLX_RGBA:
|
||||
flags |= GLO_FF_ALPHA;
|
||||
break;
|
||||
case GLX_DOUBLEBUFFER:
|
||||
isSingle = 1;
|
||||
break;
|
||||
case GLX_STEREO:
|
||||
isSingle = 1;
|
||||
break;
|
||||
case GLX_AUX_BUFFERS:
|
||||
break;
|
||||
case GLX_RED_SIZE:
|
||||
rgbaSize[0] = fbConfig[1];
|
||||
break;
|
||||
case GLX_GREEN_SIZE:
|
||||
rgbaSize[1] = fbConfig[1];
|
||||
break;
|
||||
case GLX_BLUE_SIZE:
|
||||
rgbaSize[2] = fbConfig[1];
|
||||
break;
|
||||
case GLX_ALPHA_SIZE:
|
||||
rgbaSize[3] = fbConfig[1];
|
||||
break;
|
||||
case GLX_DEPTH_SIZE:
|
||||
depthSize = fbConfig[1];
|
||||
break;
|
||||
case GLX_STENCIL_SIZE:
|
||||
stencilSize = fbConfig[1];
|
||||
break;
|
||||
case GLX_ACCUM_RED_SIZE:
|
||||
case GLX_ACCUM_GREEN_SIZE:
|
||||
case GLX_ACCUM_BLUE_SIZE:
|
||||
case GLX_ACCUM_ALPHA_SIZE:
|
||||
break;
|
||||
}
|
||||
// go to next
|
||||
if (isSingle && assumeBooleans)
|
||||
fbConfig++;
|
||||
else
|
||||
fbConfig+=2;
|
||||
}
|
||||
if (rgbaSize[3])
|
||||
flags |= GLO_FF_ALPHA;
|
||||
// ensure we have room for *some* alpha
|
||||
if ((flags & GLO_FF_ALPHA) && (rgbaSize[3]==0))
|
||||
rgbaSize[3] = 1;
|
||||
// Buffer size flag
|
||||
if (bufferSize==0)
|
||||
bufferSize = rgbaSize[0]+rgbaSize[1]+rgbaSize[2]+rgbaSize[3];
|
||||
if (bufferSize==0)
|
||||
bufferSize = (flags & GLO_FF_ALPHA) ? 32 : 24;
|
||||
if (bufferSize<=16)
|
||||
flags |= GLO_FF_BITS_16;
|
||||
else if (bufferSize<=24)
|
||||
flags |= GLO_FF_BITS_24;
|
||||
else flags |= GLO_FF_BITS_32;
|
||||
// Depth
|
||||
if (depthSize<=16)
|
||||
flags |= GLO_FF_DEPTH_16;
|
||||
else if (depthSize<=24)
|
||||
flags |= GLO_FF_DEPTH_24;
|
||||
else flags |= GLO_FF_DEPTH_32;
|
||||
// Stencil
|
||||
if (stencilSize>0)
|
||||
flags |= GLO_FF_STENCIL_8;
|
||||
return flags;
|
||||
}
|
||||
|
||||
void glo_surface_getcontents_readpixels(int formatFlags, int stride, int bpp,
|
||||
int width, int height, void *data) {
|
||||
int glFormat, glType, rl, pa;
|
||||
static int once;
|
||||
|
||||
glo_flags_get_readpixel_type(formatFlags, &glFormat, &glType);
|
||||
switch(bpp) {
|
||||
case 24:
|
||||
if(glFormat != GL_BGR) {
|
||||
if(!once) {
|
||||
fprintf(stderr, "Warning: compressing alpha\n");
|
||||
once = 1;
|
||||
}
|
||||
glFormat = GL_BGR;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
if(glFormat != GL_BGRA) {
|
||||
fprintf(stderr, "Warning: expanding alpha!\n");
|
||||
glFormat = GL_BGRA;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Warning: unsupported colourdepth\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Save guest processes GL state before we ReadPixels()
|
||||
glGetIntegerv(GL_PACK_ROW_LENGTH, &rl);
|
||||
glGetIntegerv(GL_PACK_ALIGNMENT, &pa);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
|
||||
#ifdef GETCONTENTS_INDIVIDUAL
|
||||
GLubyte *b = (GLubyte *)data;
|
||||
int irow;
|
||||
for(irow = height-1 ; irow >= 0 ; irow--) {
|
||||
glReadPixels(0, irow, width, 1, glFormat, glType, b);
|
||||
b += stride;
|
||||
}
|
||||
#else
|
||||
// Faster buffer flip
|
||||
GLubyte *b = (GLubyte *)data;
|
||||
GLubyte *c = &((GLubyte *)data)[stride*(height-1)];
|
||||
GLubyte *tmp = (GLubyte*)malloc(stride);
|
||||
int irow;
|
||||
|
||||
glReadPixels(0, 0, width, height, glFormat, glType, data);
|
||||
|
||||
for(irow = 0; irow < height/2; irow++) {
|
||||
memcpy(tmp, b, stride);
|
||||
memcpy(b, c, stride);
|
||||
memcpy(c, tmp, stride);
|
||||
b += stride;
|
||||
c -= stride;
|
||||
}
|
||||
free(tmp);
|
||||
|
||||
#endif
|
||||
|
||||
// Restore GL state
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, rl);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, pa);
|
||||
}
|
||||
|
||||
int glo_get_glx_from_flags(int formatFlags, int glxEnum) {
|
||||
int rgba[4];
|
||||
glo_flags_get_rgba_bits(formatFlags, rgba);
|
||||
|
||||
switch (glxEnum) {
|
||||
case GLX_USE_GL: return 1;
|
||||
case GLX_BUFFER_SIZE: return glo_flags_get_bytes_per_pixel(formatFlags)*8;
|
||||
case GLX_LEVEL: return 0;
|
||||
case GLX_RGBA: return formatFlags & GLO_FF_ALPHA;
|
||||
case GLX_DOUBLEBUFFER: return 1;
|
||||
case GLX_STEREO: return 0;
|
||||
case GLX_AUX_BUFFERS: return 0;
|
||||
case GLX_RED_SIZE: return rgba[0];
|
||||
case GLX_GREEN_SIZE: return rgba[1];
|
||||
case GLX_BLUE_SIZE: return rgba[2];
|
||||
case GLX_ALPHA_SIZE: return rgba[3];
|
||||
case GLX_DEPTH_SIZE: return glo_flags_get_depth_bits(formatFlags);
|
||||
case GLX_STENCIL_SIZE: return glo_flags_get_stencil_bits(formatFlags);
|
||||
case GLX_ACCUM_RED_SIZE:
|
||||
case GLX_ACCUM_GREEN_SIZE:
|
||||
case GLX_ACCUM_BLUE_SIZE:
|
||||
case GLX_ACCUM_ALPHA_SIZE:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,529 @@
|
|||
/*
|
||||
* Offscreen OpenGL abstraction layer - GLX specific
|
||||
*
|
||||
* Copyright (c) 2010 Intel
|
||||
* Written by:
|
||||
* Gordon Williams <gordon.williams@collabora.co.uk>
|
||||
* Ian Molton <ian.molton@collabora.co.uk>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#if !defined(_WIN32) || !defined(__APPLE__)
|
||||
#include "gloffscreen.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include <sys/shm.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
|
||||
struct GloMain {
|
||||
Display *dpy;
|
||||
int use_ximage;
|
||||
GloSurface *curr_surface;
|
||||
};
|
||||
struct GloMain glo;
|
||||
int glo_inited = 0;
|
||||
|
||||
struct _GloContext {
|
||||
GLuint formatFlags;
|
||||
|
||||
GLXFBConfig fbConfig;
|
||||
GLXContext context;
|
||||
};
|
||||
|
||||
struct _GloSurface {
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
|
||||
GloContext *context;
|
||||
Pixmap xPixmap;
|
||||
GLXPixmap glxPixmap;
|
||||
|
||||
// For use by the 'fast' copy code.
|
||||
XImage *image;
|
||||
XShmSegmentInfo shminfo;
|
||||
};
|
||||
|
||||
#define MAX_CTX 128
|
||||
#define MAX_SURF 128
|
||||
static GloContext *ctx_arr[MAX_CTX];
|
||||
static GloSurface *sur_arr[MAX_SURF];
|
||||
|
||||
extern void glo_surface_getcontents_readpixels(int formatFlags, int stride,
|
||||
int bpp, int width, int height, void *data);
|
||||
static void glo_test_readback_methods(void);
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
int glo_initialised(void) {
|
||||
return glo_inited;
|
||||
}
|
||||
|
||||
/* Initialise gloffscreen */
|
||||
void glo_init(void) {
|
||||
if (glo_inited) {
|
||||
printf( "gloffscreen already inited\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
/* Open a connection to the X server */
|
||||
glo.dpy = XOpenDisplay( NULL );
|
||||
if ( glo.dpy == NULL ) {
|
||||
printf( "Unable to open a connection to the X server\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
glo_inited = 1;
|
||||
glo_test_readback_methods();
|
||||
}
|
||||
|
||||
/* Uninitialise gloffscreen */
|
||||
void glo_kill(void) {
|
||||
XCloseDisplay(glo.dpy);
|
||||
glo.dpy = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Like wglGetProcAddress/glxGetProcAddress */
|
||||
void *glo_getprocaddress(const char *procName) {
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
return glXGetProcAddressARB((const GLubyte *) procName);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */
|
||||
GloContext *glo_context_create(int formatFlags, GloContext *shareLists) {
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
|
||||
GLXFBConfig *fbConfigs;
|
||||
int numReturned;
|
||||
GloContext *context;
|
||||
int rgbaBits[4];
|
||||
int bufferAttributes[] = {
|
||||
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 0,
|
||||
GLX_STENCIL_SIZE, 0,
|
||||
None
|
||||
};
|
||||
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
|
||||
// set up the surface format from the flags we were given
|
||||
glo_flags_get_rgba_bits(formatFlags, rgbaBits);
|
||||
bufferAttributes[5] = rgbaBits[0];
|
||||
bufferAttributes[7] = rgbaBits[1];
|
||||
bufferAttributes[9] = rgbaBits[2];
|
||||
bufferAttributes[11] = rgbaBits[3];
|
||||
bufferAttributes[13] = glo_flags_get_depth_bits(formatFlags);
|
||||
bufferAttributes[15] = glo_flags_get_stencil_bits(formatFlags);
|
||||
|
||||
//printf("Got R%d, G%d, B%d, A%d\n", rgbaBits[0], rgbaBits[1], rgbaBits[2], rgbaBits[3]);
|
||||
|
||||
fbConfigs = glXChooseFBConfig( glo.dpy, DefaultScreen(glo.dpy),
|
||||
bufferAttributes, &numReturned );
|
||||
if (numReturned==0) {
|
||||
printf( "No matching configs found.\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
context = (GloContext*)malloc(sizeof(GloContext));
|
||||
memset(context, 0, sizeof(GloContext));
|
||||
context->formatFlags = formatFlags;
|
||||
context->fbConfig = fbConfigs[0];
|
||||
|
||||
/* Create a GLX context for OpenGL rendering */
|
||||
context->context = glXCreateNewContext(glo.dpy, context->fbConfig,
|
||||
GLX_RGBA_TYPE,
|
||||
shareLists ? shareLists->context: NULL,
|
||||
True );
|
||||
|
||||
if (!context->context) {
|
||||
printf( "glXCreateNewContext failed\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
{
|
||||
int i;
|
||||
for(i = 0 ; i < MAX_CTX ; i++)
|
||||
if(ctx_arr[i] == NULL) {
|
||||
ctx_arr[i] = context;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Nct: %p\n", context->context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/* Destroy a previously created OpenGL context */
|
||||
void glo_context_destroy(GloContext *context) {
|
||||
{
|
||||
int i;
|
||||
if (!context) fprintf(stderr, "CTX NOT FOUND NULL\n");;
|
||||
for(i = 0 ; i < MAX_CTX ; i++)
|
||||
if(ctx_arr[i] == context) {
|
||||
ctx_arr[i] = NULL;
|
||||
break;
|
||||
}
|
||||
if(i == MAX_CTX)
|
||||
fprintf(stderr, "CTX NOT FOUND %p\n", context);
|
||||
for(i = 0 ; i < MAX_SURF ; i++)
|
||||
if(sur_arr[i])
|
||||
if(sur_arr[i]->context == context)
|
||||
fprintf(stderr, "In USE! %p\n", sur_arr[i]);
|
||||
}
|
||||
|
||||
|
||||
if (!context) return;
|
||||
// TODO: check for GloSurfaces using this?
|
||||
fprintf(stderr, "Dst: %p\n", context->context);
|
||||
glXDestroyContext( glo.dpy, context->context);
|
||||
free(context);
|
||||
}
|
||||
|
||||
static void glo_surface_free_xshm_image(GloSurface *surface) {
|
||||
XShmDetach(glo.dpy, &surface->shminfo);
|
||||
surface->image->data = NULL;
|
||||
XDestroyImage(surface->image);
|
||||
shmdt(surface->shminfo.shmaddr);
|
||||
shmctl(surface->shminfo.shmid, IPC_RMID, NULL);
|
||||
}
|
||||
|
||||
//FIXMEIM - handle failure to allocate.
|
||||
static void glo_surface_try_alloc_xshm_image(GloSurface *surface) {
|
||||
if(surface->image)
|
||||
glo_surface_free_xshm_image(surface);
|
||||
|
||||
surface->image =
|
||||
XShmCreateImage(glo.dpy, DefaultVisual(glo.dpy, 0), 24, ZPixmap, NULL,
|
||||
&surface->shminfo, surface->width, surface->height);
|
||||
surface->shminfo.shmid = shmget(IPC_PRIVATE,
|
||||
surface->image->bytes_per_line *
|
||||
surface->height,
|
||||
IPC_CREAT | 0777);
|
||||
surface->shminfo.shmaddr = shmat(surface->shminfo.shmid, NULL, 0);
|
||||
surface->image->data = surface->shminfo.shmaddr;
|
||||
surface->shminfo.readOnly = False;
|
||||
XShmAttach(glo.dpy, &surface->shminfo);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Create a surface with given width and height, formatflags are from the
|
||||
* GLO_ constants */
|
||||
GloSurface *glo_surface_create(int width, int height, GloContext *context) {
|
||||
GloSurface *surface;
|
||||
|
||||
if (!context) return 0;
|
||||
|
||||
surface = (GloSurface*)malloc(sizeof(GloSurface));
|
||||
memset(surface, 0, sizeof(GloSurface));
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->context = context;
|
||||
surface->xPixmap = XCreatePixmap( glo.dpy, DefaultRootWindow(glo.dpy),
|
||||
width, height,
|
||||
glo_flags_get_bytes_per_pixel(context->formatFlags)*8);
|
||||
|
||||
if (!surface->xPixmap) {
|
||||
printf( "XCreatePixmap failed\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
/* Create a GLX window to associate the frame buffer configuration
|
||||
** with the created X window */
|
||||
surface->glxPixmap = glXCreatePixmap( glo.dpy, context->fbConfig, surface->xPixmap, NULL );
|
||||
|
||||
fprintf(stderr, "Sct: %d %d\n", (int)surface->xPixmap, (int)surface->glxPixmap);
|
||||
|
||||
if (!surface->glxPixmap) {
|
||||
printf( "glXCreatePixmap failed\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
// If we're using XImages to pull the data from the graphics card...
|
||||
glo_surface_try_alloc_xshm_image(surface);
|
||||
{
|
||||
int i;
|
||||
for(i = 0 ; i < MAX_SURF ; i++)
|
||||
if(sur_arr[i] == NULL) {
|
||||
sur_arr[i] = surface;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
/* Destroy the given surface */
|
||||
void glo_surface_destroy(GloSurface *surface) {
|
||||
GloSurface *old = NULL;
|
||||
|
||||
if(glo.curr_surface) {
|
||||
if(surface->context != glo.curr_surface->context) {
|
||||
fprintf(stderr, "destroy_surf: %p %p %d\n", surface, surface->context, (int)surface->glxPixmap);
|
||||
old = glo.curr_surface;
|
||||
}
|
||||
}
|
||||
|
||||
glo_surface_makecurrent(surface);
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i = 0 ; i < MAX_SURF ; i++)
|
||||
if(sur_arr[i] == surface) {
|
||||
sur_arr[i] = NULL;
|
||||
break;
|
||||
}
|
||||
if(i == MAX_SURF)
|
||||
fprintf(stderr, "SURF NOT FOUND %p\n", surface);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Sdst: %d %d\n", (int)surface->xPixmap, (int)surface->glxPixmap);
|
||||
glXDestroyPixmap( glo.dpy, surface->glxPixmap);
|
||||
XFreePixmap( glo.dpy, surface->xPixmap);
|
||||
if(surface->image)
|
||||
glo_surface_free_xshm_image(surface);
|
||||
free(surface);
|
||||
|
||||
// glo_surface_makecurrent(old);
|
||||
}
|
||||
|
||||
/* Make the given surface current */
|
||||
int glo_surface_makecurrent(GloSurface *surface) {
|
||||
int ret;
|
||||
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
|
||||
if (surface) {
|
||||
{
|
||||
int i;
|
||||
for(i = 0 ; i < MAX_CTX ; i++) {
|
||||
if(ctx_arr[i] == surface->context)
|
||||
break;
|
||||
}
|
||||
if(i == MAX_CTX)
|
||||
fprintf(stderr, "CTX unknown %p\n", surface->context);
|
||||
|
||||
for(i = 0 ; i < MAX_SURF ; i++) {
|
||||
if(surface == sur_arr[i])
|
||||
break;
|
||||
}
|
||||
if(i == MAX_SURF)
|
||||
fprintf(stderr, "SURFACE unknown %p\n", surface);
|
||||
}
|
||||
|
||||
ret = glXMakeCurrent(glo.dpy, surface->glxPixmap, surface->context->context);
|
||||
glo.curr_surface = surface;
|
||||
} else {
|
||||
glo.curr_surface = NULL;
|
||||
ret = glXMakeCurrent(glo.dpy, 0, NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
#define geti(a) \
|
||||
do { \
|
||||
int b; \
|
||||
glGetIntegerv(a, &b); \
|
||||
fprintf(stderr, "%s: %d\n", #a, b); \
|
||||
} while (0);
|
||||
*/
|
||||
|
||||
/* Get the contents of the given surface */
|
||||
void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *data) {
|
||||
static int once;
|
||||
XImage *img;
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
if(glo.use_ximage) {
|
||||
glXWaitGL();
|
||||
|
||||
if(surface->image) {
|
||||
XShmGetImage (glo.dpy, surface->xPixmap, surface->image, 0, 0, AllPlanes);
|
||||
img = surface->image;
|
||||
}
|
||||
else {
|
||||
img = XGetImage(glo.dpy, surface->xPixmap, 0, 0, surface->width, surface->height, AllPlanes, ZPixmap);
|
||||
}
|
||||
|
||||
if (img) {
|
||||
if(bpp != 32 && bpp != 24 && !once) {
|
||||
fprintf(stderr, "Warning: unsupported colourdepth\n");
|
||||
once = 1;
|
||||
}
|
||||
|
||||
if(bpp == img->bits_per_pixel && stride == img->bytes_per_line)
|
||||
{
|
||||
memcpy(data, img->data, stride * surface->height);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x, y;
|
||||
for(y = 0 ; y < surface->height ; y++) {
|
||||
for(x = 0 ; x < surface->width ; x++) {
|
||||
char *src = ((char*)img->data) + (x*(img->bits_per_pixel/8)) + (y*img->bytes_per_line);
|
||||
char *dst = ((char*)data) + x*(bpp/8) + (y*stride);
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
if(bpp == 32)
|
||||
dst[3] = 0xff; // if guest is 32 bit and host is 24
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're not using Shm
|
||||
if(!surface->image)
|
||||
XDestroyImage(img);
|
||||
|
||||
return; // We're done.
|
||||
}
|
||||
// Uh oh... better fallback. Perhaps get glo.use_ximage to 0?
|
||||
}
|
||||
|
||||
// Compatible / fallback method.
|
||||
glo_surface_getcontents_readpixels(surface->context->formatFlags,
|
||||
stride, bpp, surface->width,
|
||||
surface->height, data);
|
||||
}
|
||||
|
||||
// while(0) {
|
||||
// char fname[30];
|
||||
// int y;
|
||||
// sprintf(fname, "dbg_%08x_%dx%d.rgb", surface, surface->width, surface->height);
|
||||
// FILE *d = fopen(fname, "wb");
|
||||
// for(y = 0 ; y < surface->height ; y++)
|
||||
// fwrite(data + (y*stride), surface->width*3, 1, d);
|
||||
// fclose(d);
|
||||
// }
|
||||
|
||||
/* Return the width and height of the given surface */
|
||||
void glo_surface_get_size(GloSurface *surface, int *width, int *height) {
|
||||
if (width)
|
||||
*width = surface->width;
|
||||
if (height)
|
||||
*height = surface->height;
|
||||
}
|
||||
|
||||
/* Abstract glXQueryExtensionString() */
|
||||
const char *glo_glXQueryExtensionsString(void) {
|
||||
return glXQueryExtensionsString(glo.dpy, 0);
|
||||
}
|
||||
|
||||
|
||||
#define TX (17)
|
||||
#define TY (16)
|
||||
|
||||
static int glo_can_readback(void) {
|
||||
GloContext *context;
|
||||
GloSurface *surface;
|
||||
|
||||
unsigned char *datain = (unsigned char *)malloc(4*TX*TY);
|
||||
unsigned char *datain_flip = (unsigned char *)malloc(4*TX*TY); // flipped input data (for GL)
|
||||
unsigned char *dataout = (unsigned char *)malloc(4*TX*TY);
|
||||
unsigned char *p;
|
||||
int x,y;
|
||||
|
||||
const int bufferAttributes[] = {
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 0,
|
||||
GLX_STENCIL_SIZE, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
int bufferFlags = glo_flags_get_from_glx(bufferAttributes, 0);
|
||||
int bpp = glo_flags_get_bytes_per_pixel(bufferFlags);
|
||||
int glFormat, glType;
|
||||
|
||||
memset(datain_flip, 0, TX*TY*4);
|
||||
memset(datain, 0, TX*TY*4);
|
||||
|
||||
p = datain;
|
||||
for (y=0;y<TY;y++) {
|
||||
for (x=0;x<TX;x++) {
|
||||
p[0] = x;
|
||||
p[1] = y;
|
||||
//if (y&1) { p[0]=0; p[1]=0; }
|
||||
if (bpp>2) p[2] = 0;
|
||||
if (bpp>3) p[3] = 0xFF;
|
||||
p+=bpp;
|
||||
}
|
||||
memcpy(&datain_flip[((TY-1)-y)*bpp*TX], &datain[y*bpp*TX], bpp*TX);
|
||||
}
|
||||
|
||||
context = glo_context_create(bufferFlags, 0);
|
||||
surface = glo_surface_create(TX, TY, context);
|
||||
|
||||
glo_surface_makecurrent(surface);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0,TX, 0,TY, 0, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glRasterPos2f(0,0);
|
||||
glo_flags_get_readpixel_type(bufferFlags, &glFormat, &glType);
|
||||
glDrawPixels(TX,TY,glFormat, glType, datain_flip);
|
||||
glFlush();
|
||||
|
||||
memset(dataout, 0, bpp*TX*TY);
|
||||
|
||||
glo_surface_getcontents(surface, TX*4, bpp*8, dataout);
|
||||
|
||||
glo_surface_destroy(surface);
|
||||
glo_context_destroy(context);
|
||||
|
||||
if (memcmp(datain, dataout, bpp*TX*TY)==0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void glo_test_readback_methods(void) {
|
||||
glo.use_ximage = 1;
|
||||
if(!glo_can_readback())
|
||||
glo.use_ximage = 0;
|
||||
|
||||
fprintf(stderr, "VM GL: Using %s readback\n", glo.use_ximage?"XImage":"glReadPixels");
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,814 @@
|
|||
/*
|
||||
* Offscreen OpenGL abstraction layer - WGL (windows) specific
|
||||
*
|
||||
* Copyright (c) 2010 Intel
|
||||
* Written by:
|
||||
* Gordon Williams <gordon.williams@collabora.co.uk>
|
||||
* Ian Molton <ian.molton@collabora.co.uk>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <wingdi.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/wglext.h>
|
||||
#include <GL/glut.h>
|
||||
#include "gloffscreen.h"
|
||||
|
||||
/* In Windows, you must create a window *before* you can create a pbuffer or
|
||||
* get a context. So we create a hidden Window on startup (see glo_init/GloMain).
|
||||
*
|
||||
* Also, you can't share contexts that have different pixel formats, so we can't just
|
||||
* create a new context from the window. We must create a whole new PBuffer just for
|
||||
* a context :(
|
||||
*/
|
||||
|
||||
struct GloMain {
|
||||
HINSTANCE hInstance;
|
||||
HDC hDC;
|
||||
HWND hWnd; /* Our hidden window */
|
||||
HGLRC hContext;
|
||||
};
|
||||
struct GloMain glo;
|
||||
int glo_inited = 0;
|
||||
|
||||
struct _GloContext {
|
||||
int formatFlags;
|
||||
|
||||
/* Pixel format returned by wglChoosePixelFormat */
|
||||
int wglPixelFormat;
|
||||
/* We need a pbuffer to make a context of the right pixelformat :( */
|
||||
HPBUFFERARB hPBuffer;
|
||||
HDC hDC;
|
||||
HGLRC hContext;
|
||||
};
|
||||
|
||||
struct _GloSurface {
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
|
||||
GloContext *context;
|
||||
HPBUFFERARB hPBuffer;
|
||||
HDC hDC;
|
||||
};
|
||||
|
||||
#define GLO_WINDOW_CLASS "QEmuGLClass"
|
||||
#define DEFAULT_DEPTH_BUFFER (16)
|
||||
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
|
||||
PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB;
|
||||
PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB;
|
||||
PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB;
|
||||
PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB;
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
//extern const char *glo_glXQueryExtensionsString(void);
|
||||
|
||||
extern void glo_surface_getcontents_readpixels(int formatFlags, int stride,
|
||||
int bpp, int width, int height, void *data);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
int glo_initialised(void) {
|
||||
return glo_inited;
|
||||
}
|
||||
|
||||
/* Initialise gloffscreen */
|
||||
void glo_init(void) {
|
||||
WNDCLASSEX wcx;
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
||||
if (glo_inited) {
|
||||
printf( "gloffscreen already inited\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
glo.hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
|
||||
|
||||
wcx.cbSize = sizeof(wcx);
|
||||
wcx.style = 0;
|
||||
wcx.lpfnWndProc = DefWindowProc;
|
||||
wcx.cbClsExtra = 0;
|
||||
wcx.cbWndExtra = 0;
|
||||
wcx.hInstance = glo.hInstance;
|
||||
wcx.hIcon = NULL;
|
||||
wcx.hCursor = NULL;
|
||||
wcx.hbrBackground = NULL;
|
||||
wcx.lpszMenuName = NULL;
|
||||
wcx.lpszClassName = GLO_WINDOW_CLASS;
|
||||
wcx.hIconSm = NULL;
|
||||
RegisterClassEx(&wcx);
|
||||
glo.hWnd = CreateWindow(
|
||||
GLO_WINDOW_CLASS,
|
||||
"QEmuGL",
|
||||
0,0,0,0,0,
|
||||
(HWND)NULL, (HMENU)NULL,
|
||||
glo.hInstance,
|
||||
(LPVOID) NULL);
|
||||
|
||||
if (!glo.hWnd) {
|
||||
printf( "Unable to create window\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
glo.hDC = GetDC(glo.hWnd);
|
||||
|
||||
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
pfd.iLayerType = PFD_MAIN_PLANE;
|
||||
unsigned int pixelFormat = ChoosePixelFormat(glo.hDC, &pfd);
|
||||
DescribePixelFormat(glo.hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
|
||||
if (!SetPixelFormat(glo.hDC, pixelFormat, &pfd))
|
||||
return;
|
||||
|
||||
glo.hContext = wglCreateContext(glo.hDC);
|
||||
if (glo.hContext == NULL) {
|
||||
printf( "Unable to create GL context\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
wglMakeCurrent(glo.hDC, glo.hContext);
|
||||
|
||||
// FIXME GW
|
||||
// Need to share lists AND copy state
|
||||
|
||||
// load in the extensions we need
|
||||
//const char *ext = wglGetExtensionsStringARB(hdc);
|
||||
//"WGL_ARB_pixel_format" "WGL_ARB_pbuffer"
|
||||
|
||||
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)wglGetProcAddress("wglGetPbufferDCARB");
|
||||
wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)wglGetProcAddress("wglReleasePbufferDCARB");
|
||||
wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)wglGetProcAddress("wglCreatePbufferARB");
|
||||
wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)wglGetProcAddress("wglDestroyPbufferARB");
|
||||
|
||||
if (!wglChoosePixelFormatARB ||
|
||||
!wglGetPbufferDCARB ||
|
||||
!wglReleasePbufferDCARB ||
|
||||
!wglCreatePbufferARB ||
|
||||
!wglDestroyPbufferARB) {
|
||||
printf( "Unable to load the required WGL extensions\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
// Initialize glew
|
||||
if (GLEW_OK != glewInit())
|
||||
{
|
||||
// GLEW failed!
|
||||
printf("Glew init failed.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glo_inited = 1;
|
||||
}
|
||||
|
||||
/* Uninitialise gloffscreen */
|
||||
void glo_kill(void) {
|
||||
if (glo.hContext) {
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(glo.hContext);
|
||||
glo.hContext = NULL;
|
||||
}
|
||||
if (glo.hDC) {
|
||||
ReleaseDC(glo.hWnd, glo.hDC);
|
||||
glo.hDC = NULL;
|
||||
}
|
||||
if (glo.hWnd) {
|
||||
DestroyWindow(glo.hWnd);
|
||||
glo.hWnd = NULL;
|
||||
}
|
||||
UnregisterClass(GLO_WINDOW_CLASS, glo.hInstance);
|
||||
}
|
||||
|
||||
|
||||
static const char *STANDARD_GL_FUNCTIONS ={
|
||||
/* Miscellaneous */
|
||||
"glClearIndex\0"
|
||||
"glClearColor\0"
|
||||
"glClear\0"
|
||||
"glIndexMask\0"
|
||||
"glColorMask\0"
|
||||
"glAlphaFunc\0"
|
||||
"glBlendFunc\0"
|
||||
"glLogicOp\0"
|
||||
"glCullFace\0"
|
||||
"glFrontFace\0"
|
||||
"glPointSize\0"
|
||||
"glLineWidth\0"
|
||||
"glLineStipple\0"
|
||||
"glPolygonMode\0"
|
||||
"glPolygonOffset\0"
|
||||
"glPolygonStipple\0"
|
||||
"glGetPolygonStipple\0"
|
||||
"glEdgeFlag\0"
|
||||
"glEdgeFlagv\0"
|
||||
"glScissor\0"
|
||||
"glClipPlane\0"
|
||||
"glGetClipPlane\0"
|
||||
"glDrawBuffer\0"
|
||||
"glReadBuffer\0"
|
||||
"glEnable\0"
|
||||
"glDisable\0"
|
||||
"glIsEnabled\0"
|
||||
"glEnableClientState\0"
|
||||
"glDisableClientState\0"
|
||||
"glGetBooleanv\0"
|
||||
"glGetDoublev\0"
|
||||
"glGetFloatv\0"
|
||||
"glGetIntegerv\0"
|
||||
"glPushAttrib\0"
|
||||
"glPopAttrib\0"
|
||||
"glPushClientAttrib\0"
|
||||
"glPopClientAttrib\0"
|
||||
"glRenderMode\0"
|
||||
"glGetError\0"
|
||||
"glGetString\0"
|
||||
"glFinish\0"
|
||||
"glFlush\0"
|
||||
"glHint\0"
|
||||
/* Depth Buffer */
|
||||
"glClearDepth\0"
|
||||
"glDepthFunc\0"
|
||||
"glDepthMask\0"
|
||||
"glDepthRange\0"
|
||||
/* Accumulation Buffer */
|
||||
"glClearAccum\0"
|
||||
"glAccum\0"
|
||||
/* Transformation */
|
||||
"glMatrixMode\0"
|
||||
"glOrtho\0"
|
||||
"glFrustum\0"
|
||||
"glViewport\0"
|
||||
"glPushMatrix\0"
|
||||
"glPopMatrix\0"
|
||||
"glLoadIdentity\0"
|
||||
"glLoadMatrixd\0"
|
||||
"glLoadMatrixf\0"
|
||||
"glMultMatrixd\0"
|
||||
"glMultMatrixf\0"
|
||||
"glRotated\0"
|
||||
"glRotatef\0"
|
||||
"glScaled\0"
|
||||
"glScalef\0"
|
||||
"glTranslated\0"
|
||||
"glTranslatef\0"
|
||||
/* Display Lists */
|
||||
"glIsList\0"
|
||||
"glDeleteLists\0"
|
||||
"glGenLists\0"
|
||||
"glNewList\0"
|
||||
"glEndList\0"
|
||||
"glCallList\0"
|
||||
"glCallLists\0"
|
||||
"glListBase\0"
|
||||
/* Drawing Functions */
|
||||
"glBegin\0"
|
||||
"glEnd\0"
|
||||
"glVertex2d\0"
|
||||
"glVertex2f\0"
|
||||
"glVertex2i\0"
|
||||
"glVertex2s\0"
|
||||
"glVertex3d\0"
|
||||
"glVertex3f\0"
|
||||
"glVertex3i\0"
|
||||
"glVertex3s\0"
|
||||
"glVertex4d\0"
|
||||
"glVertex4f\0"
|
||||
"glVertex4i\0"
|
||||
"glVertex4s\0"
|
||||
"glVertex2dv\0"
|
||||
"glVertex2fv\0"
|
||||
"glVertex2iv\0"
|
||||
"glVertex2sv\0"
|
||||
"glVertex3dv\0"
|
||||
"glVertex3fv\0"
|
||||
"glVertex3iv\0"
|
||||
"glVertex3sv\0"
|
||||
"glVertex4dv\0"
|
||||
"glVertex4fv\0"
|
||||
"glVertex4iv\0"
|
||||
"glVertex4sv\0"
|
||||
"glNormal3b\0"
|
||||
"glNormal3d\0"
|
||||
"glNormal3f\0"
|
||||
"glNormal3i\0"
|
||||
"glNormal3s\0"
|
||||
"glNormal3bv\0"
|
||||
"glNormal3dv\0"
|
||||
"glNormal3fv\0"
|
||||
"glNormal3iv\0"
|
||||
"glNormal3sv\0"
|
||||
"glIndexd\0"
|
||||
"glIndexf\0"
|
||||
"glIndexi\0"
|
||||
"glIndexs\0"
|
||||
"glIndexub\0"
|
||||
"glIndexdv\0"
|
||||
"glIndexfv\0"
|
||||
"glIndexiv\0"
|
||||
"glIndexsv\0"
|
||||
"glIndexubv\0"
|
||||
"glColor3b\0"
|
||||
"glColor3d\0"
|
||||
"glColor3f\0"
|
||||
"glColor3i\0"
|
||||
"glColor3s\0"
|
||||
"glColor3ub\0"
|
||||
"glColor3ui\0"
|
||||
"glColor3us\0"
|
||||
"glColor4b\0"
|
||||
"glColor4d\0"
|
||||
"glColor4f\0"
|
||||
"glColor4i\0"
|
||||
"glColor4s\0"
|
||||
"glColor4ub\0"
|
||||
"glColor4ui\0"
|
||||
"glColor4us\0"
|
||||
"glColor3bv\0"
|
||||
"glColor3dv\0"
|
||||
"glColor3fv\0"
|
||||
"glColor3iv\0"
|
||||
"glColor3sv\0"
|
||||
"glColor3ubv\0"
|
||||
"glColor3uiv\0"
|
||||
"glColor3usv\0"
|
||||
"glColor4bv\0"
|
||||
"glColor4dv\0"
|
||||
"glColor4fv\0"
|
||||
"glColor4iv\0"
|
||||
"glColor4sv\0"
|
||||
"glColor4ubv\0"
|
||||
"glColor4uiv\0"
|
||||
"glColor4usv\0"
|
||||
"glTexCoord1d\0"
|
||||
"glTexCoord1f\0"
|
||||
"glTexCoord1i\0"
|
||||
"glTexCoord1s\0"
|
||||
"glTexCoord2d\0"
|
||||
"glTexCoord2f\0"
|
||||
"glTexCoord2i\0"
|
||||
"glTexCoord2s\0"
|
||||
"glTexCoord3d\0"
|
||||
"glTexCoord3f\0"
|
||||
"glTexCoord3i\0"
|
||||
"glTexCoord3s\0"
|
||||
"glTexCoord4d\0"
|
||||
"glTexCoord4f\0"
|
||||
"glTexCoord4i\0"
|
||||
"glTexCoord4s\0"
|
||||
"glTexCoord1dv\0"
|
||||
"glTexCoord1fv\0"
|
||||
"glTexCoord1iv\0"
|
||||
"glTexCoord1sv\0"
|
||||
"glTexCoord2dv\0"
|
||||
"glTexCoord2fv\0"
|
||||
"glTexCoord2iv\0"
|
||||
"glTexCoord2sv\0"
|
||||
"glTexCoord3dv\0"
|
||||
"glTexCoord3fv\0"
|
||||
"glTexCoord3iv\0"
|
||||
"glTexCoord3sv\0"
|
||||
"glTexCoord4dv\0"
|
||||
"glTexCoord4fv\0"
|
||||
"glTexCoord4iv\0"
|
||||
"glTexCoord4sv\0"
|
||||
"glRasterPos2d\0"
|
||||
"glRasterPos2f\0"
|
||||
"glRasterPos2i\0"
|
||||
"glRasterPos2s\0"
|
||||
"glRasterPos3d\0"
|
||||
"glRasterPos3f\0"
|
||||
"glRasterPos3i\0"
|
||||
"glRasterPos3s\0"
|
||||
"glRasterPos4d\0"
|
||||
"glRasterPos4f\0"
|
||||
"glRasterPos4i\0"
|
||||
"glRasterPos4s\0"
|
||||
"glRasterPos2dv\0"
|
||||
"glRasterPos2fv\0"
|
||||
"glRasterPos2iv\0"
|
||||
"glRasterPos2sv\0"
|
||||
"glRasterPos3dv\0"
|
||||
"glRasterPos3fv\0"
|
||||
"glRasterPos3iv\0"
|
||||
"glRasterPos3sv\0"
|
||||
"glRasterPos4dv\0"
|
||||
"glRasterPos4fv\0"
|
||||
"glRasterPos4iv\0"
|
||||
"glRasterPos4sv\0"
|
||||
"glRectd\0"
|
||||
"glRectf\0"
|
||||
"glRecti\0"
|
||||
"glRects\0"
|
||||
"glRectdv\0"
|
||||
"glRectfv\0"
|
||||
"glRectiv\0"
|
||||
"glRectsv\0"
|
||||
/* Lighting */
|
||||
"glShadeModel\0"
|
||||
"glLightf\0"
|
||||
"glLighti\0"
|
||||
"glLightfv\0"
|
||||
"glLightiv\0"
|
||||
"glGetLightfv\0"
|
||||
"glGetLightiv\0"
|
||||
"glLightModelf\0"
|
||||
"glLightModeli\0"
|
||||
"glLightModelfv\0"
|
||||
"glLightModeliv\0"
|
||||
"glMaterialf\0"
|
||||
"glMateriali\0"
|
||||
"glMaterialfv\0"
|
||||
"glMaterialiv\0"
|
||||
"glGetMaterialfv\0"
|
||||
"glGetMaterialiv\0"
|
||||
"glColorMaterial\0"
|
||||
/* Raster functions */
|
||||
"glPixelZoom\0"
|
||||
"glPixelStoref\0"
|
||||
"glPixelStorei\0"
|
||||
"glPixelTransferf\0"
|
||||
"glPixelTransferi\0"
|
||||
"glPixelMapfv\0"
|
||||
"glPixelMapuiv\0"
|
||||
"glPixelMapusv\0"
|
||||
"glGetPixelMapfv\0"
|
||||
"glGetPixelMapuiv\0"
|
||||
"glGetPixelMapusv\0"
|
||||
"glBitmap\0"
|
||||
"glReadPixels\0"
|
||||
"glDrawPixels\0"
|
||||
"glCopyPixels\0"
|
||||
/* Stenciling */
|
||||
"glStencilFunc\0"
|
||||
"glStencilMask\0"
|
||||
"glStencilOp\0"
|
||||
"glClearStencil\0"
|
||||
/* Texture mapping */
|
||||
"glTexGend\0"
|
||||
"glTexGenf\0"
|
||||
"glTexGeni\0"
|
||||
"glTexGendv\0"
|
||||
"glTexGenfv\0"
|
||||
"glTexGeniv\0"
|
||||
"glGetTexGendv\0"
|
||||
"glGetTexGenfv\0"
|
||||
"glGetTexGeniv\0"
|
||||
"glTexEnvf\0"
|
||||
"glTexEnvi\0"
|
||||
"glTexEnvfv\0"
|
||||
"glTexEnviv\0"
|
||||
"glGetTexEnvfv\0"
|
||||
"glGetTexEnviv\0"
|
||||
"glTexParameterf\0"
|
||||
"glTexParameteri\0"
|
||||
"glTexParameterfv\0"
|
||||
"glTexParameteriv\0"
|
||||
"glGetTexParameterfv\0"
|
||||
"glGetTexParameteriv\0"
|
||||
"glGetTexLevelParameterfv\0"
|
||||
"glGetTexLevelParameteriv\0"
|
||||
"glTexImage1D\0"
|
||||
"glTexImage2D\0"
|
||||
"glGetTexImage\0"
|
||||
/* Evaluators */
|
||||
"glMap1d\0"
|
||||
"glMap1f\0"
|
||||
"glMap2d\0"
|
||||
"glMap2f\0"
|
||||
"glGetMapdv\0"
|
||||
"glGetMapfv\0"
|
||||
"glGetMapiv\0"
|
||||
"glEvalCoord1d\0"
|
||||
"glEvalCoord1f\0"
|
||||
"glEvalCoord1dv\0"
|
||||
"glEvalCoord1fv\0"
|
||||
"glEvalCoord2d\0"
|
||||
"glEvalCoord2f\0"
|
||||
"glEvalCoord2dv\0"
|
||||
"glEvalCoord2fv\0"
|
||||
"glMapGrid1d\0"
|
||||
"glMapGrid1f\0"
|
||||
"glMapGrid2d\0"
|
||||
"glMapGrid2f\0"
|
||||
"glEvalPoint1\0"
|
||||
"glEvalPoint2\0"
|
||||
"glEvalMesh1\0"
|
||||
"glEvalMesh2\0"
|
||||
/* Fog */
|
||||
"glFogf\0"
|
||||
"glFogi\0"
|
||||
"glFogfv\0"
|
||||
"glFogiv\0"
|
||||
/* Selection and Feedback */
|
||||
"glFeedbackBuffer\0"
|
||||
"glPassThrough\0"
|
||||
"glSelectBuffer\0"
|
||||
"glInitNames\0"
|
||||
"glLoadName\0"
|
||||
"glPushName\0"
|
||||
"glPopName\0"
|
||||
/* 1.1 functions */
|
||||
/* texture objects */
|
||||
"glGenTextures\0"
|
||||
"glDeleteTextures\0"
|
||||
"glBindTexture\0"
|
||||
"glPrioritizeTextures\0"
|
||||
"glAreTexturesResident\0"
|
||||
"glIsTexture\0"
|
||||
/* texture mapping */
|
||||
"glTexSubImage1D\0"
|
||||
"glTexSubImage2D\0"
|
||||
"glCopyTexImage1D\0"
|
||||
"glCopyTexImage2D\0"
|
||||
"glCopyTexSubImage1D\0"
|
||||
"glCopyTexSubImage2D\0"
|
||||
/* vertex arrays */
|
||||
"glVertexPointer\0"
|
||||
"glNormalPointer\0"
|
||||
"glColorPointer\0"
|
||||
"glIndexPointer\0"
|
||||
"glTexCoordPointer\0"
|
||||
"glEdgeFlagPointer\0"
|
||||
"glGetPointerv\0"
|
||||
"glArrayElement\0"
|
||||
"glDrawArrays\0"
|
||||
"glDrawElements\0"
|
||||
"glInterleavedArrays\0"
|
||||
/* GLX */
|
||||
"glXChooseVisual\0"
|
||||
"glXQueryExtensionsString\0"
|
||||
"glXQueryServerString\0"
|
||||
"glXGetClientString\0"
|
||||
"glXCreateContext\0"
|
||||
"glXCreateNewContext\0"
|
||||
"glXCopyContext\0"
|
||||
"glXDestroyContext\0"
|
||||
"glXQueryVersion\0"
|
||||
"glXMakeCurrent\0"
|
||||
"glXSwapBuffers\0"
|
||||
"glXGetConfig\0"
|
||||
"glXQueryExtension\0"
|
||||
"glXChooseFBConfig\0"
|
||||
"glXGetFBConfigs\0"
|
||||
"glXGetFBConfigAttrib\0"
|
||||
"glXQueryContext\0"
|
||||
"glXQueryDrawable\0"
|
||||
"glXGetVisualFromFBConfig\0"
|
||||
"glXIsDirect\0"
|
||||
"\0"
|
||||
};
|
||||
|
||||
/* Like wglGetProcAddress/glxGetProcAddress */
|
||||
void *glo_getprocaddress(const char *procName) {
|
||||
HGLRC oldCtx;
|
||||
HDC oldDC;
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
|
||||
oldCtx = wglGetCurrentContext();
|
||||
oldDC = wglGetCurrentDC();
|
||||
if (oldDC!=glo.hDC || oldCtx!=glo.hContext)
|
||||
wglMakeCurrent(glo.hDC, glo.hContext);
|
||||
|
||||
void *procAddr = wglGetProcAddress(procName);
|
||||
|
||||
if (oldDC!=glo.hDC || oldCtx!=glo.hContext)
|
||||
wglMakeCurrent(oldDC, oldCtx);
|
||||
|
||||
/* wgl doesn't know about the glx functions - but
|
||||
we never call these anyway (they're implemented in
|
||||
opengl_exec), so all we need to do is return a nunzero value...
|
||||
|
||||
But we also have to check for 'standard' GL function names
|
||||
too as wgl doesn't return those either! */
|
||||
if (procAddr==0) {
|
||||
const char *p = STANDARD_GL_FUNCTIONS;
|
||||
while (*p) {
|
||||
if (!strcmp(procName, p)) {
|
||||
procAddr = (void*)1;
|
||||
break;
|
||||
}
|
||||
// skip to the next '0' and then just over it
|
||||
while (*p) p++;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*printf("wglGetProcAddress '%s' -> %p\n", procName, procAddr);
|
||||
fflush(stdout);*/
|
||||
|
||||
return procAddr;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */
|
||||
GloContext *glo_context_create(int formatFlags) {
|
||||
GloContext *context;
|
||||
// pixel format attributes
|
||||
int pf_attri[] = {
|
||||
WGL_SUPPORT_OPENGL_ARB, TRUE,
|
||||
WGL_DRAW_TO_PBUFFER_ARB, TRUE,
|
||||
WGL_RED_BITS_ARB, 8,
|
||||
WGL_GREEN_BITS_ARB, 8,
|
||||
WGL_BLUE_BITS_ARB, 8,
|
||||
WGL_ALPHA_BITS_ARB, 8,
|
||||
WGL_DEPTH_BITS_ARB, 0,
|
||||
WGL_STENCIL_BITS_ARB, 0,
|
||||
WGL_DOUBLE_BUFFER_ARB, FALSE,
|
||||
0
|
||||
};
|
||||
float pf_attrf[] = {0, 0};
|
||||
unsigned int numReturned = 0;
|
||||
int pb_attr[] = { 0 };
|
||||
int rgbaBits[4];
|
||||
|
||||
|
||||
if (!glo_inited)
|
||||
glo_init();
|
||||
|
||||
context = (GloContext*)malloc(sizeof(GloContext));
|
||||
memset(context, 0, sizeof(GloContext));
|
||||
context->formatFlags = formatFlags;
|
||||
|
||||
// set up the surface format from the flags we were given
|
||||
glo_flags_get_rgba_bits(context->formatFlags, rgbaBits);
|
||||
pf_attri[5] = rgbaBits[0];
|
||||
pf_attri[7] = rgbaBits[1];
|
||||
pf_attri[9] = rgbaBits[2];
|
||||
pf_attri[11] = rgbaBits[3];
|
||||
pf_attri[13] = glo_flags_get_depth_bits(context->formatFlags);
|
||||
pf_attri[15] = glo_flags_get_stencil_bits(context->formatFlags);
|
||||
|
||||
// find out what pixel format to use
|
||||
wglChoosePixelFormatARB( glo.hDC, pf_attri, pf_attrf, 1, &context->wglPixelFormat, &numReturned);
|
||||
if( numReturned == 0 ) {
|
||||
printf( "No matching configs found.\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
// We create a tiny pbuffer - just so we can make a context of the right pixel format
|
||||
context->hPBuffer = wglCreatePbufferARB( glo.hDC, context->wglPixelFormat,
|
||||
16, 16, pb_attr );
|
||||
if( !context->hPBuffer ) {
|
||||
printf( "Couldn't create the PBuffer\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
context->hDC = wglGetPbufferDCARB( context->hPBuffer );
|
||||
if( !context->hDC ) {
|
||||
printf( "Couldn't create the DC\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
context->hContext = wglCreateContext(context->hDC);
|
||||
if (context->hContext == NULL) {
|
||||
printf( "Unable to create GL context\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
/*
|
||||
if (shareLists) {
|
||||
// Need to share lists...
|
||||
wglShareLists(shareLists->hContext, context->hContext);
|
||||
}
|
||||
*/
|
||||
glo_set_current(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
/* Set current context */
|
||||
void glo_set_current(GloContext *context)
|
||||
{
|
||||
if(context == NULL)
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
else
|
||||
wglMakeCurrent(context->hDC, context->hContext);
|
||||
}
|
||||
|
||||
/* Destroy a previously created OpenGL context */
|
||||
void glo_context_destroy(GloContext *context) {
|
||||
if (!context) return;
|
||||
|
||||
wglMakeCurrent( NULL, NULL );
|
||||
if( context->hPBuffer != NULL ) {
|
||||
wglReleasePbufferDCARB( context->hPBuffer, context->hDC );
|
||||
wglDestroyPbufferARB( context->hPBuffer );
|
||||
}
|
||||
if( context->hDC != NULL ) {
|
||||
ReleaseDC( glo.hWnd, context->hDC );
|
||||
}
|
||||
if (context->hContext) {
|
||||
wglDeleteContext(context->hContext);
|
||||
}
|
||||
free(context);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Create a surface with given width and height, formatflags are from the
|
||||
* GLO_ constants */
|
||||
GloSurface *glo_surface_create(int width, int height, GloContext *context) {
|
||||
GloSurface *surface;
|
||||
int pb_attr[] = { 0 };
|
||||
|
||||
// Create the p-buffer...
|
||||
surface = (GloSurface*)malloc(sizeof(GloSurface));
|
||||
memset(surface, 0, sizeof(GloSurface));
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->context = context;
|
||||
|
||||
surface->hPBuffer = wglCreatePbufferARB( glo.hDC, context->wglPixelFormat,
|
||||
surface->width, surface->height, pb_attr );
|
||||
if( !surface->hPBuffer ) {
|
||||
printf( "Couldn't create the PBuffer\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
surface->hDC = wglGetPbufferDCARB( surface->hPBuffer );
|
||||
if( !surface->hDC ) {
|
||||
printf( "Couldn't create the DC\n" );
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
/* Destroy the given surface */
|
||||
void glo_surface_destroy(GloSurface *surface) {
|
||||
if (!surface) return;
|
||||
|
||||
wglMakeCurrent( NULL, NULL );
|
||||
if( surface->hPBuffer != NULL ) {
|
||||
wglReleasePbufferDCARB( surface->hPBuffer, surface->hDC );
|
||||
wglDestroyPbufferARB( surface->hPBuffer );
|
||||
}
|
||||
if( surface->hDC != NULL ) {
|
||||
ReleaseDC( glo.hWnd, surface->hDC );
|
||||
}
|
||||
free(surface);
|
||||
}
|
||||
|
||||
/* Make the given surface current */
|
||||
int glo_surface_makecurrent(GloSurface *surface) {
|
||||
if (surface) {
|
||||
return wglMakeCurrent( surface->hDC, surface->context->hContext );
|
||||
} else {
|
||||
return wglMakeCurrent( NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the contents of the given surface */
|
||||
void glo_surface_getcontents(GloSurface *surface, int stride, int bpp, void *data) {
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
// Compatible / fallback method.
|
||||
glo_surface_getcontents_readpixels(surface->context->formatFlags,
|
||||
stride, bpp, surface->width,
|
||||
surface->height, data);
|
||||
}
|
||||
|
||||
/* Return the width and height of the given surface */
|
||||
void glo_surface_get_size(GloSurface *surface, int *width, int *height) {
|
||||
if (width)
|
||||
*width = surface->width;
|
||||
if (height)
|
||||
*height = surface->height;
|
||||
}
|
||||
|
||||
/* Fake glXQueryExtensionsString() */
|
||||
const char *glo_glXQueryExtensionsString(void) {
|
||||
return "";
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue