mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-04 15:00:36 +01:00
Merge branch 'master' of git+ssh://agd5f@git.freedesktop.org/git/mesa/mesa into r6xx-rewrite
This commit is contained in:
commit
e910f6831b
43 changed files with 1904 additions and 847 deletions
|
|
@ -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
|
||||
|
|
|
|||
1
progs/egl/.gitignore
vendored
1
progs/egl/.gitignore
vendored
|
|
@ -7,4 +7,5 @@ eglscreen
|
|||
egltri
|
||||
peglgears
|
||||
xeglgears
|
||||
xeglthreads
|
||||
xegl_tri
|
||||
|
|
|
|||
|
|
@ -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 $@
|
||||
|
||||
|
|
|
|||
773
progs/egl/xeglthreads.c
Normal file
773
progs/egl/xeglthreads.c
Normal file
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
31
src/egl/main/eglcompiler.h
Normal file
31
src/egl/main/eglcompiler.h
Normal file
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
|
|
@ -59,66 +55,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!
|
||||
*/
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include "eglcompiler.h"
|
||||
|
||||
typedef struct _egl_api _EGLAPI;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "rtasm/rtasm_ppc.h"
|
||||
#include "tgsi/tgsi_ppc.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
#include "tgsi/tgsi_exec.h"
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -97,6 +98,14 @@ make_xmm(
|
|||
|
||||
static struct x86_reg
|
||||
get_const_base( void )
|
||||
{
|
||||
return x86_make_reg(
|
||||
file_REG32,
|
||||
reg_AX );
|
||||
}
|
||||
|
||||
static struct x86_reg
|
||||
get_machine_base( void )
|
||||
{
|
||||
return x86_make_reg(
|
||||
file_REG32,
|
||||
|
|
@ -106,21 +115,29 @@ get_const_base( void )
|
|||
static struct x86_reg
|
||||
get_input_base( void )
|
||||
{
|
||||
return x86_make_reg(
|
||||
file_REG32,
|
||||
reg_AX );
|
||||
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,
|
||||
|
|
@ -128,9 +145,11 @@ get_temp_base( void )
|
|||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -167,6 +186,15 @@ get_const(
|
|||
(vec * 4 + chan) * 4 );
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -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(
|
||||
func,
|
||||
make_xmm( registers[chan_index] ),
|
||||
get_temp(
|
||||
TGSI_EXEC_TEMP_00000000_I,
|
||||
TGSI_EXEC_TEMP_00000000_C ),
|
||||
cc_LessThan );
|
||||
for (i = 0 ; i < unique_count; i++ ) {
|
||||
struct x86_reg dataXMM = make_xmm(i);
|
||||
|
||||
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 ) );
|
||||
}
|
||||
sse_cmpps(
|
||||
func,
|
||||
dataXMM,
|
||||
get_temp(
|
||||
TGSI_EXEC_TEMP_00000000_I,
|
||||
TGSI_EXEC_TEMP_00000000_C ),
|
||||
cc_LessThan );
|
||||
|
||||
if( i == 0 ) {
|
||||
sse_movmskps(
|
||||
func,
|
||||
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_coef_base(),
|
||||
x86_fn_arg( func, 4 ) );
|
||||
|
||||
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 ) );
|
||||
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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue