diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-07-17 14:46:40 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-07-17 14:46:40 -0400 |
commit | e910f6831b4e7033a0d5cbd83bdab191d622bad0 (patch) | |
tree | f5a386cad3583d60757e2837418b734f09e76295 | |
parent | 79a170108f1d9cad949cd2a34e4de597beae72db (diff) | |
parent | 30bccf8ea9cd84d1a52a31b6f86b783dfb919374 (diff) |
Merge branch 'master' of git+ssh://agd5f@git.freedesktop.org/git/mesa/mesa into r6xx-rewriter6xx-rewrite
43 files changed, 1903 insertions, 846 deletions
diff --git a/configs/default b/configs/default index a8996702d70..60638d739dd 100644 --- a/configs/default +++ b/configs/default @@ -105,7 +105,7 @@ GALLIUM_STATE_TRACKERS_DIRS = glx # Library dependencies #EXTRA_LIB_PATH ?= GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lm -lpthread -EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -ldl +EGL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -ldl -lpthread OSMESA_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) GLU_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -lm GLUT_LIB_DEPS = $(EXTRA_LIB_PATH) -L$(TOP)/$(LIB_DIR) -l$(GLU_LIB) -l$(GL_LIB) -lX11 -lXmu -lXi -lm diff --git a/progs/egl/.gitignore b/progs/egl/.gitignore index 793c6c0f614..f417aefb93a 100644 --- a/progs/egl/.gitignore +++ b/progs/egl/.gitignore @@ -7,4 +7,5 @@ eglscreen egltri peglgears xeglgears +xeglthreads xegl_tri diff --git a/progs/egl/Makefile b/progs/egl/Makefile index e1fdb1ce63d..d3c32d46f78 100644 --- a/progs/egl/Makefile +++ b/progs/egl/Makefile @@ -18,6 +18,7 @@ PROGRAMS = \ eglscreen \ peglgears \ xeglgears \ + xeglthreads \ xegl_tri @@ -90,6 +91,13 @@ xeglgears.o: xeglgears.c $(HEADERS) $(CC) -c $(CFLAGS) -I$(TOP)/include xeglgears.c +xeglthreads: xeglthreads.o $(TOP)/$(LIB_DIR)/libEGL.so + $(CC) $(CFLAGS) xeglthreads.o -L$(TOP)/$(LIB_DIR) -lEGL -lGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@ + +xeglthreads.o: xeglthreads.c $(HEADERS) + $(CC) -c $(CFLAGS) -I$(TOP)/include xeglthreads.c + + xegl_tri: xegl_tri.o $(TOP)/$(LIB_DIR)/libEGL.so $(CC) $(CFLAGS) xegl_tri.o -L$(TOP)/$(LIB_DIR) -lEGL -lGL $(LIBDRM_LIB) $(APP_LIB_DEPS) -o $@ diff --git a/progs/egl/xeglthreads.c b/progs/egl/xeglthreads.c new file mode 100644 index 00000000000..508dbc09432 --- /dev/null +++ b/progs/egl/xeglthreads.c @@ -0,0 +1,773 @@ +/* + * Copyright (C) 2000 Brian Paul All Rights Reserved. + * + * 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 + * BRIAN PAUL 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. + * + * Ported to EGL by Chia-I Wu <olvaffe@gmail.com> + */ + + +/* + * This program tests EGL thread safety. + * Command line options: + * -p Open a display connection for each thread + * -l Enable application-side locking + * -n <num threads> Number of threads to create (default is 2) + * -display <display name> Specify X display (default is $DISPLAY) + * -t Use texture mapping + * + * Brian Paul 20 July 2000 + */ + + +/* + * Notes: + * - Each thread gets its own EGL context. + * + * - The EGL contexts share texture objects. + * + * - When 't' is pressed to update the texture image, the window/thread which + * has input focus is signalled to change the texture. The other threads + * should see the updated texture the next time they call glBindTexture. + */ + + +#if defined(PTHREADS) /* defined by Mesa on Linux and other platforms */ + +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <GL/gl.h> +#include <EGL/egl.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> + + +/* + * Each window/thread/context: + */ +struct winthread { + Display *Dpy; + int Index; + pthread_t Thread; + Window Win; + EGLDisplay Display; + EGLContext Context; + EGLSurface Surface; + float Angle; + int WinWidth, WinHeight; + GLboolean NewSize; + GLboolean Initialized; + GLboolean MakeNewTexture; +}; + + +#define MAX_WINTHREADS 100 +static struct winthread WinThreads[MAX_WINTHREADS]; +static int NumWinThreads = 0; +static volatile GLboolean ExitFlag = GL_FALSE; + +static GLboolean MultiDisplays = 0; +static GLboolean Locking = 0; +static GLboolean Texture = GL_FALSE; +static GLuint TexObj = 12; +static GLboolean Animate = GL_TRUE; + +static pthread_mutex_t Mutex; +static pthread_cond_t CondVar; +static pthread_mutex_t CondMutex; + + +static void +Error(const char *msg) +{ + fprintf(stderr, "Error: %s\n", msg); + exit(1); +} + + +static void +signal_redraw(void) +{ + pthread_mutex_lock(&CondMutex); + pthread_cond_broadcast(&CondVar); + pthread_mutex_unlock(&CondMutex); +} + + +static void +MakeNewTexture(struct winthread *wt) +{ +#define TEX_SIZE 128 + static float step = 0.0; + GLfloat image[TEX_SIZE][TEX_SIZE][4]; + GLint width; + int i, j; + + for (j = 0; j < TEX_SIZE; j++) { + for (i = 0; i < TEX_SIZE; i++) { + float dt = 5.0 * (j - 0.5 * TEX_SIZE) / TEX_SIZE; + float ds = 5.0 * (i - 0.5 * TEX_SIZE) / TEX_SIZE; + float r = dt * dt + ds * ds + step; + image[j][i][0] = + image[j][i][1] = + image[j][i][2] = 0.75 + 0.25 * cos(r); + image[j][i][3] = 1.0; + } + } + + step += 0.5; + + glBindTexture(GL_TEXTURE_2D, TexObj); + + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); + if (width) { + assert(width == TEX_SIZE); + /* sub-tex replace */ + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEX_SIZE, TEX_SIZE, + GL_RGBA, GL_FLOAT, image); + } + else { + /* create new */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, + GL_RGBA, GL_FLOAT, image); + } +} + + + +/* draw a colored cube */ +static void +draw_object(void) +{ + glPushMatrix(); + glScalef(0.75, 0.75, 0.75); + + glColor3f(1, 0, 0); + + if (Texture) { + glBindTexture(GL_TEXTURE_2D, TexObj); + glEnable(GL_TEXTURE_2D); + } + else { + glDisable(GL_TEXTURE_2D); + } + + glBegin(GL_QUADS); + + /* -X */ + glColor3f(0, 1, 1); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); + + /* +X */ + glColor3f(1, 0, 0); + glTexCoord2f(0, 0); glVertex3f(1, -1, -1); + glTexCoord2f(1, 0); glVertex3f(1, 1, -1); + glTexCoord2f(1, 1); glVertex3f(1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(1, -1, 1); + + /* -Y */ + glColor3f(1, 0, 1); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); + + /* +Y */ + glColor3f(0, 1, 0); + glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); + + /* -Z */ + glColor3f(1, 1, 0); + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, -1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); + + /* +Y */ + glColor3f(0, 0, 1); + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); + glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); + glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); + + glEnd(); + + glPopMatrix(); +} + + +/* signal resize of given window */ +static void +resize(struct winthread *wt, int w, int h) +{ + wt->NewSize = GL_TRUE; + wt->WinWidth = w; + wt->WinHeight = h; + if (!Animate) + signal_redraw(); +} + + +/* + * We have an instance of this for each thread. + */ +static void +draw_loop(struct winthread *wt) +{ + while (!ExitFlag) { + + if (Locking) + pthread_mutex_lock(&Mutex); + + if (!wt->Initialized) { + eglMakeCurrent(wt->Display, wt->Surface, wt->Surface, wt->Context); + printf("xeglthreads: %d: GL_RENDERER = %s\n", wt->Index, + (char *) glGetString(GL_RENDERER)); + if (Texture /*&& wt->Index == 0*/) { + MakeNewTexture(wt); + } + wt->Initialized = GL_TRUE; + } + + if (Locking) + pthread_mutex_unlock(&Mutex); + + eglBindAPI(EGL_OPENGL_API); + if (eglGetCurrentContext() != wt->Context) { + printf("xeglthreads: current context %p != %p\n", + eglGetCurrentContext(), wt->Context); + } + + glEnable(GL_DEPTH_TEST); + + if (wt->NewSize) { + GLfloat w = (float) wt->WinWidth / (float) wt->WinHeight; + glViewport(0, 0, wt->WinWidth, wt->WinHeight); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-w, w, -1.0, 1.0, 1.5, 10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -2.5); + wt->NewSize = GL_FALSE; + } + + if (wt->MakeNewTexture) { + MakeNewTexture(wt); + wt->MakeNewTexture = GL_FALSE; + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(wt->Angle, 0, 1, 0); + glRotatef(wt->Angle, 1, 0, 0); + glScalef(0.7, 0.7, 0.7); + draw_object(); + glPopMatrix(); + + if (Locking) + pthread_mutex_lock(&Mutex); + + eglSwapBuffers(wt->Display, wt->Surface); + + if (Locking) + pthread_mutex_unlock(&Mutex); + + if (Animate) { + usleep(5000); + } + else { + /* wait for signal to draw */ + pthread_mutex_lock(&CondMutex); + pthread_cond_wait(&CondVar, &CondMutex); + pthread_mutex_unlock(&CondMutex); + } + wt->Angle += 1.0; + } + eglMakeCurrent(wt->Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + + +static void +keypress(XEvent *event, struct winthread *wt) +{ + char buf[100]; + KeySym keySym; + XComposeStatus stat; + + XLookupString(&event->xkey, buf, sizeof(buf), &keySym, &stat); + + switch (keySym) { + case XK_Escape: + /* tell all threads to exit */ + if (!Animate) { + signal_redraw(); + } + ExitFlag = GL_TRUE; + /*printf("exit draw_loop %d\n", wt->Index);*/ + return; + case XK_t: + case XK_T: + if (Texture) { + wt->MakeNewTexture = GL_TRUE; + if (!Animate) + signal_redraw(); + } + break; + case XK_a: + case XK_A: + Animate = !Animate; + if (Animate) /* yes, prev Animate state! */ + signal_redraw(); + break; + case XK_s: + case XK_S: + if (!Animate) + signal_redraw(); + break; + default: + ; /* nop */ + } +} + + +/* + * The main process thread runs this loop. + * Single display connection for all threads. + */ +static void +event_loop(Display *dpy) +{ + XEvent event; + int i; + + assert(!MultiDisplays); + + while (!ExitFlag) { + + if (Locking) { + while (1) { + int k; + pthread_mutex_lock(&Mutex); + k = XPending(dpy); + if (k) { + XNextEvent(dpy, &event); + pthread_mutex_unlock(&Mutex); + break; + } + pthread_mutex_unlock(&Mutex); + usleep(5000); + } + } + else { + XNextEvent(dpy, &event); + } + + switch (event.type) { + case ConfigureNotify: + /* Find winthread for this event's window */ + for (i = 0; i < NumWinThreads; i++) { + struct winthread *wt = &WinThreads[i]; + if (event.xconfigure.window == wt->Win) { + resize(wt, event.xconfigure.width, + event.xconfigure.height); + break; + } + } + break; + case KeyPress: + for (i = 0; i < NumWinThreads; i++) { + struct winthread *wt = &WinThreads[i]; + if (event.xkey.window == wt->Win) { + keypress(&event, wt); + break; + } + } + break; + default: + /*no-op*/ ; + } + } +} + + +/* + * Separate display connection for each thread. + */ +static void +event_loop_multi(void) +{ + XEvent event; + int w = 0; + + assert(MultiDisplays); + + while (!ExitFlag) { + struct winthread *wt = &WinThreads[w]; + if (XPending(wt->Dpy)) { + XNextEvent(wt->Dpy, &event); + switch (event.type) { + case ConfigureNotify: + resize(wt, event.xconfigure.width, event.xconfigure.height); + break; + case KeyPress: + keypress(&event, wt); + break; + default: + ; /* nop */ + } + } + w = (w + 1) % NumWinThreads; + usleep(5000); + } +} + + + +/* + * we'll call this once for each thread, before the threads are created. + */ +static void +create_window(struct winthread *wt, EGLContext shareCtx) +{ + Window win; + EGLContext ctx; + EGLSurface surf; + EGLint attribs[] = { EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_DEPTH_SIZE, 1, + EGL_NONE }; + EGLConfig config; + EGLint num_configs; + EGLint vid; + int scrnum; + XSetWindowAttributes attr; + unsigned long mask; + Window root; + XVisualInfo *visinfo, visTemplate; + int num_visuals; + int width = 160, height = 160; + int xpos = (wt->Index % 8) * (width + 10); + int ypos = (wt->Index / 8) * (width + 20); + + scrnum = DefaultScreen(wt->Dpy); + root = RootWindow(wt->Dpy, scrnum); + + if (!eglChooseConfig(wt->Display, attribs, &config, 1, &num_configs)) { + Error("Unable to choose an EGL config"); + } + + assert(config); + assert(num_configs > 0); + + if (!eglGetConfigAttrib(wt->Display, config, EGL_NATIVE_VISUAL_ID, &vid)) { + Error("Unable to get visual id of EGL config\n"); + } + + visTemplate.visualid = vid; + visinfo = XGetVisualInfo(wt->Dpy, VisualIDMask, + &visTemplate, &num_visuals); + if (!visinfo) { + Error("Unable to find RGB, Z, double-buffered visual"); + } + + /* window attributes */ + attr.background_pixel = 0; + attr.border_pixel = 0; + attr.colormap = XCreateColormap(wt->Dpy, root, visinfo->visual, AllocNone); + attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; + mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; + + win = XCreateWindow(wt->Dpy, root, xpos, ypos, width, height, + 0, visinfo->depth, InputOutput, + visinfo->visual, mask, &attr); + if (!win) { + Error("Couldn't create window"); + } + + XFree(visinfo); + + { + XSizeHints sizehints; + sizehints.x = xpos; + sizehints.y = ypos; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize | USPosition; + XSetNormalHints(wt->Dpy, win, &sizehints); + XSetStandardProperties(wt->Dpy, win, "xeglthreads", "xeglthreads", + None, (char **)NULL, 0, &sizehints); + } + + eglBindAPI(EGL_OPENGL_API); + + ctx = eglCreateContext(wt->Display, config, shareCtx, NULL); + if (!ctx) { + Error("Couldn't create EGL context"); + } + surf = eglCreateWindowSurface(wt->Display, config, win, NULL); + if (!surf) { + Error("Couldn't create EGL surface"); + } + + XMapWindow(wt->Dpy, win); + XSync(wt->Dpy, 0); + + /* save the info for this window/context */ + wt->Win = win; + wt->Context = ctx; + wt->Surface = surf; + wt->Angle = 0.0; + wt->WinWidth = width; + wt->WinHeight = height; + wt->NewSize = GL_TRUE; +} + + +/* + * Called by pthread_create() + */ +static void * +thread_function(void *p) +{ + struct winthread *wt = (struct winthread *) p; + draw_loop(wt); + return NULL; +} + + +/* + * called before exit to wait for all threads to finish + */ +static void +clean_up(void) +{ + int i; + + /* wait for threads to finish */ + for (i = 0; i < NumWinThreads; i++) { + pthread_join(WinThreads[i].Thread, NULL); + } + + for (i = 0; i < NumWinThreads; i++) { + eglDestroyContext(WinThreads[i].Display, WinThreads[i].Context); + XDestroyWindow(WinThreads[i].Dpy, WinThreads[i].Win); + } +} + + +static void +usage(void) +{ + printf("xeglthreads: test of EGL/GL thread safety (any key = exit)\n"); + printf("Usage:\n"); + printf(" xeglthreads [options]\n"); + printf("Options:\n"); + printf(" -display DISPLAYNAME Specify display string\n"); + printf(" -n NUMTHREADS Number of threads to create\n"); + printf(" -p Use a separate display connection for each thread\n"); + printf(" -l Use application-side locking\n"); + printf(" -t Enable texturing\n"); + printf("Keyboard:\n"); + printf(" Esc Exit\n"); + printf(" t Change texture image (requires -t option)\n"); + printf(" a Toggle animation\n"); + printf(" s Step rotation (when not animating)\n"); +} + + +int +main(int argc, char *argv[]) +{ + char *displayName = NULL; + int numThreads = 2; + Display *dpy = NULL; + EGLDisplay *egl_dpy = NULL; + int i; + Status threadStat; + + if (argc == 1) { + usage(); + } + else { + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) { + displayName = argv[i + 1]; + i++; + } + else if (strcmp(argv[i], "-p") == 0) { + MultiDisplays = 1; + } + else if (strcmp(argv[i], "-l") == 0) { + Locking = 1; + } + else if (strcmp(argv[i], "-t") == 0) { + Texture = 1; + } + else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { + numThreads = atoi(argv[i + 1]); + if (numThreads < 1) + numThreads = 1; + else if (numThreads > MAX_WINTHREADS) + numThreads = MAX_WINTHREADS; + i++; + } + else { + usage(); + exit(1); + } + } + } + + if (Locking) + printf("xeglthreads: Using explicit locks around Xlib calls.\n"); + else + printf("xeglthreads: No explict locking.\n"); + + if (MultiDisplays) + printf("xeglthreads: Per-thread display connections.\n"); + else + printf("xeglthreads: Single display connection.\n"); + + /* + * VERY IMPORTANT: call XInitThreads() before any other Xlib functions. + */ + if (!MultiDisplays) { + if (!Locking) { + threadStat = XInitThreads(); + if (threadStat) { + printf("XInitThreads() returned %d (success)\n", + (int) threadStat); + } + else { + printf("XInitThreads() returned 0 " + "(failure- this program may fail)\n"); + } + } + + dpy = XOpenDisplay(displayName); + if (!dpy) { + fprintf(stderr, "Unable to open display %s\n", + XDisplayName(displayName)); + return -1; + } + egl_dpy = eglGetDisplay(dpy); + if (!egl_dpy) { + fprintf(stderr, "Unable to get EGL display\n"); + XCloseDisplay(dpy); + return -1; + } + if (!eglInitialize(egl_dpy, NULL, NULL)) { + fprintf(stderr, "Unable to initialize EGL display\n"); + return -1; + } + } + + pthread_mutex_init(&Mutex, NULL); + pthread_mutex_init(&CondMutex, NULL); + pthread_cond_init(&CondVar, NULL); + + printf("xeglthreads: creating windows\n"); + + NumWinThreads = numThreads; + + /* Create the EGL windows and contexts */ + for (i = 0; i < numThreads; i++) { + EGLContext share; + + if (MultiDisplays) { + WinThreads[i].Dpy = XOpenDisplay(displayName); + assert(WinThreads[i].Dpy); + WinThreads[i].Display = eglGetDisplay(WinThreads[i].Dpy); + assert(eglInitialize(WinThreads[i].Display, NULL, NULL)); + } + else { + WinThreads[i].Dpy = dpy; + WinThreads[i].Display = egl_dpy; + } + WinThreads[i].Index = i; + WinThreads[i].Initialized = GL_FALSE; + + share = (Texture && i > 0) ? WinThreads[0].Context : 0; + + create_window(&WinThreads[i], share); + } + + printf("xeglthreads: creating threads\n"); + + /* Create the threads */ + for (i = 0; i < numThreads; i++) { + pthread_create(&WinThreads[i].Thread, NULL, thread_function, + (void*) &WinThreads[i]); + printf("xeglthreads: Created thread %p\n", + (void *) WinThreads[i].Thread); + } + + if (MultiDisplays) + event_loop_multi(); + else + event_loop(dpy); + + clean_up(); + + if (MultiDisplays) { + for (i = 0; i < numThreads; i++) { + eglTerminate(WinThreads[i].Display); + XCloseDisplay(WinThreads[i].Dpy); + } + } + else { + eglTerminate(egl_dpy); + XCloseDisplay(dpy); + } + + return 0; +} + + +#else /* PTHREADS */ + + +#include <stdio.h> + +int +main(int argc, char *argv[]) +{ + printf("Sorry, this program wasn't compiled with PTHREADS defined.\n"); + return 0; +} + + +#endif /* PTHREADS */ diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c index 1750e976b84..f316974d836 100644 --- a/src/egl/drivers/demo/demo.c +++ b/src/egl/drivers/demo/demo.c @@ -146,12 +146,12 @@ demoCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext if (!c) return EGL_NO_CONTEXT; - _eglInitContext(drv, dpy, &c->Base, config, attrib_list); + _eglInitContext(drv, &c->Base, conf, attrib_list); c->DemoStuff = 1; printf("demoCreateContext\n"); - /* generate handle and insert into hash table */ - _eglSaveContext(&c->Base); + /* link to display */ + _eglLinkContext(&c->Base, _eglLookupDisplay(dpy)); assert(_eglGetContextHandle(&c->Base)); return _eglGetContextHandle(&c->Base); @@ -213,11 +213,14 @@ demoCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { DemoSurface *surf = (DemoSurface *) calloc(1, sizeof(DemoSurface)); + _EGLConfig *conf; + if (!surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { + conf = _eglLookupConfig(drv, dpy, config); + if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } @@ -232,13 +235,9 @@ static EGLBoolean demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { DemoSurface *fs = LookupDemoSurface(surface); - _eglRemoveSurface(&fs->Base); - if (fs->Base.IsBound) { - fs->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(&fs->Base); + if (!fs->Base.IsBound) free(fs); - } return EGL_TRUE; } @@ -247,13 +246,9 @@ static EGLBoolean demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { DemoContext *fc = LookupDemoContext(context); - _eglRemoveContext(&fc->Base); - if (fc->Base.IsBound) { - fc->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkContext(&fc->Base); + if (!fc->Base.IsBound) free(fc); - } return EGL_TRUE; } diff --git a/src/egl/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c index 57661cc3ab8..3f9617a8f98 100644 --- a/src/egl/drivers/dri/egldri.c +++ b/src/egl/drivers/dri/egldri.c @@ -171,7 +171,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!c) return EGL_NO_CONTEXT; - if (!_eglInitContext(drv, dpy, &c->Base, config, attrib_list)) { + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); + + if (!_eglInitContext(drv, &c->Base, conf, attrib_list)) { free(c); return EGL_NO_CONTEXT; } @@ -189,8 +192,6 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, else sharePriv = NULL; - conf = _eglLookupConfig(drv, dpy, config); - assert(conf); _eglConfigToContextModesRec(conf, &visMode); c->driContext.private = disp->driScreen.createNewContext(disp, &visMode, @@ -200,8 +201,8 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_FALSE; } - /* generate handle and insert into hash table */ - _eglSaveContext(&c->Base); + /* link to display */ + _eglLinkContext(&c->Base, &disp->Base); return _eglGetContextHandle(&c->Base); } @@ -237,14 +238,18 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { driSurface *surf; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); surf = (driSurface *) calloc(1, sizeof(*surf)); if (!surf) { return EGL_NO_SURFACE; } - if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } @@ -275,7 +280,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, #endif } - _eglSaveSurface(&surf->Base); + _eglLinkSurface(&surf->Base, _eglLookupDisplay(dpy)); return surf->Base.Handle; } @@ -287,16 +292,12 @@ _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) driDisplay *disp = Lookup_driDisplay(dpy); driSurface *fs = Lookup_driSurface(surface); - _eglRemoveSurface(&fs->Base); + _eglUnlinkSurface(&fs->Base); fs->drawable.destroyDrawable(disp, fs->drawable.private); - if (fs->Base.IsBound) { - fs->Base.DeletePending = EGL_TRUE; - } - else { + if (!fs->Base.IsBound) free(fs); - } return EGL_TRUE; } @@ -307,16 +308,12 @@ _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) driDisplay *disp = Lookup_driDisplay(dpy); driContext *fc = Lookup_driContext(context); - _eglRemoveContext(&fc->Base); + _eglUnlinkContext(&fc->Base); fc->driContext.destroyContext(disp, 0, fc->driContext.private); - if (fc->Base.IsBound) { - fc->Base.DeletePending = EGL_TRUE; - } - else { + if (!fc->Base.IsBound) free(fc); - } return EGL_TRUE; } @@ -340,13 +337,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, } /* init base class, do error checking, etc. */ - if (!_eglInitSurface(drv, dpy, &surface->Base, EGL_SCREEN_BIT_MESA, - cfg, attrib_list)) { + if (!_eglInitSurface(drv, &surface->Base, EGL_SCREEN_BIT_MESA, + config, attrib_list)) { free(surface); return EGL_NO_SURFACE; } - _eglSaveSurface(&surface->Base); + _eglLinkSurface(&surface->Base &disp->Base); /* @@ -363,7 +360,7 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, if (!disp->driScreen.createNewDrawable(disp, &visMode, drawBuf, &surface->drawable, GLX_WINDOW_BIT, empty_attribute_list)) { - _eglRemoveSurface(&surface->Base); + _eglUnlinkSurface(&surface->Base); free(surface); return EGL_NO_SURFACE; } diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c index 155caa413c8..207b1ea7793 100644 --- a/src/egl/drivers/glx/egl_glx.c +++ b/src/egl/drivers/glx/egl_glx.c @@ -532,7 +532,10 @@ GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!GLX_ctx) return EGL_NO_CONTEXT; - if (!_eglInitContext(drv, dpy, &GLX_ctx->Base, config, attrib_list)) { + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); + + if (!_eglInitContext(drv, &GLX_ctx->Base, conf, attrib_list)) { free(GLX_ctx); return EGL_NO_CONTEXT; } @@ -546,9 +549,6 @@ GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, GLX_ctx_shared = GLX_egl_context(shareCtx); } - conf = _eglLookupConfig(drv, dpy, config); - assert(conf); - #ifdef GLX_VERSION_1_3 if (GLX_drv->fbconfigs) GLX_ctx->context = glXCreateNewContext(disp->Xdpy, GLX_drv->fbconfigs[(int)config-1], GLX_RGBA_TYPE, GLX_ctx_shared ? GLX_ctx_shared->context : NULL, GL_TRUE); @@ -564,7 +564,7 @@ GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_FALSE; #endif - return _eglGetContextHandle(&GLX_ctx->Base); + return _eglLinkContext(&GLX_ctx->Base, disp); } @@ -619,18 +619,22 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, _EGLDisplay *disp = _eglLookupDisplay(dpy); struct GLX_egl_surface *GLX_surf; uint width, height; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); GLX_surf = CALLOC_STRUCT(GLX_egl_surface); if (!GLX_surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_WINDOW_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_WINDOW_BIT, + conf, attrib_list)) { free(GLX_surf); return EGL_FALSE; } - _eglSaveSurface(&GLX_surf->Base); + _eglLinkSurface(&GLX_surf->Base, disp); GLX_surf->drawable = window; get_drawable_size(disp->Xdpy, window, &width, &height); @@ -648,19 +652,23 @@ GLX_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); _EGLDisplay *disp = _eglLookupDisplay(dpy); struct GLX_egl_surface *GLX_surf; + _EGLConfig *conf; int i; + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); + GLX_surf = CALLOC_STRUCT(GLX_egl_surface); if (!GLX_surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_PIXMAP_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PIXMAP_BIT, + conf, attrib_list)) { free(GLX_surf); return EGL_FALSE; } - _eglSaveSurface(&GLX_surf->Base); + _eglLinkSurface(&GLX_surf->Base, disp); for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { @@ -683,20 +691,24 @@ GLX_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); _EGLDisplay *disp = _eglLookupDisplay(dpy); struct GLX_egl_surface *GLX_surf; + _EGLConfig *conf; int attribs[5]; int i = 0, j = 0; + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); + GLX_surf = CALLOC_STRUCT(GLX_egl_surface); if (!GLX_surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { free(GLX_surf); return EGL_NO_SURFACE; } - _eglSaveSurface(&GLX_surf->Base); + _eglLinkSurface(&GLX_surf->Base, disp); while(attrib_list[i] != EGL_NONE) { switch (attrib_list[i]) { @@ -726,13 +738,9 @@ GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) _EGLSurface *surf = _eglLookupSurface(surface); return EGL_TRUE; if (surf) { - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); - if (surf->IsBound) { - surf->DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(surf); + if (!surf->IsBound) free(surf); - } return EGL_TRUE; } diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c index 3b3e312746e..e040efdd438 100644 --- a/src/egl/drivers/xdri/egl_xdri.c +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -770,7 +770,7 @@ xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!xdri_ctx) return EGL_NO_CONTEXT; - if (!_eglInitContext(drv, dpy, &xdri_ctx->Base, config, attrib_list)) { + if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) { free(xdri_ctx); return EGL_NO_CONTEXT; } @@ -794,7 +794,7 @@ xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, xdri_ctx->driContext.mode = xdri_config->mode; - return _eglGetContextHandle(&xdri_ctx->Base); + return _eglLinkContext(&xdri_ctx->Base, &disp); } @@ -835,6 +835,7 @@ xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) { _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); struct xdri_egl_surface *xdri_surf; int scrn = DefaultScreen(disp->Xdpy); uint width, height; @@ -843,8 +844,8 @@ xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!xdri_surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_WINDOW_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT, + &xdri_config->Base, attrib_list)) { free(xdri_surf); return EGL_FALSE; } @@ -856,7 +857,7 @@ xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, xdri_surf->driDrawable = window; - _eglSaveSurface(&xdri_surf->Base); + _eglLinkSurface(&xdri_surf->Base, disp); get_drawable_size(disp->Xdpy, window, &width, &height); xdri_surf->Base.Width = width; @@ -888,8 +889,8 @@ xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!xdri_surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_PBUFFER_BIT, + &xdri_config->Base, attrib_list)) { free(xdri_surf); return EGL_FALSE; } @@ -939,7 +940,7 @@ xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, xdri_surf->driDrawable = window; - _eglSaveSurface(&xdri_surf->Base); + _eglLinkSurface(&xdri_surf->Base, disp); _eglLog(_EGL_DEBUG, "XDRI: CreatePbufferSurface handle %d hDrawable %d", @@ -956,11 +957,8 @@ xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { struct xdri_egl_surface *xdri_surf = lookup_surface(surface); if (xdri_surf) { - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); - if (xdri_surf->Base.IsBound) { - xdri_surf->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(&xdri_surf->Base); + if (!xdri_surf->Base.IsBound) { /* st_unreference_framebuffer(surf->Framebuffer); */ diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index cddba9f0887..e1ff8794b35 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -7,9 +7,11 @@ include $(TOP)/configs/current INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi HEADERS = \ + eglcompiler.h \ eglconfig.h \ eglconfigutil.h \ eglcontext.h \ + eglcurrent.h \ egldefines.h \ egldisplay.h \ egldriver.h \ @@ -28,6 +30,7 @@ SOURCES = \ eglconfig.c \ eglconfigutil.c \ eglcontext.c \ + eglcurrent.c \ egldisplay.c \ egldriver.c \ eglglobals.c \ diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 9df938e1887..f0a6f7f9355 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -51,7 +51,12 @@ eglGetDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy; _eglInitGlobals(); - dpy = _eglNewDisplay(nativeDisplay); + dpy = _eglFindDisplay(nativeDisplay); + if (!dpy) { + dpy = _eglNewDisplay(nativeDisplay); + if (dpy) + _eglLinkDisplay(dpy); + } return _eglGetDisplayHandle(dpy); } @@ -321,7 +326,8 @@ eglGetError(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint e = t->LastError; - t->LastError = EGL_SUCCESS; + if (!_eglIsCurrentThreadDummy()) + t->LastError = EGL_SUCCESS; return e; } @@ -546,11 +552,17 @@ eglBindAPI(EGLenum api) { _EGLThreadInfo *t = _eglGetCurrentThread(); + if (_eglIsCurrentThreadDummy()) + return _eglError(EGL_BAD_ALLOC, "eglBindAPI"); + + if (!_eglIsApiValid(api)) + return _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); + switch (api) { #ifdef EGL_VERSION_1_4 case EGL_OPENGL_API: if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) { - t->CurrentAPI = api; + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); @@ -558,14 +570,14 @@ eglBindAPI(EGLenum api) #endif case EGL_OPENGL_ES_API: if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) { - t->CurrentAPI = api; + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); return EGL_FALSE; case EGL_OPENVG_API: if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) { - t->CurrentAPI = api; + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); @@ -585,7 +597,7 @@ eglQueryAPI(void) { /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentAPI; + return _eglConvertApiFromIndex(t->CurrentAPIIndex); } @@ -603,15 +615,19 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLBoolean eglReleaseThread(void) { - _EGLThreadInfo *t = _eglGetCurrentThread(); - EGLDisplay dpy = eglGetCurrentDisplay(); + EGLDisplay dpy; + + if (_eglIsCurrentThreadDummy()) + return EGL_TRUE; + + dpy = eglGetCurrentDisplay(); if (dpy) { _EGLDriver *drv = _eglLookupDriver(dpy); /* unbind context */ (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } - _eglDeleteThreadData(t); + _eglDestroyCurrentThread(); return EGL_TRUE; } diff --git a/src/egl/main/eglcompiler.h b/src/egl/main/eglcompiler.h new file mode 100644 index 00000000000..0b19afedfd3 --- /dev/null +++ b/src/egl/main/eglcompiler.h @@ -0,0 +1,31 @@ +#ifndef EGLCOMPILER_INCLUDED +#define EGLCOMPILER_INCLUDED + + +/** + * Function inlining + */ +#if defined(__GNUC__) +# define INLINE __inline__ +#elif defined(__MSC__) +# define INLINE __inline +#elif defined(_MSC_VER) +# define INLINE __inline +#elif defined(__ICL) +# define INLINE __inline +#elif defined(__INTEL_COMPILER) +# define INLINE inline +#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100) +# define INLINE __inline +#elif defined(__SUNPRO_C) && defined(__C99FEATURES__) +# define INLINE inline +# define __inline inline +# define __inline__ inline +#elif (__STDC_VERSION__ >= 199901L) /* C99 */ +# define INLINE inline +#else +# define INLINE +#endif + + +#endif /* EGLCOMPILER_INCLUDED */ diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 461679db090..9ab4286d3a8 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -14,11 +14,9 @@ * in the attrib_list. */ EGLBoolean -_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, - EGLConfig config, const EGLint *attrib_list) +_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, + _EGLConfig *conf, const EGLint *attrib_list) { - _EGLConfig *conf; - _EGLDisplay *display = _eglLookupDisplay(dpy); EGLint i; const EGLenum api = eglQueryAPI(); @@ -27,7 +25,6 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, return EGL_FALSE; } - conf = _eglLookupConfig(drv, dpy, config); if (!conf) { _eglError(EGL_BAD_CONFIG, "_eglInitContext"); return EGL_FALSE; @@ -49,7 +46,6 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, } } - ctx->Display = display; ctx->Config = conf; ctx->DrawSurface = EGL_NO_SURFACE; ctx->ReadSurface = EGL_NO_SURFACE; @@ -60,66 +56,6 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, /** - * Save a new _EGLContext into the hash table. - */ -void -_eglSaveContext(_EGLContext *ctx) -{ - /* no-op. - * Public EGLContext handle and private _EGLContext are the same. - */ -} - - -/** - * Remove the given _EGLContext object from the hash table. - */ -void -_eglRemoveContext(_EGLContext *ctx) -{ - /* no-op. - * Public EGLContext handle and private _EGLContext are the same. - */ -} - - -/** - * Return the public handle for the given private context ptr. - * This is the inverse of _eglLookupContext(). - */ -EGLContext -_eglGetContextHandle(_EGLContext *ctx) -{ - /* just a cast! */ - return (EGLContext) ctx; -} - - -/** - * Return the _EGLContext object that corresponds to the given - * EGLContext handle. - * This is the inverse of _eglGetContextHandle(). - */ -_EGLContext * -_eglLookupContext(EGLContext ctx) -{ - /* just a cast since EGLContext is just a void ptr */ - return (_EGLContext *) ctx; -} - - -/** - * Return the currently bound _EGLContext object, or NULL. - */ -_EGLContext * -_eglGetCurrentContext(void) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentContext; -} - - -/** * Just a placeholder/demo function. Real driver will never use this! */ EGLContext @@ -128,18 +64,24 @@ _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, { #if 0 /* example code */ _EGLContext *context; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreateContext"); + return EGL_NO_CONTEXT; + } context = (_EGLContext *) calloc(1, sizeof(_EGLContext)); if (!context) return EGL_NO_CONTEXT; - if (!_eglInitContext(drv, dpy, context, config, attrib_list)) { + if (!_eglInitContext(drv, context, conf, attrib_list)) { free(context); return EGL_NO_CONTEXT; } - _eglSaveContext(context); - return (EGLContext) context; + return _eglLinkContext(context, _eglLookupDisplay(dpy)); #endif return EGL_NO_CONTEXT; } @@ -153,12 +95,9 @@ _eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) { _EGLContext *context = _eglLookupContext(ctx); if (context) { - if (context->IsBound) { - context->DeletePending = EGL_TRUE; - } - else { + _eglUnlinkContext(context); + if (!context->IsBound) free(context); - } return EGL_TRUE; } else { @@ -203,7 +142,7 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, /** * Drivers will typically call this to do the error checking and - * update the various IsBound and DeletePending flags. + * update the various flags. * Then, the driver will do its device-dependent Make-Current stuff. */ EGLBoolean @@ -214,10 +153,13 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, _EGLContext *ctx = _eglLookupContext(context); _EGLSurface *draw = _eglLookupSurface(d); _EGLSurface *read = _eglLookupSurface(r); + _EGLContext *oldContext = NULL; + _EGLSurface *oldDrawSurface = NULL; + _EGLSurface *oldReadSurface = NULL; + EGLint apiIndex; - _EGLContext *oldContext = _eglGetCurrentContext(); - _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW); - _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ); + if (_eglIsCurrentThreadDummy()) + return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); /* error checking */ if (ctx) { @@ -233,6 +175,32 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_FALSE; } + +#ifdef EGL_VERSION_1_4 + /* OpenGL and OpenGL ES are conflicting */ + switch (ctx->ClientAPI) { + case EGL_OPENGL_ES_API: + if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + break; + case EGL_OPENGL_API: + if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)]) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + break; + default: + break; + } +#endif + apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); + } + else { + apiIndex = t->CurrentAPIIndex; + } + + oldContext = t->CurrentContexts[apiIndex]; + if (oldContext) { + oldDrawSurface = oldContext->DrawSurface; + oldReadSurface = oldContext->ReadSurface; } /* @@ -240,7 +208,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, */ if (oldDrawSurface != NULL) { oldDrawSurface->IsBound = EGL_FALSE; - if (oldDrawSurface->DeletePending) { + if (!_eglIsSurfaceLinked(oldDrawSurface)) { /* make sure we don't try to rebind a deleted surface */ if (draw == oldDrawSurface || draw == oldReadSurface) { draw = NULL; @@ -251,7 +219,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, } if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) { oldReadSurface->IsBound = EGL_FALSE; - if (oldReadSurface->DeletePending) { + if (!_eglIsSurfaceLinked(oldReadSurface)) { /* make sure we don't try to rebind a deleted surface */ if (read == oldDrawSurface || read == oldReadSurface) { read = NULL; @@ -262,7 +230,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, } if (oldContext != NULL) { oldContext->IsBound = EGL_FALSE; - if (oldContext->DeletePending) { + if (!_eglIsContextLinked(oldContext)) { /* make sure we don't try to rebind a deleted context */ if (ctx == oldContext) { ctx = NULL; @@ -283,9 +251,11 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, ctx->IsBound = EGL_TRUE; draw->IsBound = EGL_TRUE; read->IsBound = EGL_TRUE; + t->CurrentContexts[apiIndex] = ctx; + } + else { + t->CurrentContexts[apiIndex] = NULL; } - - t->CurrentContext = ctx; return EGL_TRUE; } diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index 34fee9c6376..2fb28d38b91 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -11,7 +11,9 @@ */ struct _egl_context { - _EGLDisplay *Display; /* who do I belong to? */ + /* Managed by EGLDisplay for linking */ + _EGLDisplay *Display; + _EGLContext *Next; _EGLConfig *Config; @@ -19,7 +21,6 @@ struct _egl_context _EGLSurface *ReadSurface; EGLBoolean IsBound; - EGLBoolean DeletePending; EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */ EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */ @@ -27,28 +28,8 @@ struct _egl_context extern EGLBoolean -_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, - EGLConfig config, const EGLint *attrib_list); - - -extern void -_eglSaveContext(_EGLContext *ctx); - - -extern void -_eglRemoveContext(_EGLContext *ctx); - - -extern EGLContext -_eglGetContextHandle(_EGLContext *ctx); - - -extern _EGLContext * -_eglLookupContext(EGLContext ctx); - - -extern _EGLContext * -_eglGetCurrentContext(void); +_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, + _EGLConfig *config, const EGLint *attrib_list); extern EGLContext diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 47a2323eafb..89de609d0b4 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include "eglcontext.h" +#include "eglsurface.h" #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" @@ -25,11 +26,6 @@ _eglNewDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); if (dpy) { - EGLuint key = _eglHashGenKey(_eglGlobal.Displays); - - dpy->Handle = (EGLDisplay) key; - _eglHashInsert(_eglGlobal.Displays, key, dpy); - dpy->NativeDisplay = nativeDisplay; #if defined(_EGL_PLATFORM_X) dpy->Xdpy = (Display *) nativeDisplay; @@ -46,8 +42,37 @@ _eglNewDisplay(NativeDisplayType nativeDisplay) /** - * Return the public handle for an internal _EGLDisplay. - * This is the inverse of _eglLookupDisplay(). + * Link a display to itself and return the handle of the link. + * The handle can be passed to client directly. + */ +EGLDisplay +_eglLinkDisplay(_EGLDisplay *dpy) +{ + EGLuint key; + key = _eglHashGenKey(_eglGlobal.Displays); + assert(key); + /* "link" the display to the hash table */ + _eglHashInsert(_eglGlobal.Displays, key, dpy); + dpy->Handle = (EGLDisplay) key; + + return dpy->Handle; +} + + +/** + * Unlink a linked display from itself. + * Accessing an unlinked display should generate EGL_BAD_DISPLAY error. + */ +void +_eglUnlinkDisplay(_EGLDisplay *dpy) +{ + _eglHashRemove(_eglGlobal.Displays, (EGLuint) dpy->Handle); + dpy->Handle = EGL_NO_DISPLAY; +} + + +/** + * Return the handle of a linked display, or EGL_NO_DISPLAY. */ EGLDisplay _eglGetDisplayHandle(_EGLDisplay *display) @@ -60,40 +85,70 @@ _eglGetDisplayHandle(_EGLDisplay *display) /** - * Return the _EGLDisplay object that corresponds to the given public/ - * opaque display handle. - * This is the inverse of _eglGetDisplayHandle(). + * Lookup a handle to find the linked display. + * Return NULL if the handle has no corresponding linked display. */ _EGLDisplay * _eglLookupDisplay(EGLDisplay dpy) { EGLuint key = (EGLuint) dpy; - if (!_eglGlobal.Displays) - return NULL; return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key); } -void -_eglSaveDisplay(_EGLDisplay *dpy) +/** + * Find the display corresponding to the specified native display id in all + * linked displays. + */ +_EGLDisplay * +_eglFindDisplay(NativeDisplayType nativeDisplay) { - EGLuint key = _eglHashGenKey(_eglGlobal.Displays); - assert(dpy); - assert(!dpy->Handle); - dpy->Handle = (EGLDisplay) key; - assert(dpy->Handle); - _eglHashInsert(_eglGlobal.Displays, key, dpy); + EGLuint key = _eglHashFirstEntry(_eglGlobal.Displays); + + /* Walk the hash table. Should switch to list if it is a problem. */ + while (key) { + _EGLDisplay *dpy = (_EGLDisplay *) + _eglHashLookup(_eglGlobal.Displays, key); + assert(dpy); + + if (dpy->NativeDisplay == nativeDisplay) + return dpy; + key = _eglHashNextEntry(_eglGlobal.Displays, key); + } + + return NULL; } -_EGLDisplay * -_eglGetCurrentDisplay(void) +/** + * Destroy the contexts and surfaces that are linked to the display. + */ +void +_eglReleaseDisplayResources(_EGLDriver *drv, EGLDisplay dpy) { - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) - return ctx->Display; - else - return NULL; + _EGLDisplay *display; + _EGLContext *contexts; + _EGLSurface *surfaces; + + display = _eglLookupDisplay(dpy); + if (!display) + return; + contexts = display->ContextList; + surfaces = display->SurfaceList; + + while (contexts) { + EGLContext handle = _eglGetContextHandle(contexts); + contexts = contexts->Next; + drv->API.DestroyContext(drv, dpy, handle); + } + assert(!display->ContextList); + + while (surfaces) { + EGLSurface handle = _eglGetSurfaceHandle(surfaces); + surfaces = surfaces->Next; + drv->API.DestroySurface(drv, dpy, handle); + } + assert(!display->SurfaceList); } @@ -119,3 +174,147 @@ _eglCleanupDisplay(_EGLDisplay *disp) /* driver deletes the _EGLDisplay object */ } + + +/** + * Link a context to a display and return the handle of the link. + * The handle can be passed to client directly. + */ +EGLContext +_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy) +{ + ctx->Display = dpy; + ctx->Next = dpy->ContextList; + dpy->ContextList = ctx; + return (EGLContext) ctx; +} + + +/** + * Unlink a linked context from its display. + * Accessing an unlinked context should generate EGL_BAD_CONTEXT error. + */ +void +_eglUnlinkContext(_EGLContext *ctx) +{ + _EGLContext *prev; + + prev = ctx->Display->ContextList; + if (prev != ctx) { + while (prev) { + if (prev->Next == ctx) + break; + prev = prev->Next; + } + assert(prev); + prev->Next = ctx->Next; + } + else { + ctx->Display->ContextList = ctx->Next; + } + + ctx->Next = NULL; + ctx->Display = NULL; +} + + +/** + * Return the handle of a linked context, or EGL_NO_CONTEXT. + */ +EGLContext +_eglGetContextHandle(_EGLContext *ctx) +{ + return (EGLContext) (ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT; +} + + +/** + * Lookup a handle to find the linked context. + * Return NULL if the handle has no corresponding linked context. + */ +_EGLContext * +_eglLookupContext(EGLContext ctx) +{ + _EGLContext *context = (_EGLContext *) ctx; + return (context && context->Display) ? context : NULL; +} + + +/** + * Link a surface to a display and return the handle of the link. + * The handle can be passed to client directly. + */ +EGLSurface +_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) +{ + EGLuint key; + + surf->Display = dpy; + surf->Next = dpy->SurfaceList; + dpy->SurfaceList = surf; + + key = _eglHashGenKey(_eglGlobal.Surfaces); + assert(key); + _eglHashInsert(_eglGlobal.Surfaces, key, surf); + + surf->Handle = (EGLSurface) key; + return surf->Handle; +} + + +/** + * Unlink a linked surface from its display. + * Accessing an unlinked surface should generate EGL_BAD_SURFACE error. + */ +void +_eglUnlinkSurface(_EGLSurface *surf) +{ + _EGLSurface *prev; + + _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle); + surf->Handle = EGL_NO_SURFACE; + + prev = surf->Display->SurfaceList; + if (prev != surf) { + while (prev) { + if (prev->Next == surf) + break; + prev = prev->Next; + } + assert(prev); + prev->Next = surf->Next; + } + else { + prev = NULL; + surf->Display->SurfaceList = surf->Next; + } + + surf->Next = NULL; + surf->Display = NULL; +} + + +/** + * Return the handle of a linked surface, or EGL_NO_SURFACE. + */ +EGLSurface +_eglGetSurfaceHandle(_EGLSurface *surface) +{ + if (surface) + return surface->Handle; + else + return EGL_NO_SURFACE; +} + + +/** + * Lookup a handle to find the linked surface. + * Return NULL if the handle has no corresponding linked surface. + */ +_EGLSurface * +_eglLookupSurface(EGLSurface surf) +{ + _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, + (EGLuint) surf); + return c; +} diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index ff623ee1c66..372ed3cd79a 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -23,6 +23,9 @@ struct _egl_display EGLint NumConfigs; _EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */ + /* lists of linked contexts and surface */ + _EGLContext *ContextList; + _EGLSurface *SurfaceList; #ifdef _EGL_PLATFORM_X Display *Xdpy; #endif @@ -33,7 +36,15 @@ extern _EGLDisplay * _eglNewDisplay(NativeDisplayType displayName); -EGLDisplay +extern EGLDisplay +_eglLinkDisplay(_EGLDisplay *dpy); + + +extern void +_eglUnlinkDisplay(_EGLDisplay *dpy); + + +extern EGLDisplay _eglGetDisplayHandle(_EGLDisplay *display); @@ -41,21 +52,77 @@ extern _EGLDisplay * _eglLookupDisplay(EGLDisplay dpy); -extern void -_eglSaveDisplay(_EGLDisplay *dpy); +/** + * Return true if the display is linked. + */ +static INLINE EGLBoolean +_eglIsDisplayLinked(_EGLDisplay *dpy) +{ + return (EGLBoolean) (_eglGetDisplayHandle(dpy) != EGL_NO_DISPLAY); +} extern _EGLDisplay * -_eglGetCurrentDisplay(void); +_eglFindDisplay(NativeDisplayType nativeDisplay); + + +extern void +_eglReleaseDisplayResources(_EGLDriver *drv, EGLDisplay dpy); extern void _eglCleanupDisplay(_EGLDisplay *disp); -extern EGLBoolean -_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value); +extern EGLContext +_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy); + + +extern void +_eglUnlinkContext(_EGLContext *ctx); + + +extern EGLContext +_eglGetContextHandle(_EGLContext *ctx); +extern _EGLContext * +_eglLookupContext(EGLContext ctx); + + +/** + * Return true if the context is linked to a display. + */ +static INLINE EGLBoolean +_eglIsContextLinked(_EGLContext *ctx) +{ + return (EGLBoolean) (_eglGetContextHandle(ctx) != EGL_NO_CONTEXT); +} + +extern EGLSurface +_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy); + + +extern void +_eglUnlinkSurface(_EGLSurface *surf); + + +extern EGLSurface +_eglGetSurfaceHandle(_EGLSurface *); + + +extern _EGLSurface * +_eglLookupSurface(EGLSurface surf); + + +/** + * Return true if the surface is linked to a display. + */ +static INLINE EGLBoolean +_eglIsSurfaceLinked(_EGLSurface *surf) +{ + return (EGLBoolean) (_eglGetSurfaceHandle(surf) != EGL_NO_SURFACE); +} + #endif /* EGLDISPLAY_INCLUDED */ diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index 43b1f519034..f2a864cd8a7 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -284,9 +284,7 @@ _eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy) _eglLog(_EGL_DEBUG, "Closing %s", drv->Name); - /* - * XXX check for currently bound context/surfaces and delete them? - */ + _eglReleaseDisplayResources(drv, dpy); b = drv->API.Terminate(drv, dpy); diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index b770e55dbdf..55de394ef5f 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -1,6 +1,6 @@ -#include <stdio.h> #include <stdlib.h> #include "eglglobals.h" +#include "egllog.h" struct _egl_global _eglGlobal = { @@ -22,8 +22,8 @@ _eglInitGlobals(void) _eglGlobal.ClientAPIsMask = 0x0; - /* XXX temporary */ - _eglGlobal.ThreadInfo = _eglNewThreadInfo(); + if (!_eglInitCurrent()) + _eglLog(_EGL_FATAL, "failed to initialize \"current\" system"); } } @@ -34,113 +34,8 @@ _eglInitGlobals(void) void _eglDestroyGlobals(void) { + _eglFiniCurrent(); /* XXX TODO walk over table entries, deleting each */ _eglDeleteHashTable(_eglGlobal.Displays); _eglDeleteHashTable(_eglGlobal.Surfaces); } - - -/** - * Allocate and init a new _EGLThreadInfo object. - */ -_EGLThreadInfo * -_eglNewThreadInfo(void) -{ - _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo)); - if (t) { - t->CurrentContext = EGL_NO_CONTEXT; - t->LastError = EGL_SUCCESS; - t->CurrentAPI = EGL_OPENGL_ES_API; /* default, per EGL spec */ - } - return t; -} - - -/** - * Delete/free a _EGLThreadInfo object. - */ -void -_eglDeleteThreadData(_EGLThreadInfo *t) -{ - free(t); -} - - - -/** - * Return pointer to calling thread's _EGLThreadInfo object. - * Create a new one if needed. - * Should never return NULL. - */ -_EGLThreadInfo * -_eglGetCurrentThread(void) -{ - _eglInitGlobals(); - - /* XXX temporary */ - return _eglGlobal.ThreadInfo; -} - - -/** - * Record EGL error code. - */ -void -_eglError(EGLint errCode, const char *msg) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - const char *s; - - if (t->LastError == EGL_SUCCESS) { - t->LastError = errCode; - - switch (errCode) { - case EGL_BAD_ACCESS: - s = "EGL_BAD_ACCESS"; - break; - case EGL_BAD_ALLOC: - s = "EGL_BAD_ALLOC"; - break; - case EGL_BAD_ATTRIBUTE: - s = "EGL_BAD_ATTRIBUTE"; - break; - case EGL_BAD_CONFIG: - s = "EGL_BAD_CONFIG"; - break; - case EGL_BAD_CONTEXT: - s = "EGL_BAD_CONTEXT"; - break; - case EGL_BAD_CURRENT_SURFACE: - s = "EGL_BAD_CURRENT_SURFACE"; - break; - case EGL_BAD_DISPLAY: - s = "EGL_BAD_DISPLAY"; - break; - case EGL_BAD_MATCH: - s = "EGL_BAD_MATCH"; - break; - case EGL_BAD_NATIVE_PIXMAP: - s = "EGL_BAD_NATIVE_PIXMAP"; - break; - case EGL_BAD_NATIVE_WINDOW: - s = "EGL_BAD_NATIVE_WINDOW"; - break; - case EGL_BAD_PARAMETER: - s = "EGL_BAD_PARAMETER"; - break; - case EGL_BAD_SURFACE: - s = "EGL_BAD_SURFACE"; - break; - case EGL_BAD_SCREEN_MESA: - s = "EGL_BAD_SCREEN_MESA"; - break; - case EGL_BAD_MODE_MESA: - s = "EGL_BAD_MODE_MESA"; - break; - default: - s = "other"; - } - /* XXX temporary */ - fprintf(stderr, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg); - } -} diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index 14d8ea487af..a9443cfbdd8 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -3,17 +3,7 @@ #include "egltypedefs.h" #include "eglhash.h" - - -/** - * Per-thread info - */ -struct _egl_thread_info -{ - EGLint LastError; - _EGLContext *CurrentContext; - EGLenum CurrentAPI; -}; +#include "eglcurrent.h" /** @@ -23,6 +13,7 @@ struct _egl_global { EGLBoolean Initialized; + /* these are private to egldisplay.c */ _EGLHashtable *Displays; _EGLHashtable *Surfaces; @@ -33,9 +24,6 @@ struct _egl_global char ClientAPIs[1000]; /**< updated by eglQueryString */ - /* XXX temporary - should be thread-specific data (TSD) */ - _EGLThreadInfo *ThreadInfo; - EGLint NumDrivers; _EGLDriver *Drivers[10]; }; @@ -52,20 +40,4 @@ extern void _eglDestroyGlobals(void); -extern _EGLThreadInfo * -_eglNewThreadInfo(void); - - -extern void -_eglDeleteThreadData(_EGLThreadInfo *t); - - -extern _EGLThreadInfo * -_eglGetCurrentThread(void); - - -extern void -_eglError(EGLint errCode, const char *msg); - - #endif /* EGLGLOBALS_INCLUDED */ diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c index 9c9a8377bf2..b6bde65e8b5 100644 --- a/src/egl/main/eglscreen.c +++ b/src/egl/main/eglscreen.c @@ -128,20 +128,25 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, { #if 0 /* THIS IS JUST EXAMPLE CODE */ _EGLSurface *surf; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreateScreenSurfaceMESA"); + return EGL_NO_SURFACE; + } surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA, - config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_SCREEN_BIT_MESA, + conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } - _eglSaveSurface(surf); - - return surf->Handle; + return _eglLinkSurface(surf, _eglLookupDisplay(dpy)); #endif return EGL_NO_SURFACE; } diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 6905acac50b..9821e636287 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -6,6 +6,7 @@ #include <assert.h> #include <stdlib.h> #include <string.h> +#include "egldisplay.h" #include "eglcontext.h" #include "eglconfig.h" #include "egldriver.h" @@ -20,12 +21,10 @@ * \return EGL_TRUE if no errors, EGL_FALSE otherwise. */ EGLBoolean -_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, - _EGLSurface *surf, EGLint type, EGLConfig config, - const EGLint *attrib_list) +_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, + _EGLConfig *conf, const EGLint *attrib_list) { const char *func; - _EGLConfig *conf; EGLint width = 0, height = 0, largest = 0; EGLint texFormat = 0, texTarget = 0, mipmapTex = 0; EGLint renderBuffer = EGL_BACK_BUFFER; @@ -55,7 +54,6 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, return EGL_FALSE; } - conf = _eglLookupConfig(drv, dpy, config); if (!conf) { _eglError(EGL_BAD_CONFIG, func); return EGL_FALSE; @@ -211,72 +209,6 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, } -void -_eglSaveSurface(_EGLSurface *surf) -{ - EGLuint key = _eglHashGenKey(_eglGlobal.Surfaces); - assert(surf); - assert(!surf->Handle); - surf->Handle = (EGLSurface) key; - assert(surf->Handle); - _eglHashInsert(_eglGlobal.Surfaces, key, surf); -} - - -void -_eglRemoveSurface(_EGLSurface *surf) -{ - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle); -} - - - -/** - * Return the public handle for an internal _EGLSurface. - * This is the inverse of _eglLookupSurface(). - */ -EGLSurface -_eglGetSurfaceHandle(_EGLSurface *surface) -{ - if (surface) - return surface->Handle; - else - return EGL_NO_SURFACE; -} - - -/** - * Return the private _EGLSurface which corresponds to a public EGLSurface - * handle. - * This is the inverse of _eglGetSurfaceHandle(). - */ -_EGLSurface * -_eglLookupSurface(EGLSurface surf) -{ - _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, - (EGLuint) surf); - return c; -} - - -_EGLSurface * -_eglGetCurrentSurface(EGLint readdraw) -{ - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) { - switch (readdraw) { - case EGL_DRAW: - return ctx->DrawSurface; - case EGL_READ: - return ctx->ReadSurface; - default: - return NULL; - } - } - return NULL; -} - - EGLBoolean _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) { @@ -385,19 +317,24 @@ _eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, { #if 0 /* THIS IS JUST EXAMPLE CODE */ _EGLSurface *surf; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreateWindowSurface"); + return EGL_NO_SURFACE; + } surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_WINDOW_BIT, conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } - _eglSaveSurface(surf); - - return surf->Handle; + return _eglLinkSurface(surf, _eglLookupDisplay(dpy)); #endif return EGL_NO_SURFACE; } @@ -412,19 +349,24 @@ _eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, { #if 0 /* THIS IS JUST EXAMPLE CODE */ _EGLSurface *surf; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface"); + return EGL_NO_SURFACE; + } surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_PIXMAP_BIT, conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } - _eglSaveSurface(surf); - - return surf->Handle; + return _eglLinkSurface(surf, _eglLookupDisplay(dpy)); #endif return EGL_NO_SURFACE; } @@ -439,19 +381,24 @@ _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, { #if 0 /* THIS IS JUST EXAMPLE CODE */ _EGLSurface *surf; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + if (!conf) { + _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface"); + return EGL_NO_SURFACE; + } surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) return EGL_NO_SURFACE; - if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_PBUFFER_BIT, conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } - _eglSaveSurface(surf); - - return surf->Handle; + return _eglLinkSurface(surf, _eglLookupDisplay(dpy)); #endif return EGL_NO_SURFACE; } @@ -465,13 +412,9 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { _EGLSurface *surf = _eglLookupSurface(surface); if (surf) { - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); - if (surf->IsBound) { - surf->DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(surf); + if (!surf->IsBound) free(surf); - } return EGL_TRUE; } else { diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index 50f965b5cb7..f9413eb9d75 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -10,12 +10,15 @@ */ struct _egl_surface { - EGLSurface Handle; /* The public/opaque handle which names this object */ + /* Managed by EGLDisplay for linking */ + _EGLDisplay *Display; + _EGLSurface *Next; + EGLSurface Handle; + _EGLConfig *Config; /* May need reference counting here */ EGLBoolean IsBound; - EGLBoolean DeletePending; EGLBoolean BoundToTexture; EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */ @@ -39,29 +42,8 @@ struct _egl_surface extern EGLBoolean -_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, - _EGLSurface *surf, EGLint type, EGLConfig config, - const EGLint *attrib_list); - - -extern void -_eglSaveSurface(_EGLSurface *surf); - - -extern void -_eglRemoveSurface(_EGLSurface *surf); - - -extern EGLSurface -_eglGetSurfaceHandle(_EGLSurface *surface); - - -extern _EGLSurface * -_eglLookupSurface(EGLSurface surf); - - -extern _EGLSurface * -_eglGetCurrentSurface(EGLint readdraw); +_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, + _EGLConfig *config, const EGLint *attrib_list); extern EGLBoolean diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h index 9fbc55352c2..0a770dec0cb 100644 --- a/src/egl/main/egltypedefs.h +++ b/src/egl/main/egltypedefs.h @@ -6,6 +6,7 @@ #include <EGL/egl.h> #include <EGL/eglext.h> +#include "eglcompiler.h" typedef struct _egl_api _EGLAPI; diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 81e4eae401c..41fcb16a0a5 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -44,7 +44,6 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "tgsi/tgsi_exec.h" #include "tgsi/tgsi_scan.h" @@ -55,6 +54,8 @@ struct draw_vertex_shader; struct draw_context; struct draw_stage; struct vbuf_render; +struct tgsi_exec_machine; +struct tgsi_sampler; /** @@ -185,7 +186,7 @@ struct draw_context uint position_output; /** TGSI program interpreter runtime state */ - struct tgsi_exec_machine machine; + struct tgsi_exec_machine *machine; uint num_samplers; struct tgsi_sampler **samplers; diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c index c057cd67fde..790e89ed820 100644 --- a/src/gallium/auxiliary/draw/draw_vs.c +++ b/src/gallium/auxiliary/draw/draw_vs.c @@ -43,6 +43,8 @@ #include "translate/translate.h" #include "translate/translate_cache.h" +#include "tgsi/tgsi_exec.h" + @@ -146,16 +148,8 @@ draw_delete_vertex_shader(struct draw_context *draw, boolean draw_vs_init( struct draw_context *draw ) { - tgsi_exec_machine_init(&draw->vs.machine); - - /* FIXME: give this machine thing a proper constructor: - */ - draw->vs.machine.Inputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); - if (!draw->vs.machine.Inputs) - return FALSE; - - draw->vs.machine.Outputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); - if (!draw->vs.machine.Outputs) + draw->vs.machine = tgsi_exec_machine_create(); + if (!draw->vs.machine) return FALSE; draw->vs.emit_cache = translate_cache_create(); @@ -178,12 +172,6 @@ draw_vs_init( struct draw_context *draw ) void draw_vs_destroy( struct draw_context *draw ) { - if (draw->vs.machine.Inputs) - align_free(draw->vs.machine.Inputs); - - if (draw->vs.machine.Outputs) - align_free(draw->vs.machine.Outputs); - if (draw->vs.fetch_cache) translate_cache_destroy(draw->vs.fetch_cache); @@ -196,8 +184,7 @@ draw_vs_destroy( struct draw_context *draw ) if (draw->vs.aligned_constant_storage) align_free((void*)draw->vs.aligned_constant_storage); - tgsi_exec_machine_free_data(&draw->vs.machine); - + tgsi_exec_machine_destroy(draw->vs.machine); } diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index f2368dde5c2..41cc8026131 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -41,6 +41,7 @@ #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_scan.h" +#include "tgsi/tgsi_exec.h" struct exec_vertex_shader { @@ -201,7 +202,7 @@ draw_create_vs_exec(struct draw_context *draw, vs->base.run_linear = vs_exec_run_linear; vs->base.delete = vs_exec_delete; vs->base.create_varient = draw_vs_varient_generic; - vs->machine = &draw->vs.machine; + vs->machine = draw->vs.machine; return &vs->base; } diff --git a/src/gallium/auxiliary/draw/draw_vs_ppc.c b/src/gallium/auxiliary/draw/draw_vs_ppc.c index d35db57d571..ad184bd696d 100644 --- a/src/gallium/auxiliary/draw/draw_vs_ppc.c +++ b/src/gallium/auxiliary/draw/draw_vs_ppc.c @@ -48,6 +48,7 @@ #include "rtasm/rtasm_ppc.h" #include "tgsi/tgsi_ppc.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_exec.h" diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index 77ba5152f9f..fb58983e011 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -48,27 +48,16 @@ #include "rtasm/rtasm_x86sse.h" #include "tgsi/tgsi_sse2.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_exec.h" #define SSE_MAX_VERTICES 4 -typedef void (PIPE_CDECL *codegen_function) ( - const struct tgsi_exec_vector *input, /* 1 */ - struct tgsi_exec_vector *output, /* 2 */ - float (*constant)[4], /* 3 */ - struct tgsi_exec_vector *temporary, /* 4 */ - float (*immediates)[4], /* 5 */ - const float (*aos_input)[4], /* 6 */ - uint num_inputs, /* 7 */ - uint input_stride, /* 8 */ - float (*aos_output)[4], /* 9 */ - uint num_outputs, /* 10 */ - uint output_stride ); /* 11 */ struct draw_sse_vertex_shader { struct draw_vertex_shader base; struct x86_function sse2_program; - codegen_function func; + tgsi_sse2_vs_func func; struct tgsi_exec_machine *machine; }; @@ -118,11 +107,9 @@ vs_sse_run_linear( struct draw_vertex_shader *base, /* run compiled shader */ - shader->func(machine->Inputs, - machine->Outputs, - (float (*)[4])constants, - machine->Temps, - (float (*)[4])shader->base.immediates, + shader->func(machine, + constants, + shader->base.immediates, input, base->info.num_inputs, input_stride, @@ -184,7 +171,7 @@ draw_create_vs_sse(struct draw_context *draw, vs->base.immediates = align_malloc(TGSI_EXEC_NUM_IMMEDIATES * 4 * sizeof(float), 16); - vs->machine = &draw->vs.machine; + vs->machine = draw->vs.machine; x86_init_func( &vs->sse2_program ); @@ -194,7 +181,7 @@ draw_create_vs_sse(struct draw_context *draw, TRUE )) goto fail; - vs->func = (codegen_function) x86_get_func( &vs->sse2_program ); + vs->func = (tgsi_sse2_vs_func) x86_get_func( &vs->sse2_program ); if (!vs->func) { goto fail; } diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c index 57fcf6de2ab..1acf3c373eb 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -993,6 +993,15 @@ void sse_pmovmskb( struct x86_function *p, emit_modrm(p, dst, src); } +void sse_movmskps( struct x86_function *p, + struct x86_reg dst, + struct x86_reg src) +{ + DUMP_RR( dst, src ); + emit_2ub(p, X86_TWOB, 0x50); + emit_modrm(p, dst, src); +} + /*********************************************************************** * SSE2 instructions */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h index 1b5eaaca850..731a6517968 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h @@ -223,6 +223,7 @@ void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg sr void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src ); void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movmskps( struct x86_function *p, struct x86_reg dst, struct x86_reg src); void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void x86_and( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 5cb322a5fa2..fe571a86bca 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -365,15 +365,26 @@ tgsi_exec_machine_bind_shader( } -void -tgsi_exec_machine_init( - struct tgsi_exec_machine *mach ) +struct tgsi_exec_machine * +tgsi_exec_machine_create( void ) { + struct tgsi_exec_machine *mach; uint i; - mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps); + mach = align_malloc( sizeof *mach, 16 ); + if (!mach) + goto fail; + mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR]; + mach->Samplers = NULL; + mach->Consts = NULL; + mach->Tokens = NULL; + mach->Primitives = NULL; + mach->InterpCoefs = NULL; + mach->Instructions = NULL; + mach->Declarations = NULL; + /* Setup constants. */ for( i = 0; i < 4; i++ ) { mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].u[i] = 0x00000000; @@ -393,22 +404,24 @@ tgsi_exec_machine_init( (void) print_chan; (void) print_temp; #endif + + return mach; + +fail: + align_free(mach); + return NULL; } void -tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach) +tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach) { - if (mach->Instructions) { + if (mach) { FREE(mach->Instructions); - mach->Instructions = NULL; - mach->NumInstructions = 0; - } - if (mach->Declarations) { FREE(mach->Declarations); - mach->Declarations = NULL; - mach->NumDeclarations = 0; } + + align_free(mach); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index da22baad3ef..8a9100f4c3e 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -29,6 +29,7 @@ #define TGSI_EXEC_H #include "pipe/p_compiler.h" +#include "pipe/p_state.h" #if defined __cplusplus extern "C" { @@ -94,7 +95,6 @@ struct tgsi_exec_labels #define TGSI_EXEC_NUM_TEMPS 128 -#define TGSI_EXEC_NUM_TEMP_EXTRAS 6 #define TGSI_EXEC_NUM_IMMEDIATES 256 /* @@ -162,9 +162,14 @@ struct tgsi_exec_labels #define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3) #define TGSI_EXEC_MASK_C 2 +/* 4 register buffer for various purposes */ #define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4) +#define TGSI_EXEC_NUM_TEMP_R 4 + +#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8) +#define TGSI_EXEC_NUM_ADDRS 1 +#define TGSI_EXEC_NUM_TEMP_EXTRAS 9 -#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 5) #define TGSI_EXEC_MAX_COND_NESTING 20 @@ -187,24 +192,21 @@ struct tgsi_exec_labels struct tgsi_exec_machine { /* Total = program temporaries + internal temporaries - * + 1 padding to align to 16 bytes */ - struct tgsi_exec_vector _Temps[TGSI_EXEC_NUM_TEMPS + - TGSI_EXEC_NUM_TEMP_EXTRAS + 1]; + struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS + + TGSI_EXEC_NUM_TEMP_EXTRAS]; + + float Imms[TGSI_EXEC_NUM_IMMEDIATES][4]; + + struct tgsi_exec_vector Inputs[PIPE_MAX_ATTRIBS]; + struct tgsi_exec_vector Outputs[PIPE_MAX_ATTRIBS]; - /* - * This will point to _Temps after aligning to 16B boundary. - */ - struct tgsi_exec_vector *Temps; struct tgsi_exec_vector *Addrs; struct tgsi_sampler **Samplers; - float Imms[TGSI_EXEC_NUM_IMMEDIATES][4]; unsigned ImmLimit; const float (*Consts)[4]; - struct tgsi_exec_vector *Inputs; - struct tgsi_exec_vector *Outputs; const struct tgsi_token *Tokens; /**< Declarations, instructions */ unsigned Processor; /**< TGSI_PROCESSOR_x */ @@ -251,9 +253,11 @@ struct tgsi_exec_machine struct tgsi_exec_labels Labels; }; +struct tgsi_exec_machine * +tgsi_exec_machine_create( void ); + void -tgsi_exec_machine_init( - struct tgsi_exec_machine *mach ); +tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach); void @@ -268,10 +272,6 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach ); -void -tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach); - - static INLINE void tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index ba2bfdef062..df49638d512 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -32,6 +32,7 @@ #include "util/u_debug.h" #include "pipe/p_shader_tokens.h" #include "util/u_math.h" +#include "util/u_memory.h" #if defined(PIPE_ARCH_SSE) #include "util/u_sse.h" #endif @@ -100,37 +101,55 @@ get_const_base( void ) { return x86_make_reg( file_REG32, - reg_CX ); + reg_AX ); } static struct x86_reg -get_input_base( void ) +get_machine_base( void ) { return x86_make_reg( file_REG32, - reg_AX ); + reg_CX ); +} + +static struct x86_reg +get_input_base( void ) +{ + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, Inputs) ); } static struct x86_reg get_output_base( void ) { - return x86_make_reg( - file_REG32, - reg_DX ); + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, Outputs) ); } static struct x86_reg get_temp_base( void ) { + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, Temps) ); +} + +static struct x86_reg +get_coef_base( void ) +{ return x86_make_reg( file_REG32, reg_BX ); } static struct x86_reg -get_coef_base( void ) +get_sampler_base( void ) { - return get_output_base(); + return x86_make_reg( + file_REG32, + reg_DI ); } static struct x86_reg @@ -138,7 +157,7 @@ get_immediate_base( void ) { return x86_make_reg( file_REG32, - reg_DI ); + reg_DX ); } @@ -168,6 +187,15 @@ get_const( } static struct x86_reg +get_sampler_ptr( + unsigned unit ) +{ + return x86_make_disp( + get_sampler_base(), + unit * sizeof( struct tgsi_sampler * ) ); +} + +static struct x86_reg get_input( unsigned vec, unsigned chan ) @@ -520,24 +548,15 @@ emit_coef_dady( * that the stack pointer is 16 byte aligned, as expected. */ static void -emit_func_call_dst( +emit_func_call( struct x86_function *func, - unsigned xmm_save, - unsigned xmm_dst, + unsigned xmm_save_mask, + const struct x86_reg *arg, + unsigned nr_args, void (PIPE_CDECL *code)() ) { struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX ); unsigned i, n; - unsigned xmm_mask; - - /* Bitmask of the xmm registers to save */ - xmm_mask = (1 << xmm_save) - 1; - xmm_mask &= ~(1 << xmm_dst); - - sse_movaps( - func, - get_temp( TEMP_R0, 0 ), - make_xmm( xmm_dst ) ); x86_push( func, @@ -549,8 +568,10 @@ emit_func_call_dst( func, x86_make_reg( file_REG32, reg_DX) ); + /* Store XMM regs to the stack + */ for(i = 0, n = 0; i < 8; ++i) - if(xmm_mask & (1 << i)) + if(xmm_save_mask & (1 << i)) ++n; x86_sub_imm( @@ -559,26 +580,42 @@ emit_func_call_dst( n*16); for(i = 0, n = 0; i < 8; ++i) - if(xmm_mask & (1 << i)) { + if(xmm_save_mask & (1 << i)) { sse_movups( func, x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ), make_xmm( i ) ); ++n; } + + for (i = 0; i < nr_args; i++) { + /* Load the address of the buffer we use for passing arguments and + * receiving results: + */ + x86_lea( + func, + ecx, + arg[i] ); - x86_lea( - func, - ecx, - get_temp( TEMP_R0, 0 ) ); - - x86_push( func, ecx ); + /* Push actual function arguments (currently just the pointer to + * the buffer above), and call the function: + */ + x86_push( func, ecx ); + } + x86_mov_reg_imm( func, ecx, (unsigned long) code ); x86_call( func, ecx ); - x86_pop(func, ecx ); - + + /* Pop the arguments (or just add an immediate to esp) + */ + for (i = 0; i < nr_args; i++) { + x86_pop(func, ecx ); + } + + /* Pop the saved XMM regs: + */ for(i = 0, n = 0; i < 8; ++i) - if(xmm_mask & (1 << i)) { + if(xmm_save_mask & (1 << i)) { sse_movups( func, make_xmm( i ), @@ -602,34 +639,86 @@ emit_func_call_dst( x86_pop( func, x86_make_reg( file_REG32, reg_AX) ); +} + +static void +emit_func_call_dst_src1( + struct x86_function *func, + unsigned xmm_save, + unsigned xmm_dst, + unsigned xmm_src0, + void (PIPE_CDECL *code)() ) +{ + struct x86_reg store = get_temp( TEMP_R0, 0 ); + unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst); + + /* Store our input parameters (in xmm regs) to the buffer we use + * for passing arguments. We will pass a pointer to this buffer as + * the actual function argument. + */ + sse_movaps( + func, + store, + make_xmm( xmm_src0 ) ); + + emit_func_call( func, + xmm_mask, + &store, + 1, + code ); sse_movaps( func, make_xmm( xmm_dst ), - get_temp( TEMP_R0, 0 ) ); + store ); } + static void -emit_func_call_dst_src( +emit_func_call_dst_src2( struct x86_function *func, unsigned xmm_save, unsigned xmm_dst, - unsigned xmm_src, + unsigned xmm_src0, + unsigned xmm_src1, void (PIPE_CDECL *code)() ) { + struct x86_reg store = get_temp( TEMP_R0, 0 ); + unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst); + + /* Store two inputs to parameter buffer. + */ sse_movaps( func, - get_temp( TEMP_R0, 1 ), - make_xmm( xmm_src ) ); + store, + make_xmm( xmm_src0 ) ); - emit_func_call_dst( + sse_movaps( func, - xmm_save, - xmm_dst, - code ); + x86_make_disp( store, 4 * sizeof(float) ), + make_xmm( xmm_src1 ) ); + + + /* Emit the call + */ + emit_func_call( func, + xmm_mask, + &store, + 1, + code ); + + /* Retrieve the results: + */ + sse_movaps( + func, + make_xmm( xmm_dst ), + store ); } + + + #if defined(PIPE_ARCH_SSE) /* @@ -782,10 +871,11 @@ emit_cos( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, cos4f ); } @@ -812,10 +902,11 @@ emit_ex2( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, ex24f ); } @@ -857,10 +948,11 @@ emit_flr( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, flr4f ); } @@ -880,10 +972,11 @@ emit_frc( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, frc4f ); } @@ -910,10 +1003,11 @@ emit_lg2( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, lg24f ); } @@ -975,13 +1069,15 @@ emit_pow( struct x86_function *func, unsigned xmm_save, unsigned xmm_dst, - unsigned xmm_src ) + unsigned xmm_src0, + unsigned xmm_src1 ) { - emit_func_call_dst_src( + emit_func_call_dst_src2( func, xmm_save, xmm_dst, - xmm_src, + xmm_src0, + xmm_src1, pow4f ); } @@ -1017,10 +1113,11 @@ emit_rnd( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, rnd4f ); } @@ -1099,10 +1196,11 @@ emit_sgn( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, sgn4f ); } @@ -1121,10 +1219,11 @@ emit_sin (struct x86_function *func, unsigned xmm_save, unsigned xmm_dst) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, sin4f ); } @@ -1140,6 +1239,12 @@ emit_sub( make_xmm( xmm_src ) ); } + + + + + + /** * Register fetch. */ @@ -1298,20 +1403,164 @@ emit_store( #define STORE( FUNC, INST, XMM, INDEX, CHAN )\ emit_store( FUNC, XMM, &(INST).FullDstRegisters[INDEX], &(INST), CHAN ) + +static void PIPE_CDECL +fetch_texel( struct tgsi_sampler **sampler, + float *store ) +{ +#if 0 + uint j; + + debug_printf("%s sampler: %p (%p) store: %p\n", + __FUNCTION__, + sampler, *sampler, + store ); + + debug_printf("lodbias %f\n", store[12]); + + for (j = 0; j < 4; j++) + debug_printf("sample %d texcoord %f %f\n", + j, + store[0+j], + store[4+j]); +#endif + + { + float rgba[NUM_CHANNELS][QUAD_SIZE]; + (*sampler)->get_samples(*sampler, + &store[0], + &store[4], + &store[8], + 0.0f, /*store[12], lodbias */ + rgba); + + memcpy( store, rgba, 16 * sizeof(float)); + } + +#if 0 + for (j = 0; j < 4; j++) + debug_printf("sample %d result %f %f %f %f\n", + j, + store[0+j], + store[4+j], + store[8+j], + store[12+j]); +#endif +} + /** * High-level instruction translators. */ static void +emit_tex( struct x86_function *func, + const struct tgsi_full_instruction *inst, + boolean lodbias, + boolean projected) +{ + const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index; + struct x86_reg args[2]; + unsigned count; + unsigned i; + + switch (inst->InstructionExtTexture.Texture) { + case TGSI_TEXTURE_1D: + case TGSI_TEXTURE_SHADOW1D: + count = 1; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + count = 2; + break; + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + count = 3; + break; + default: + assert(0); + return; + } + + if (lodbias) { + FETCH( func, *inst, 3, 0, 3 ); + } + else { + emit_tempf( + func, + 3, + TGSI_EXEC_TEMP_00000000_I, + TGSI_EXEC_TEMP_00000000_C ); + + } + + /* store lodbias whether enabled or not -- fetch_texel currently + * respects it always. + */ + sse_movaps( func, + get_temp( TEMP_R0, 3 ), + make_xmm( 3 ) ); + + + if (projected) { + FETCH( func, *inst, 3, 0, 3 ); + + emit_rcp( func, 3, 3 ); + } + + for (i = 0; i < count; i++) { + FETCH( func, *inst, i, 0, i ); + + if (projected) { + sse_mulps( + func, + make_xmm( i ), + make_xmm( 3 ) ); + } + + /* Store in the argument buffer: + */ + sse_movaps( + func, + get_temp( TEMP_R0, i ), + make_xmm( i ) ); + } + + args[0] = get_temp( TEMP_R0, 0 ); + args[1] = get_sampler_ptr( unit ); + + + emit_func_call( func, + 0, + args, + Elements(args), + fetch_texel ); + + /* If all four channels are enabled, could use a pointer to + * dst[0].x instead of TEMP_R0 for store? + */ + FOR_EACH_DST0_ENABLED_CHANNEL( *inst, i ) { + + sse_movaps( + func, + make_xmm( 0 ), + get_temp( TEMP_R0, i ) ); + + STORE( func, *inst, 0, 0, i ); + } +} + + +static void emit_kil( struct x86_function *func, const struct tgsi_full_src_register *reg ) { unsigned uniquemask; - unsigned registers[4]; - unsigned nextregister = 0; - unsigned firstchan = ~0; + unsigned unique_count = 0; unsigned chan_index; + unsigned i; /* This mask stores component bits that were already tested. Note that * we test if the value is less than zero, so 1.0 and 0.0 need not to be @@ -1331,18 +1580,11 @@ emit_kil( uniquemask |= 1 << swizzle; /* allocate register */ - registers[chan_index] = nextregister; emit_fetch( func, - nextregister, + unique_count++, reg, chan_index ); - nextregister++; - - /* mark the first channel used */ - if( firstchan == ~0 ) { - firstchan = chan_index; - } } } @@ -1353,32 +1595,32 @@ emit_kil( func, x86_make_reg( file_REG32, reg_DX ) ); - FOR_EACH_CHANNEL( chan_index ) { - if( uniquemask & (1 << chan_index) ) { - sse_cmpps( + for (i = 0 ; i < unique_count; i++ ) { + struct x86_reg dataXMM = make_xmm(i); + + sse_cmpps( + func, + dataXMM, + get_temp( + TGSI_EXEC_TEMP_00000000_I, + TGSI_EXEC_TEMP_00000000_C ), + cc_LessThan ); + + if( i == 0 ) { + sse_movmskps( func, - make_xmm( registers[chan_index] ), - get_temp( - TGSI_EXEC_TEMP_00000000_I, - TGSI_EXEC_TEMP_00000000_C ), - cc_LessThan ); - - if( chan_index == firstchan ) { - sse_pmovmskb( - func, - x86_make_reg( file_REG32, reg_AX ), - make_xmm( registers[chan_index] ) ); - } - else { - sse_pmovmskb( - func, - x86_make_reg( file_REG32, reg_DX ), - make_xmm( registers[chan_index] ) ); - x86_or( - func, - x86_make_reg( file_REG32, reg_AX ), - x86_make_reg( file_REG32, reg_DX ) ); - } + x86_make_reg( file_REG32, reg_AX ), + dataXMM ); + } + else { + sse_movmskps( + func, + x86_make_reg( file_REG32, reg_DX ), + dataXMM ); + x86_or( + func, + x86_make_reg( file_REG32, reg_AX ), + x86_make_reg( file_REG32, reg_DX ) ); } } @@ -1573,7 +1815,7 @@ emit_instruction( get_temp( TGSI_EXEC_TEMP_MINUS_128_I, TGSI_EXEC_TEMP_MINUS_128_C ) ); - emit_pow( func, 3, 1, 2 ); + emit_pow( func, 3, 1, 1, 2 ); FETCH( func, *inst, 0, 0, CHAN_X ); sse_xorps( func, @@ -1917,7 +2159,7 @@ emit_instruction( /* TGSI_OPCODE_POW */ FETCH( func, *inst, 0, 0, CHAN_X ); FETCH( func, *inst, 1, 1, CHAN_X ); - emit_pow( func, 0, 0, 1 ); + emit_pow( func, 0, 0, 0, 1 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } @@ -2086,21 +2328,7 @@ emit_instruction( break; case TGSI_OPCODE_TEX: - if (0) { - /* Disable dummy texture code: - */ - emit_tempf( - func, - 0, - TEMP_ONE_I, - TEMP_ONE_C ); - FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { - STORE( func, *inst, 0, 0, chan_index ); - } - } - else { - return 0; - } + emit_tex( func, inst, FALSE, FALSE ); break; case TGSI_OPCODE_TXD: @@ -2198,7 +2426,7 @@ emit_instruction( break; case TGSI_OPCODE_TXB: - return 0; + emit_tex( func, inst, TRUE, FALSE ); break; case TGSI_OPCODE_NRM: @@ -2306,9 +2534,13 @@ emit_instruction( break; case TGSI_OPCODE_TXL: - return 0; + emit_tex( func, inst, TRUE, FALSE ); break; + case TGSI_OPCODE_TXP: + emit_tex( func, inst, FALSE, TRUE ); + break; + case TGSI_OPCODE_BRK: return 0; break; @@ -2488,7 +2720,7 @@ emit_declaration( static void aos_to_soa( struct x86_function *func, uint arg_aos, - uint arg_soa, + uint arg_machine, uint arg_num, uint arg_stride ) { @@ -2503,7 +2735,10 @@ static void aos_to_soa( struct x86_function *func, x86_push( func, x86_make_reg( file_REG32, reg_BX ) ); x86_mov( func, aos_input, x86_fn_arg( func, arg_aos ) ); - x86_mov( func, soa_input, x86_fn_arg( func, arg_soa ) ); + x86_mov( func, soa_input, x86_fn_arg( func, arg_machine ) ); + x86_lea( func, soa_input, + x86_make_disp( soa_input, + Offset(struct tgsi_exec_machine, Inputs) ) ); x86_mov( func, num_inputs, x86_fn_arg( func, arg_num ) ); x86_mov( func, stride, x86_fn_arg( func, arg_stride ) ); @@ -2545,28 +2780,30 @@ static void aos_to_soa( struct x86_function *func, x86_jcc( func, cc_NE, inner_loop ); /* Restore EBX */ - x86_pop( func, aos_input ); + x86_pop( func, x86_make_reg( file_REG32, reg_BX ) ); } -static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, uint stride ) +static void soa_to_aos( struct x86_function *func, + uint arg_aos, + uint arg_machine, + uint arg_num, + uint arg_stride ) { - struct x86_reg soa_output; - struct x86_reg aos_output; - struct x86_reg num_outputs; - struct x86_reg temp; + struct x86_reg soa_output = x86_make_reg( file_REG32, reg_AX ); + struct x86_reg aos_output = x86_make_reg( file_REG32, reg_BX ); + struct x86_reg num_outputs = x86_make_reg( file_REG32, reg_CX ); + struct x86_reg temp = x86_make_reg( file_REG32, reg_DX ); int inner_loop; - soa_output = x86_make_reg( file_REG32, reg_AX ); - aos_output = x86_make_reg( file_REG32, reg_BX ); - num_outputs = x86_make_reg( file_REG32, reg_CX ); - temp = x86_make_reg( file_REG32, reg_DX ); - /* Save EBX */ - x86_push( func, aos_output ); + x86_push( func, x86_make_reg( file_REG32, reg_BX ) ); - x86_mov( func, soa_output, x86_fn_arg( func, soa ) ); - x86_mov( func, aos_output, x86_fn_arg( func, aos ) ); - x86_mov( func, num_outputs, x86_fn_arg( func, num ) ); + x86_mov( func, aos_output, x86_fn_arg( func, arg_aos ) ); + x86_mov( func, soa_output, x86_fn_arg( func, arg_machine ) ); + x86_lea( func, soa_output, + x86_make_disp( soa_output, + Offset(struct tgsi_exec_machine, Outputs) ) ); + x86_mov( func, num_outputs, x86_fn_arg( func, arg_num ) ); /* do */ inner_loop = x86_get_label( func ); @@ -2583,7 +2820,7 @@ static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, sse_unpcklps( func, make_xmm( 3 ), make_xmm( 4 ) ); sse_unpckhps( func, make_xmm( 5 ), make_xmm( 4 ) ); - x86_mov( func, temp, x86_fn_arg( func, stride ) ); + x86_mov( func, temp, x86_fn_arg( func, arg_stride ) ); x86_push( func, aos_output ); sse_movlps( func, x86_make_disp( aos_output, 0 ), make_xmm( 0 ) ); sse_movlps( func, x86_make_disp( aos_output, 8 ), make_xmm( 3 ) ); @@ -2607,20 +2844,13 @@ static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, x86_jcc( func, cc_NE, inner_loop ); /* Restore EBX */ - x86_pop( func, aos_output ); + x86_pop( func, x86_make_reg( file_REG32, reg_BX ) ); } /** * Translate a TGSI vertex/fragment shader to SSE2 code. * Slightly different things are done for vertex vs. fragment shaders. * - * Note that fragment shaders are responsible for interpolating shader - * inputs. Because on x86 we have only 4 GP registers, and here we - * have 5 shader arguments (input, output, const, temp and coef), the - * code is split into two phases -- DECLARATION and INSTRUCTION phase. - * GP register holding the output argument is aliased with the coeff - * argument, as outputs are not needed in the DECLARATION phase. - * * \param tokens the TGSI input shader * \param func the output SSE code/function * \param immediates buffer to place immediates, later passed to SSE func @@ -2634,7 +2864,6 @@ tgsi_emit_sse2( boolean do_swizzles ) { struct tgsi_parse_context parse; - boolean instruction_phase = FALSE; unsigned ok = 1; uint num_immediates = 0; @@ -2646,74 +2875,48 @@ tgsi_emit_sse2( /* Can't just use EDI, EBX without save/restoring them: */ - x86_push( - func, - get_immediate_base() ); - - x86_push( - func, - get_temp_base() ); - + x86_push( func, x86_make_reg( file_REG32, reg_BX ) ); + x86_push( func, x86_make_reg( file_REG32, reg_DI ) ); /* * Different function args for vertex/fragment shaders: */ - if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { - /* DECLARATION phase, do not load output argument. */ - x86_mov( - func, - get_input_base(), - x86_fn_arg( func, 1 ) ); - /* skipping outputs argument here */ - x86_mov( - func, - get_const_base(), - x86_fn_arg( func, 3 ) ); - x86_mov( - func, - get_temp_base(), - x86_fn_arg( func, 4 ) ); - x86_mov( - func, - get_coef_base(), - x86_fn_arg( func, 5 ) ); - x86_mov( - func, - get_immediate_base(), - x86_fn_arg( func, 6 ) ); - } - else { - assert(parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX); - + if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) { if (do_swizzles) aos_to_soa( func, - 6, /* aos_input */ - 1, /* machine->input */ - 7, /* num_inputs */ - 8 ); /* input_stride */ + 4, /* aos_input */ + 1, /* machine */ + 5, /* num_inputs */ + 6 ); /* input_stride */ + } + x86_mov( + func, + get_machine_base(), + x86_fn_arg( func, 1 ) ); + x86_mov( + func, + get_const_base(), + x86_fn_arg( func, 2 ) ); + x86_mov( + func, + get_immediate_base(), + x86_fn_arg( func, 3 ) ); + + if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { x86_mov( - func, - get_input_base(), - x86_fn_arg( func, 1 ) ); - x86_mov( - func, - get_output_base(), - x86_fn_arg( func, 2 ) ); - x86_mov( - func, - get_const_base(), - x86_fn_arg( func, 3 ) ); - x86_mov( - func, - get_temp_base(), - x86_fn_arg( func, 4 ) ); + func, + get_coef_base(), + x86_fn_arg( func, 4 ) ); + x86_mov( - func, - get_immediate_base(), - x86_fn_arg( func, 5 ) ); + func, + get_sampler_base(), + x86_make_disp( get_machine_base(), + Offset( struct tgsi_exec_machine, Samplers ) ) ); } + while( !tgsi_parse_end_of_tokens( &parse ) && ok ) { tgsi_parse_token( &parse ); @@ -2727,17 +2930,6 @@ tgsi_emit_sse2( break; case TGSI_TOKEN_TYPE_INSTRUCTION: - if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { - if( !instruction_phase ) { - /* INSTRUCTION phase, overwrite coeff with output. */ - instruction_phase = TRUE; - x86_mov( - func, - get_output_base(), - x86_fn_arg( func, 2 ) ); - } - } - ok = emit_instruction( func, &parse.FullToken.FullInstruction ); @@ -2781,18 +2973,17 @@ tgsi_emit_sse2( if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) { if (do_swizzles) - soa_to_aos( func, 9, 2, 10, 11 ); + soa_to_aos( func, + 7, /* aos_output */ + 1, /* machine */ + 8, /* num_outputs */ + 9 ); /* output_stride */ } /* Can't just use EBX, EDI without save/restoring them: */ - x86_pop( - func, - get_temp_base() ); - - x86_pop( - func, - get_immediate_base() ); + x86_pop( func, x86_make_reg( file_REG32, reg_DI ) ); + x86_pop( func, x86_make_reg( file_REG32, reg_BX ) ); emit_ret( func ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/tgsi_sse2.h index af838b2a25b..d81ee3d00ec 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.h +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.h @@ -34,6 +34,7 @@ extern "C" { struct tgsi_token; struct x86_function; +struct tgsi_interp_coef; unsigned tgsi_emit_sse2( @@ -42,6 +43,33 @@ tgsi_emit_sse2( float (*immediates)[4], boolean do_swizzles ); + +/* This is the function prototype generated when do_swizzles is false + * -- effectively for fragment shaders. + */ +typedef void (PIPE_CDECL *tgsi_sse2_fs_function) ( + struct tgsi_exec_machine *machine, /* 1 */ + const float (*constant)[4], /* 2 */ + const float (*immediate)[4], /* 3 */ + const struct tgsi_interp_coef *coef /* 4 */ + ); + + +/* This is the function prototype generated when do_swizzles is true + * -- effectively for vertex shaders. + */ +typedef void (PIPE_CDECL *tgsi_sse2_vs_func) ( + struct tgsi_exec_machine *machine, /* 1 */ + const float (*constant)[4], /* 2 */ + const float (*immediate)[4], /* 3 */ + const float (*aos_input)[4], /* 4 */ + uint num_inputs, /* 5 */ + uint input_stride, /* 6 */ + float (*aos_output)[4], /* 7 */ + uint num_outputs, /* 8 */ + uint output_stride ); /* 9 */ + + #if defined __cplusplus } #endif diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index 31c3ca21c51..f4fa0905d74 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -45,17 +45,6 @@ #include "rtasm/rtasm_x86sse.h" -/* Surely this should be defined somewhere in a tgsi header: - */ -typedef void (PIPE_CDECL *codegen_function)( - const struct tgsi_exec_vector *input, - struct tgsi_exec_vector *output, - const float (*constant)[4], - struct tgsi_exec_vector *temporary, - const struct tgsi_interp_coef *coef, - float (*immediates)[4] - //, const struct tgsi_exec_vector *quadPos - ); /** @@ -65,7 +54,7 @@ struct sp_sse_fragment_shader { struct sp_fragment_shader base; struct x86_function sse2_program; - codegen_function func; + tgsi_sse2_fs_function func; float immediates[TGSI_EXEC_NUM_IMMEDIATES][4]; }; @@ -83,6 +72,7 @@ fs_sse_prepare( const struct sp_fragment_shader *base, struct tgsi_exec_machine *machine, struct tgsi_sampler **samplers ) { + machine->Samplers = samplers; } @@ -107,12 +97,10 @@ fs_sse_run( const struct sp_fragment_shader *base, tgsi_set_kill_mask(machine, 0x0); tgsi_set_exec_mask(machine, 1, 1, 1, 1); - shader->func( machine->Inputs, - machine->Outputs, + shader->func( machine, machine->Consts, - machine->Temps, - machine->InterpCoefs, - shader->immediates + (const float (*)[4])shader->immediates, + machine->InterpCoefs // , &machine->QuadPos ); @@ -151,7 +139,7 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe, return NULL; } - shader->func = (codegen_function) x86_get_func( &shader->sse2_program ); + shader->func = (tgsi_sse2_fs_function) x86_get_func( &shader->sse2_program ); if (!shader->func) { x86_release_func( &shader->sse2_program ); FREE(shader); diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index ca637a1d6a4..28f8d1a60ea 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -52,7 +52,7 @@ struct quad_shade_stage { struct quad_stage stage; /**< base class */ - struct tgsi_exec_machine machine; + struct tgsi_exec_machine *machine; struct tgsi_exec_vector *inputs, *outputs; }; @@ -73,7 +73,7 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad) { struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; - struct tgsi_exec_machine *machine = &qss->machine; + struct tgsi_exec_machine *machine = qss->machine; boolean z_written; /* Consts do not require 16 byte alignment. */ @@ -146,7 +146,7 @@ shade_begin(struct quad_stage *qs) struct softpipe_context *softpipe = qs->softpipe; softpipe->fs->prepare( softpipe->fs, - &qss->machine, + qss->machine, (struct tgsi_sampler **) softpipe->tgsi.frag_samplers_list ); @@ -159,9 +159,8 @@ shade_destroy(struct quad_stage *qs) { struct quad_shade_stage *qss = (struct quad_shade_stage *) qs; - tgsi_exec_machine_free_data(&qss->machine); - FREE( qss->inputs ); - FREE( qss->outputs ); + tgsi_exec_machine_destroy(qss->machine); + FREE( qs ); } @@ -170,19 +169,24 @@ struct quad_stage * sp_quad_shade_stage( struct softpipe_context *softpipe ) { struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage); - - /* allocate storage for program inputs/outputs, aligned to 16 bytes */ - qss->inputs = MALLOC(PIPE_MAX_ATTRIBS * sizeof(*qss->inputs) + 16); - qss->outputs = MALLOC(PIPE_MAX_ATTRIBS * sizeof(*qss->outputs) + 16); - qss->machine.Inputs = align16(qss->inputs); - qss->machine.Outputs = align16(qss->outputs); + if (!qss) + goto fail; qss->stage.softpipe = softpipe; qss->stage.begin = shade_begin; qss->stage.run = shade_quad; qss->stage.destroy = shade_destroy; - tgsi_exec_machine_init( &qss->machine ); + qss->machine = tgsi_exec_machine_create(); + if (!qss->machine) + goto fail; return &qss->stage; + +fail: + if (qss && qss->machine) + tgsi_exec_machine_destroy(qss->machine); + + FREE(qss); + return NULL; } diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c index edd49486e5b..f03a29582a9 100644 --- a/src/gallium/state_trackers/egl/egl_context.c +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -113,7 +113,7 @@ drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext if (!ctx) goto err_c; - _eglInitContext(drv, dpy, &ctx->base, config, attrib_list); + _eglInitContext(drv, dpy, &ctx->base, conf, attrib_list); ctx->pipe = dev->api->create_context(dev->api, dev->screen); if (!ctx->pipe) @@ -129,8 +129,8 @@ drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext if (!ctx->st) goto err_gl; - /* generate handle and insert into hash table */ - _eglSaveContext(&ctx->base); + /* link to display */ + _eglLinkContext(&ctx->base, _eglLookupDisplay(dpy)); assert(_eglGetContextHandle(&ctx->base)); return _eglGetContextHandle(&ctx->base); @@ -147,10 +147,8 @@ EGLBoolean drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { struct drm_context *c = lookup_drm_context(context); - _eglRemoveContext(&c->base); - if (c->base.IsBound) { - c->base.DeletePending = EGL_TRUE; - } else { + _eglUnlinkContext(&c->base); + if (!c->base.IsBound) { st_destroy_context(c->st); c->pipe->destroy(c->pipe); free(c); diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c index de8194a46af..86f2ea97e54 100644 --- a/src/gallium/state_trackers/egl/egl_surface.c +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -232,7 +232,7 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!surf) goto err; - if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list)) + if (!_eglInitSurface(drv, &surf->base, EGL_PBUFFER_BIT, conf, attrib_list)) goto err_surf; surf->w = width; @@ -245,7 +245,7 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, (void*)surf); drm_visual_modes_destroy(visual); - _eglSaveSurface(&surf->base); + _eglLinkSurface(&surf->base, _eglLookupDisplay(dpy)); return surf->base.Handle; err_surf: @@ -364,10 +364,9 @@ EGLBoolean drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { struct drm_surface *surf = lookup_drm_surface(surface); - _eglRemoveSurface(&surf->base); - if (surf->base.IsBound) { - surf->base.DeletePending = EGL_TRUE; - } else { + _eglUnlinkSurface(&surf->base); + + if (!surf->base.IsBound) { if (surf->screen) drm_takedown_shown_screen(drv, surf->screen); st_unreference_framebuffer(surf->stfb); diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c index c10e3c00ffc..e1ddcae97ba 100644 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -345,7 +345,7 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_CONTEXT; /* let EGL lib init the common stuff */ - if (!_eglInitContext(drv, dpy, &ctx->Base, config, attrib_list)) { + if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) { free(ctx); return EGL_NO_CONTEXT; } @@ -370,7 +370,7 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_CONTEXT; } - _eglSaveContext(&ctx->Base); + _eglLinkContext(&ctx->Base, _eglLookupDisplay(dpy)); return _eglGetContextHandle(&ctx->Base); } @@ -381,10 +381,8 @@ xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) { struct xlib_egl_context *context = lookup_context(ctx); if (context) { - if (context->Base.IsBound) { - context->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkContext(&context->Base); + if (!context->Base.IsBound) { /* API-dependent clean-up */ switch (context->Base.ClientAPI) { case EGL_OPENGL_ES_API: @@ -491,13 +489,13 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_SURFACE; /* Let EGL lib init the common stuff */ - if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_WINDOW_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT, + conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } - _eglSaveSurface(&surf->Base); + _eglLinkSurface(&surf->Base, disp); /* * Now init the Xlib and gallium stuff @@ -534,11 +532,8 @@ xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { struct xlib_egl_surface *surf = lookup_surface(surface); if (surf) { - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); - if (surf->Base.IsBound) { - surf->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(&surf->Base); + if (!surf->Base.IsBound) { XFreeGC(surf->Dpy, surf->Gc); st_unreference_framebuffer(surf->Framebuffer); free(surf); diff --git a/src/mesa/drivers/dri/fb/fb_egl.c b/src/mesa/drivers/dri/fb/fb_egl.c index 35c268441c3..dee67feb5ac 100644 --- a/src/mesa/drivers/dri/fb/fb_egl.c +++ b/src/mesa/drivers/dri/fb/fb_egl.c @@ -472,8 +472,8 @@ fbCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext sh c->Base.DrawSurface = EGL_NO_SURFACE; c->Base.ReadSurface = EGL_NO_SURFACE; - /* generate handle and insert into hash table */ - _eglSaveContext(&c->Base); + /* link to display */ + _eglLinkContext(&c->Base, disp); assert(c->Base.Handle); /* Init default driver functions then plug in our FBdev-specific functions @@ -604,13 +604,9 @@ static EGLBoolean fbDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { fbSurface *fs = Lookup_fbSurface(surface); - _eglRemoveSurface(&fs->Base); - if (fs->Base.IsBound) { - fs->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(&fs->Base); + if (!fs->Base.IsBound) free(fs); - } return EGL_TRUE; } @@ -619,13 +615,9 @@ static EGLBoolean fbDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { fbContext *fc = Lookup_fbContext(context); - _eglRemoveContext(&fc->Base); - if (fc->Base.IsBound) { - fc->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkContext(&fc->Base); + if (!fc->Base.IsBound) free(fc); - } return EGL_TRUE; } @@ -688,7 +680,7 @@ fbCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, surface->mesa_framebuffer = _mesa_create_framebuffer(&vis); if (!surface->mesa_framebuffer) { free(surface); - _eglRemoveSurface(&surface->Base); + _eglUnlinkSurface(&surface->Base); return EGL_NO_SURFACE; } diff --git a/src/mesa/drivers/dri/i965/brw_sf_state.c b/src/mesa/drivers/dri/i965/brw_sf_state.c index e73e57a1c83..b5f6371c82c 100644 --- a/src/mesa/drivers/dri/i965/brw_sf_state.c +++ b/src/mesa/drivers/dri/i965/brw_sf_state.c @@ -246,7 +246,7 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key, else if (sf.sf6.line_width <= 0x2) sf.sf6.line_width = 0; - /* _NEW_POINT */ + /* _NEW_BUFFERS */ key->render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0; if (!key->render_to_fbo) { /* Rendering to an OpenGL window */ @@ -276,6 +276,7 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key, } /* XXX clamp max depends on AA vs. non-AA */ + /* _NEW_POINT */ sf.sf7.sprite_point = key->point_sprite; sf.sf7.point_size = CLAMP(rint(key->point_size), 1, 255) * (1<<3); sf.sf7.use_point_size_state = !key->point_attenuated; @@ -341,7 +342,8 @@ const struct brw_tracked_state brw_sf_unit = { .mesa = (_NEW_POLYGON | _NEW_LINE | _NEW_POINT | - _NEW_SCISSOR), + _NEW_SCISSOR | + _NEW_BUFFERS), .brw = BRW_NEW_URB_FENCE, .cache = (CACHE_NEW_SF_VP | CACHE_NEW_SF_PROG) diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 9ba131bee50..d8191ab5187 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -546,7 +546,7 @@ _mesa_update_state_locked( GLcontext *ctx ) /* Determine which state flags effect vertex/fragment program state */ if (ctx->FragmentProgram._MaintainTexEnvProgram) { - prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR | + prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _NEW_ARRAY | _NEW_LIGHT | _NEW_POINT | _NEW_RENDERMODE); } if (ctx->VertexProgram._MaintainTnlProgram) { diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index a3f1246c985..6b090ff399b 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -62,6 +62,18 @@ struct texenvprog_cache_item struct texenvprog_cache_item *next; }; +static GLboolean +texenv_doing_secondary_color(GLcontext *ctx) +{ + if (ctx->Light.Enabled && + (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) + return GL_TRUE; + + if (ctx->Fog.ColorSumEnabled) + return GL_TRUE; + + return GL_FALSE; +} /** * Up to nine instructions per tex unit, plus fog, specular color. @@ -298,7 +310,7 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) if (ctx->Light.Enabled) { fp_inputs |= FRAG_BIT_COL0; - if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + if (texenv_doing_secondary_color(ctx)) fp_inputs |= FRAG_BIT_COL1; } @@ -416,8 +428,8 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) } } - /* _DD_NEW_SEPARATE_SPECULAR */ - if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { + /* _NEW_LIGHT | _NEW_FOG */ + if (texenv_doing_secondary_color(ctx)) { key->separate_specular = 1; inputs_referenced |= FRAG_BIT_COL1; } diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index e4d3bb33c71..806e0ca8f65 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -151,6 +151,7 @@ st_translate_vertex_program(struct st_context *st, case VERT_ATTRIB_TEX5: case VERT_ATTRIB_TEX6: case VERT_ATTRIB_TEX7: + assert(slot < Elements(vs_input_semantic_name)); vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; vs_input_semantic_index[slot] = num_generic++; break; @@ -171,6 +172,7 @@ st_translate_vertex_program(struct st_context *st, case VERT_ATTRIB_GENERIC14: case VERT_ATTRIB_GENERIC15: assert(attr < VERT_ATTRIB_MAX); + assert(slot < Elements(vs_input_semantic_name)); vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; vs_input_semantic_index[slot] = num_generic++; break; @@ -198,6 +200,7 @@ st_translate_vertex_program(struct st_context *st, /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { + assert(i < Elements(vs_output_semantic_name)); vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; vs_output_semantic_index[i] = 0; output_flags[i] = 0x0; @@ -273,6 +276,7 @@ st_translate_vertex_program(struct st_context *st, case VERT_RESULT_VAR0: /* fall-through */ default: + assert(slot < Elements(vs_output_semantic_name)); if (outputSemanticName) { /* use provided semantic into */ assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT); @@ -286,6 +290,7 @@ st_translate_vertex_program(struct st_context *st, } } + assert(slot < Elements(output_flags)); output_flags[slot] = stvp->Base.Base.OutputFlags[attr]; } } |